【问题标题】:Redis zrangebyscore and zincrby under high concurrency高并发下的redis zrangebyscore和zincrby
【发布时间】:2021-07-10 13:57:54
【问题描述】:

我面临 redis 的并发问题,我的 API 是基于 Nodejs Fastify 构建的,我在 API 调用中使用 fastify-redis。

我使用了两种简单的redis方法ZRANGEBYSCOREZINCRBY

问题是在高并发下 ZINCRBY 执行较晚,导致在多个请求上给我相同的值。

在高并发下如何防止这种情况有什么方法可以锁定之前执行的KEY。

这是我的代码示例

numbers = await redis.zrangebyscore(
            `user:${req.query.key}:${state}`, //key
            0, // min value
            50, // max value
            "LIMIT",
            0, // offset
            1 // limit
        );

if (numbers.length > 0) {
        await redis.zincrby(`user:${req.query.key}:${state}`, 1, numbers[0]);
        res.send(numbers[0]);
    }

【问题讨论】:

    标签: node.js redis fastify


    【解决方案1】:

    问题不在于并发本身,而在于您有一系列需要原子的操作,而您没有做任何事情来确保这一点。

    Redis 具有尝试确保原子性的设施,如 here 所述。在您的情况下,由于第二个操作中使用了第一个操作的值,因此您无法执行简单的MULTIEXEC。您必须改为WATCH 密钥,然后在它中止时重试该操作。

    不过,更简单且推荐的方法是将上述代码放入Lua script,它可以在服务器上作为单个原子操作执行。

    【讨论】:

    • 所以如果我创建一个 lua 脚本并使用这些命令形成 lua 脚本,它将确保以原子方式执行 zincrby 和所有系列操作?
    • 我也只需要在 ZINCRBY 或一系列中运行 MULTI 命令...还有一件事 zrangebyscore 将返回一个我将递增的值,所以在一个多命令中我将如何运行它?一点帮助就可以真正清除我的概念
    • @AmanullahTanweer:是的,你不能只使用MULTI。您必须WATCH 密钥并在它中止时重试该操作。但只需将上面的代码翻译成 Lua 脚本并使用EVAL。这将使整个操作原子化。
    猜你喜欢
    • 2012-08-25
    • 1970-01-01
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-06
    • 2013-11-28
    相关资源
    最近更新 更多