How does Redis keep the value of self-incrementing key within a fixed number under concurrency?

the approximate code is as follows:

     func(id, ip){
         int countId = jedis.hget("count", id);
         int countIP = jedis.get("count", ip);
         if(countId >= 5 || countIP>=5){
             return;
         }
         ... //
         
         //
         int countId = jedis.hget("count", id);
         int countIP = jedis.get("count", ip);
         if(countId >= 5 || countIP>=5){
             doSomething();
             jedis.hincrBy("count", id, 1);
             jedis.hincrBy("count", ip, 1);
         }
     }
     

the above code only expresses the general meaning, because it is obvious that there will be problems in the case of concurrency

my idea is, for example, to do a, casIncrBy ("count" like CAS, id, 1, 5), this atomic operation increases the key value by 1, and fails if it is > 5. Then judge whether to fail or not. If you fail, you will not doSomething (),. If you succeed, you will doSomething ().

.

how can it be achieved?


take it out and judge it. After modification, it is found that if it is greater than 5, the value will be changed to 5.


use the Lua script.

eval "local curr = redis.call('get', KEYS[1]); if curr and tonumber(curr) >= tonumber(ARGV[2]) then return 0 else redis.call('incrby', KEYS[1], ARGV[1]); return curr + ARGV[1] end" 1 count 1 5

you can use @ oraoto to write a lua script.
if the lua script cannot implement business logic, you can use the WATCH command, or you can implement a simple lock to lock the key.
can refer to Redis practice " 4.4Redis transaction "and" 6.2distributed Lock "

Menu