哪种缓存方法是Node / Mongo / NginX最快/最轻的?

时间:2013-03-21 18:57:29

标签: node.js caching nginx redis varnish

我的任务是为一个客户开展项目,该客户有一个他估计每天会收到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

3 个答案:

答案 0 :(得分:18)

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

答案 1 :(得分:4)

  1. nginx页面级缓存适用于缓存静态内容。但对于动态内容,这并不好。例如,如果在上游更改内容,如何使缓存无效?

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

  3. 没有选择3和4的经验。

    我很惊讶你没有在这里包含memcache作为选项。根据我的经验,它作为缓存提供商是可靠的。 redis没有的一个memcache功能是它不能保证密钥在你指定的到期时间内不会过期。这对于数据存储是不利的,但它使得memcache成为缓存的理想选择:您不必担心使用分配给memcache的内存。 memcache将删除较少使用的密钥(缓存较少使用),即使这些密钥的到期时间尚未达到。

    Nginx提供此内置版memcache module。它很坚固。如果你在线谷歌,可以参考一些教程。

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

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

答案 2 :(得分:1)

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

Nginx也是页面缓存的正常选择,每天点击1-2M,您不需要极高的性能。所以,请选择与您合作的方式。

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

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