如何使用Redis以原子方式增加价值

时间:2018-06-07 08:22:41

标签: node.js redis

我在nodejs中有以下代码:

const decrease = async (userId, points) => {
    const user = await redisClient.hgetall(userId);
    if(user.points - points >= 0) {
       await redisClient.hset(userId, userId, user.points - points);
    }
}

由于async/await没有阻止执行,如果对同一userId有多个请求,则代码不会以原子方式运行。这意味着即使用户帐户上没有足够的点,用户点也可能会多次减少。如何使方法以原子方式运行?

我检查了redis multi命令,它适用于多个redis语句。但在我的情况下,我需要计算不属于redis命令的用户点。那么如何使它们作为原子函数运行。

我还阅读了INCR模式:https://redis.io/commands/incr 但它似乎没有解决我的问题。那里列出的模式需要使用expire,我没有这样的要求给出特定的超时值。

1 个答案:

答案 0 :(得分:1)

通过调用EVAL来使用(Redis)服务器端Lua脚本的强大功能。它应该看起来像这样:

const lua = `
    local p = redis.call('HGET',KEYS[1],'points')
    local d = p - ARGV[1]
    if d >= 0 then
      redis.call('HSET', KEYS[1], 'points', d)
    end`
const decrease = async (userId, points) => {
    await redisClient.eval(lua, 1, userId, points);
}