日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

redis(千帆竞发--分布式锁)

發布時間:2023/12/16 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redis(千帆竞发--分布式锁) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

比如一個操作要修改的用戶的狀態,修改狀態需要先讀出用戶的狀態,在內存里進行修改,改完了再存回去。

如果這樣的操作同時進行了,就會出現并發問題,因為讀取和保存狀態這兩個操作不是原子的。

分布式鎖:

分布式鎖本質上要實現的目標就是在Redis里面占“坑”,當別的進程也要來占時,發現已經有人蹲在那里了,就

只好放棄或者稍后再試。

占坑一般是使用setnx(set if not exists)指令,只允許被一個客戶端占坑。先來先到,用完了在調用del指令釋放。

>setnx lock:codehole true OK ...do something critical... >del lock:codehole (integer) 1

但有個問題,如果邏輯執行到中間出現異常,可能會導致del指令沒有被調用,這樣就會陷入死鎖,鎖就得不到釋放了。

這樣我們可以拿到鎖之后,再給鎖加上一個過期時間,for example:5s

>setnx lock:codehole true OK >expire lock:codehole 5 ...do something critical... >del lock:codehole (integer) 1

如果在setnx和expire之間服務器進程突然掛掉的,就會導致expire得不到執行,也會造成死鎖。這個問題根源在于setnx和expire是兩條指令而不是原子指令。如果這兩條指令可以一起執行就不會出現問題。

>set lock:codehole true ex 5 nx OK ...do something critical... >del lock:codehole

上面這個指令就是setnx和expire組合一起的原子指令,它就是分布式鎖奧義的所在。

?

?

超時問題:

Redis的分布式鎖解決超時問題,如果在加鎖和釋放鎖之間的邏輯執行的太長,以至于超出了鎖的超時限制,就會出現問題。因為

這時候第一個線程持有的鎖過期了,臨界區的邏輯還沒有執行完,這個時候第二個線程就提前重新持有了這把鎖,導致臨界區代碼不能得到嚴格的串行執行。

lua 腳本if redis.call("get",keys[1] == argv[1] then return redis.call("del",keys[1]))else return 0 end

可重入性:

可重入性是指線程在持有鎖的情況下再次請求加鎖,如果一個鎖支持同一個線程的多次加鎖,那么這個鎖就是可重入的。

public class RedisWithReentrantLock{private ThreadLocal<Map<String,Integer>> lockers=new ThreadLocal<>();private Jedis jedis;public RedisWithReentrantLock(Jedis jedis){this.jedis=jedis;}private boolean lock(String key){return jedis.set(key,"","nx","ex",5L)}private void unlock(){jedis.del(key);}private Map<String,Integer> currentLockers(){Map<String,Integer> refs=lockers.get();if(refs!=null){return refs;}lockers.set(new HashMap<>());return lockers.get();}public boolean lock(String key){Map<String,Integer> refs=currentLockers();Integer refCnt=refs.get(key);if(refCnt!=null){refs.put(key,refCnt+1);return true;}boolean ok=this.lock(key);if(!ok){return false;}refs.put(key,1);return true; }public boolean unlock(String key){Map<String,Integer> refs=currentLockers(); Integer refCnt=refs.get(key);if(refCnt ==null){return false;}refCnt-=1;if(refCnt>0){refs.put(key,refCnt);}else{refs.remove(key);this.unlock(key);}return true;} public static void main(String[] args){Jedis jedis=new Jedis();RedisWithReentrantLock redis=new RedisWithReentrantLock(jedis);System.out.println(redis.lock("codehole"));System.out.println(redis.lock("codehole"));System.out.println(redis.unlock("codehole"));System.out.println(redis.unlock("codehole"));} }


?

總結

以上是生活随笔為你收集整理的redis(千帆竞发--分布式锁)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。