鍍金池/ 問答/人工智能  HTML5  Java  Linux/ Redis如何在并發(fā)下讓自增key的值不超過某個(gè)固定的數(shù)?

Redis如何在并發(fā)下讓自增key的值不超過某個(gè)固定的數(shù)?

大致代碼如下:

     func(id, ip){
         int countId = jedis.hget("count", id);
         int countIP = jedis.get("count", ip);
         if(countId >= 5 || countIP>=5){
             return;
         }
         ... //一些其他操作
         
         //再次判斷,怕并發(fā)時(shí)被其他線程修改過
         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);
         }
     }
     

上述代碼只是表達(dá)大致意思,因?yàn)轱@然在并發(fā)情況下會(huì)有問題

我的設(shè)想是,譬如做一個(gè)類似CAS的,casIncrBy("count", id, 1, 5), 這個(gè)原子操作對(duì)key值增1,如果>5則失敗。然后判斷是否失敗,失敗就不doSomething(),成功就doSomething().

如何達(dá)成?

回答
編輯回答
耍太極

可以使用 @oraoto 的思路, 寫個(gè)lua腳本.
如果lua腳本無法實(shí)現(xiàn)業(yè)務(wù)邏輯, 可以使用WATCH命令, 或者自己實(shí)現(xiàn)一個(gè)簡(jiǎn)單的鎖, 鎖住這個(gè)鍵.
可以參考Redis實(shí)戰(zhàn)中《4.4 Redis事務(wù)》 和 《6.2分布式鎖》

2017年3月5日 03:42
編輯回答
傲寒

拿出來, 判斷一下, 修改后發(fā)現(xiàn)大于5把數(shù)值改成5..

2017年10月24日 05:02
編輯回答
笑浮塵

用Lua腳本。

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
2018年3月15日 15:08