【问题标题】:Which method of caching is the fastest/lightest for Node/Mongo/NginX?对于 Node/Mongo/NginX,哪种缓存方法最快/最轻?
【发布时间】:2013-03-11 10:57:57
【问题描述】:

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

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

我的问题是如何处理缓存。我来自 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

【问题讨论】:

  • 我们需要知道您服务的唯一页面数量以及您服务的页面的哪些部分是可缓存的。例如,如果每个页面都显示用户名和当前时间(不使用 JavaScript 更新它),那么任何页面都不能被缓存,因为每个人看到的页面不同。即使每个人在同一个 URL 上看到同一个页面,如果您的站点有数百万个(自动生成的)页面,以至于一天中 95% 的页面只被查看一次,那么再次缓存也无济于事。因此,我们需要有关您的情况的更多信息。

标签: node.js caching nginx redis varnish


【解决方案1】:

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

【讨论】:

    【解决方案2】:
    1. nginx 页面级缓存适用于缓存静态内容。但是对于动态内容,就不好说了。比如,如果内容在上游发生变化,如何使缓存失效?

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

    没有选择 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/

    【讨论】:

      【解决方案3】:

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

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

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

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

      【讨论】:

        猜你喜欢
        • 2011-06-04
        • 2020-02-16
        • 1970-01-01
        • 2010-11-16
        • 2013-10-08
        • 2012-04-02
        • 1970-01-01
        • 2011-10-12
        • 1970-01-01
        相关资源
        最近更新 更多