【问题标题】:Caching relational data using redis使用redis缓存关系数据
【发布时间】:2019-05-15 15:53:23
【问题描述】:

我正在构建一个小型社交网络(用户有帖子,帖子有 cmets - 非常基本),使用集群 nodejs 服务器和 redis 作为分布式缓存。
我缓存用户帖子的方法是有一个sorted set,其中包含按速率排序的所有用户帖子ID(每次有人添加喜欢或评论时都应该更新),实际对象排序为hash objects
所以获取用户的帖子流程应该是这样的:
1. 使用zrangesorted set 中获取一系列id。
2. 使用multi/exechgetall 一次性获取所有对象。

我有几个问题:
1。关于性能问题,当缓存大小变大时,我的方法是否会扩展,或者我应该使用 lua 之类的?
1.如果我想继续当前的方法,我应该在redis崩溃的情况下保存排序集,如果我使用redis持久化这会影响整体性能,我考虑为@使用专用的redis服务器987654327@(我搜索了是否可以只备份部分redis数据但没有找到。

我的方法 => getTopObjects({userID}, 0, 20) :

self.zrange = function(setID, start, stop, multi)
{
    return execute(this, "zrange", [setID, start, stop], multi);
};

self.getObject = function(key, multi)
{
    return execute(this, "hgetall", key, multi);
};

self.getObjects = function(keys)
{
    let multi = thisArg.client.multi();
    let promiseArray = [];

    for (var i = 0, len = keys.length; i < len; i++)
    {
        promiseArray.push(this.getObject(keys[i], multi));
    }
    return execute(this, "exec", [], multi).then(function(results)
    {
        //TODO: do something with the result.
        return Promise.all(promiseArray);
    });
};

self.getTopObjects = function(setID, start, stop)
{
    //TODO: validate the range 
    let thisArg = this;
    return this.zrevrange(setID, start, stop).then(function(keys)
    {
        return thisArg.getObjects(keys);
    });
};

【问题讨论】:

    标签: node.js caching redis social-networking


    【解决方案1】:

    这是一个有趣的智力练习,但在我看来这是经典的premature optimization

    1) 甚至引入 redis 可能还为时过早,更不用说考虑redis 是否足够快了。您的社交网络几乎肯定可以容纳大约 1,000 名用户对 Mysql / Postgres / Random RDS 运行原始 SQL 查询。如果它开始变慢,请获取有关运行缓慢的查询的数据,并使用查询优化和适当的索引来修复它们。这将使您超过 10,000 个用户。

    2) 现在可以开始介绍redis了。在一般中,我鼓励您将您的 redis 视为纯粹的缓存而不是永久存储;它是否被吹走无关紧要,这只是意味着您的网站在接下来的几秒钟内变慢了,因为您的用户从 SQL 查询而不是 redis 点击中获取页面加载(每个查询重新填充该用户的排序帖子列表当然是在 redis 中)。

    您使用 redis 的策略和示例代码对我来说似乎很好,但在您获得有关用户如何使用您的网站的实际数据(这可能与您当前的预期大不相同)之前,这根本是不可能的了解您将需要哪些类型的 SQL 索引、哪些键和列表最适合在 redis 中进行缓存等。

    【讨论】:

      【解决方案2】:

      我遇到了类似的问题,我需要一种更有效地查询数据的方法。不能肯定地说,但我听说Redis 在运行 lua 脚本时单线程阻塞了主线程,我确信这对社交网站不利。我听说过Tarantool,它看起来很有希望,目前我正试图将其包裹起来。

      如果你担心你的缓存越来越大,我认为大多数社交网络都会在用户缓存中保留两周的数据,超过两周的数据会被删除,你只需实现一个与分页一起使用的滚动功能,一次用户向下滚动,获取接下来两周的数据并仅为该特定用户将其添加回内存(不要忘记为新添加的数据指定新的 ttl)。这有助于保持缓存大小精简。

      当您使用的 redis 或任何内存数据工具崩溃时会发生什么,您只需将数据重新加载回内存即可。它们都具有将数据保存到文件作为备份的功能。我正在考虑实现另一个数据库层,不知道让我们说CassandraMongodb,它保存了每个用户自成立以来的时间线。当然,这会产生另一个开销,因为您必须保持三个数据层(例如 mysql、redis 和 mongodb)同步!

      如果这看起来工作量很大,请随意使用 3rd 方服务来托管您的内存数据,至少您可以安心入睡,但这会花费您。

      也就是说,这是高度自以为是的。厌倦了人们告诉我等到我的网站与用户爆炸或所谓的premature optimization 回复你得到:)

      【讨论】:

        猜你喜欢
        • 2015-09-04
        • 2021-07-02
        • 2020-05-17
        • 2018-08-28
        • 1970-01-01
        • 2013-04-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多