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: 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With