20

我的任务是为一个客户开展一个项目,该客户拥有一个他估计每天将获得 1-2M 次点击的网站。他拥有一个包含 5800 万用户的现有数据库,这些用户需要在每次注册的基础上为新品牌播种。该网站的大部分内容都是由外部 API 提供的数据提供的,其中存储在我们的 Mongo 设置中的大部分数据是配置文件信息和保存的 API 参数。

NginX 将在端口 80 上,并在端口 8000 - 8010 上对节点集群进行负载平衡。

我的问题是如何处理缓存。我来自 LAMP 背景,所以我习惯于使用 PHP 编写静态 HTML 文件并提供这些文件以最小化 MySQL 负载,或者将 Memcached 用于需要更高级别缓存的站点。这个设置对我来说有点陌生。

就最小的响应时间和 CPU 负载而言,哪个是最理想的?

1:使用 NginX 进行页面级缓存

参考:http ://andytson.com/blog/2010/04/page-level-caching-with-nginx/

server {
    listen            80;
    servername        mysite.com;

    proxy_set_header  X-Real-IP  $remote_addr;
    proxy_set_header  Host       $host;

    location / {
        proxy_pass    http://localhost:8080/;
        proxy_cache   anonymous;
    }

    # don't cache admin folder, send all requests through the proxy
    location /admin {
        proxy_pass    http://localhost:8080/;
    }

    # handle static files directly. Set their expiry time to max, so they'll
    # always use the browser cache after first request
    location ~* (css|js|png|jpe?g|gif|ico)$ {
        root          /var/www/${host}/http;
        expires       max;
    }
}


2:Redis作为缓存桶

hash()函数就是numbers()这个页面的函数:http: //jsperf.com/hashing-strings

function hash(str) {
    var res = 0,
        len = str.length;
    for (var i = 0; i < len; i++) {
        res = res * 31 + str.charCodeAt(i);
    }
    return res;
}

var apiUrl = 'https://www.myexternalapi.com/rest/someparam/someotherparam/?auth=3dfssd6s98d7f09s8df98sdef';
var key    = hash(apiUrl).toString(); // 1.8006908172911553e+136

myRedisClient.set(key,theJSONresponse, function(err) {...});


3:节点写入JSON文件

hash()函数就是numbers()这个页面的函数:http: //jsperf.com/hashing-strings

function hash(str) {
    var res = 0,
        len = str.length;
    for (var i = 0; i < len; i++) {
        res = res * 31 + str.charCodeAt(i);
    }
    return res;
}

var fs     = require('fs');
var apiUrl = 'https://www.myexternalapi.com/rest/someparam/someotherparam/?auth=3dfssd6s98d7f09s8df98sdef';
var key    = hash(apiUrl).toString(); // 1.8006908172911553e+136

fs.writeFile('/var/www/_cache/' + key + '.json', theJSONresponse, function(err) {...});


4:前面清漆

我做了一些研究和基准测试,就像这个网站上显示的那样让我远离这个解决方案,但如果它最有意义,我仍然愿意考虑它:http: //todsul.com/nginx-varnish

4

3 回答 3

18

我会做一个组合,使用 Redis 缓存具有短 TTL 的会话用户 API 调用,并使用 Nginx 缓存长期 RESTless 数据和静态资产。我不会编写 JSON 文件,因为我认为文件系统 IO 将是列出的选项中最慢且 CPU 密集度最高的。

于 2013-03-21T19:29:07.583 回答
5
  1. nginx 页面级缓存适用于缓存静态内容。但对于动态内容,就不好说了。例如,如果内容在上游发生更改,如何使缓存无效?

  2. Redis 非常适合内存数据存储。但我不喜欢将它用作缓存。由于内存有限,我不得不经常担心内存不足。是的,您可以为 redis 中的过期键设置策略。但这是额外的工作,仍然不如我希望它成为缓存提供程序那么好。

没有选择 3 和 4 的经验。

我很惊讶您没有在此处包含 memcache 作为选项。根据我的经验,它作为缓存提供程序是可靠的。redis 没有的一个 memcache 特性是它不能保证一个键在你指定的过期时间之前不会过期。这对数据存储不利,但它使 memcache 成为缓存的完美候选者:您无需担心用尽分配给 memcache 的内存。memcache 将删除较少使用的键(缓存较少使用),即使这些键的到期时间尚未满足。

Nginx 提供了这个内置的memcache 模块。它很结实。如果你在网上谷歌,有很多教程。

这是我最喜欢的一个(见下面的链接)。缓存失效很容易:例如,如果一个页面在上游更新,只需从上游应用服务器中删除 memcache 键。作者声称响应时间增加了 4 倍。相信它对您的用例来说已经足够好了。

http://www.igvita.com/2008/02/11/nginx-and-memcached-a-400-boost/

于 2013-03-25T22:53:38.410 回答
1

至于清漆,我不打算破译您找到的网站上的基准,但我可以告诉您它们是非常糟糕的数字,与真正的高流量实现没有任何共同之处(谷歌进行清漆优化并查看显示 100-200k 的基准req/s 而不是 8k)。

Nginx 也是页面缓存的一个不错的选择,每天 1-2M 的点击量你不需要极端的性能。所以选择你觉得更舒服的工作。

两个节点的解决方案确实是一个更糟糕的选择。页面缓存应该与您的动态应用程序分开,以提供可靠性和性能。

此外,如果您将 redis/memcached 用作对象缓存或常用反序列化数据的缓存,redis/memcached 将最好地帮助您扩展应用程序。

于 2013-03-25T11:00:42.883 回答