开发者

Atomically remove an item from set if a counter in another key is below zero?

Redis 2.0.3

In my Redis DB I have a set of items. Each item has a counter, associated with it:

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

New items are added to the set at random intervals.

When user does a certain action, counter is decremented:

new_counter = DECR "items:foo"

I need to atomically remove the item from the set, when the counter drops below zero (alternatively:开发者_如何学Python when the counter reaches zero exactly, I can fix up logic for that.)

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

How can I do this without locking by the item name with SETNX/GETSET?

Solutions, involving change of the way I store data in Redis, are acceptable. (But, just in case, I reserve a right to counter them with some task-specific detail that I could miss in initial text.)


just use the new WATCH capability of 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

To understand the example you need to understand how WATCH works. Please check the doc at http://redis.io site.

p.s. there are no ways to do this with Redis 2.0.3


It should be on a loop, so you can retry if someone else touched the value in the middle.

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜