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) :
- If some key K exists get the value for it
- Otherwise, call SETNX function with a random value that is generated by some function F(that generates salts)
- Ask redis for the value of key K that was just generated by the current session (or by another session "simultaneously" - a short moment before the current session generated it)
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 :
- I don't want to call F with no justification (it might cause an intensive CPU behaviour(
- I want to avoid the next problematic situation : T1 : Session 1 generated a random value VAL1 T2 : Session 1 asked if key K exists and got "False" T3 : Session 2 generated a random value VAL2 T4 : Session 2 asked if key K exists and got "False" T5 : Session 2 calls SETNX with the value VAL2 and uses VAL2 from now on T6 : Session 1 calls SETNX with the value VAL1 and uses VAL1 from now on where the actual value of key K is VAL2
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?