Атомно удалить элемент из набора, если счетчик в другом ключе ниже нуля? - PullRequest
6 голосов
/ 25 февраля 2011

Redis 2.0.3

В моей БД Redis у меня есть набор предметов. У каждого предмета есть счетчик, связанный с ним:

MULTI
    SADD "items-set" "foo"
    INCRBY "items:foo" 10000
EXEC

Новые предметы добавляются в набор через произвольные интервалы.

Когда пользователь выполняет определенное действие, счетчик уменьшается:

new_counter = DECR "items:foo"

Мне нужно атомарно удалить предмет из набора, когда счетчик опускается ниже нуля (альтернативно: когда счетчик точно достигает нуля, я могу исправить логику для этого.)

if new_counter < 0 then
    MULTI
        SREM "items-set" "foo"
        DEL "items:foo"
    EXEC
end

Как это сделать без блокировки по имени элемента с помощью SETNX / GETSET?

Решения, связанные с изменением способа хранения данных в Redis, являются приемлемыми. (Но, на всякий случай, я оставляю за собой право противопоставить им некоторые специфические для задачи детали, которые я мог бы пропустить в первоначальном тексте.)

Ответы [ 2 ]

10 голосов
/ 25 февраля 2011

просто используйте новую возможность WATCH Redis 2.2:

WATCH items-set items:foo
count = GET items:foo
IF count == 0:
    MULTI
    SREM items-set foo
    SET items:foo count-1
    EXEC
ELSE:
    MULTI
    SET items:foo count-1
    EXEC

Чтобы понять пример, вам нужно понять, как работает WATCH. Пожалуйста, проверьте документ на http://redis.io сайте.

p.s. нет никаких способов сделать это с Redis 2.0.3

2 голосов
/ 25 февраля 2011

Это должно быть в цикле, поэтому вы можете повторить попытку, если кто-то еще коснулся значения в середине.

success = false
while not success 
    WATCH items-set items:foo
    count = GET items:foo
    MULTI
    IF count == 0:
        SREM items-set foo
    SET items:foo count-1
    success = EXEC
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...