Как увеличить значение атомарно с помощью Redis - PullRequest
0 голосов
/ 07 июня 2018

У меня есть код ниже в 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 не блокирует выполнение, если есть несколько запросов для одного и того же идентификатора пользователя, код работает не так, как атомарно.Это означает, что пользовательские баллы могут быть уменьшены многократно, даже если на учетной записи пользователя недостаточно баллов.Как я могу заставить метод работать атомарно?

Я проверил команду redis multi, и она работает для нескольких операторов redis.Но в моем случае мне нужно рассчитать пользовательские баллы, которые не являются частью команды redis.Итак, как заставить их работать как элементарную функцию.

Я также прочитал шаблон INCR: https://redis.io/commands/incr Но, похоже, это не решает мою проблему.Перечисленные там шаблоны должны работать с истечением, но у меня нет такого требования для указания определенного значения времени ожидания.

1 Ответ

0 голосов
/ 07 июня 2018

Используйте возможности (Redis) серверных сценариев Lua, вызывая EVAL.Вероятно, это должно выглядеть примерно так:

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...