I have a redis server and I want to implement an atomic (or pseudo atomic) method that will do the following (NOTICE: I have a system that has multiple sessions to the redis server) :
The reasons that I don't want to pre-generate (before checking if the value exists) a value with function F, and use it if the key doesn't exist are :
A python pseudo-code that I created is :
import redis
r = redis.StrictRedis(host='localhost', port=6379, db=0)
''' gets the value of key K if exists (r.get(K) if r.exists(K)),
otherwise gets the value of key K if calling SETNX function returned TRUE
(else r.get(K) if r.setnx(K,F())), meaning this the sent value is really the value,
otherwise, get the value of key K, that was generated by another session a
short moment ago (else r.get(K))
The last one is redundant and I can write "**r.setnx(K,F()) or True**" to get the
latest value instead, but the syntax requires an "else" clause at the end '''
r.get(K) if r.exists(K) else r.get(K) if r.setnx(K,F()) else r.get(K)
Is there another solution?
Yes, you can use WATCH for this. Here's a modified example with redis-py:
def atomic_get_set(some_key):
with r.pipeline() as pipe:
try:
# put a WATCH on the key that holds our sequence value
pipe.watch(some_key)
# after WATCHing, the pipeline is put into immediate execution
# mode until we tell it to start buffering commands again.
# this allows us to get the current value of our sequence
if pipe.exists(some_key):
return pipe.get(some_key)
# now we can put the pipeline back into buffered mode with MULTI
pipe.multi()
pipe.set(some_key, F())
pipe.get(some_key)
# and finally, execute the pipeline (the set and get commands)
return pipe.execute()[-1]
# if a WatchError wasn't raised during execution, everything
# we just did happened atomically.
except WatchError:
# another client must have changed some_key between
# the time we started WATCHing it and the pipeline's execution.
# Let's just get the value they changed it to.
return pipe.get(some_key)
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