日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Java基于redis實現分布式鎖代碼實例

瀏覽:32日期:2022-09-03 09:06:11

為什么會有這個需求:

例如一個簡單用戶的操作,一個線程去修改用戶狀態,首先在在內存中讀出用戶的狀態,然后在內存中進行修改,然后在存到數據庫中。在單線程中,這是沒有問題的。但是在多線程中由于讀取,修改,寫入是三個操作,不是原子操作(同時成功或失敗),因此在多線程中會存在數據的安全性問題。

這個問題的話,就可以用分布式鎖在限制程序的并發執行。

實現思路:

就是進來一個先占位,當別的線程進來操作的時候,發現有人占位了,就會放棄或者稍后再試。

占位的實現:

在redis中的setnx命令來實現,redis命令可以參考我這篇博客https://www.cnblogs.com/javazl/p/12657280.html,默認set命令就是存值,當key存在的時候,set就會覆蓋key的value值,而setnx則不會。當沒有key的時候,setnx就會進來先占位,當key存在了,其他的setnx就進不來了。。等到第一個執行完成后,在del命令釋放位子。

代碼實現:

public class LockTest { public static void main(String[] args) { Redis redis = new Redis(); redis.execute(jedis->{ Long setnx = jedis.setnx('k1', 'v1'); //setnx的返回值為long類型 if (setnx == 1) {//沒人占位jedis.set('name', 'zl');String name = jedis.get('name');System.out.println(name);//釋放資源 jedis.del('k1'); }else{//有人占位,停止/暫緩 操作 } }); }}

上邊代碼中,就是一個簡易的分布式鎖的實現,但是有一個問題。就是如果在占位后釋放前掛了。那么這個線程會一直釋放不了,也就是del命令沒有調用,后面的全部請求都阻塞到這里,鎖就變成了死鎖。因此這里需要去優化。

優化的方法就是加過期時間,確保鎖在一定時間后能夠釋放.

public class LockTest { public static void main(String[] args) { Redis redis = new Redis(); redis.execute(jedis->{ Long setnx = jedis.setnx('k1', 'v1'); if (setnx == 1) {//給鎖添加一個過期時間,防止應用在運行過程中拋出異常導致鎖無法及時得到釋放jedis.expire('k1', 5);//沒人占位jedis.set('name', 'zl');String name = jedis.get('name');System.out.println(name);jedis.del('k1'); }else{//有人占位,停止/暫緩 操作 } }); }

這樣處理后,就可以保證鎖可以正常的釋放。但是會有一個新的問題,就是如果在取鎖和設置過期時間服務器掛掉了,因為取鎖,也就是setnx和設置過期時間是兩個操作,不具備原子性所以不可能同時完成。這個鎖就會被一直占用,無法得到釋放,成為死鎖。那么如何解決呢?

在redis2.8之后,setnx和expireke可以通過一個命令一起執行,讓兩個操作變成一個,就會解決這個問題。

優化實現:

public class LockTest { public static void main(String[] args) { Redis redis = new Redis(); redis.execute(jedis->{ //將兩個操作合并成一個,nx就是setnx,ex就是expire String set = jedis.set('k1', 'v1', new SetParams().nx().ex(5)); //操作結果為okhuo或者error if (set !=null && 'OK'.equals(set)) { //給鎖添加一個過期時間,防止應用在運行過程中拋出異常導致鎖無法及時得到釋放jedis.expire('k1', 5);//沒人占位jedis.set('name', 'zl);String name = jedis.get('name');System.out.println(name); //釋放資源jedis.del('k1'); }else{//有人占位,停止/暫緩 操作 } }); }}

用過期時間優化后,雖然解決了死鎖的問題,但是又有一個新的問題產生,就是超時問題:

舉個例子:如果要執行的業務很耗時,可能會出現紊亂,當地一個線程獲取到鎖的時候,開始執行業務代碼,但是業務代碼很耗時,假如過期時間是3秒,而業務執行需要5秒,這樣,鎖就會提前釋放,然后第二個線程獲取到鎖并開始執行。當執行到第2秒的時候,第一個鎖也執行完了,此時第一個線程會釋放第二個線程的鎖,然后第三個線程繼續獲取鎖并執行,當到第3秒的時候第二個線程執行完了,那么又會提前釋放鎖,一直如此循環,會造成線程的紊亂。

那么解決的思路主要有兩種

盡量避免耗時操作。

去處理鎖,給鎖的value設置隨機數或隨機字符串,每當要釋放的時候去判斷這個value的值,如果是的話就去釋放,如果不是就不釋放,舉個例子,假設第一個線程進來,它獲取鎖的value是1,如果發生超時就會進入下一個線程,下一個線程會獲取新的value為

3,在釋放第二個所之前先去獲取value并比較,發現1不等于三,那么就不去釋放鎖。第一種的話沒啥說的,但是第二種的話會有一個問題,就是釋放鎖會查看value,然后比較,然后釋放,會有三個操作,那么就不具備原子性,這樣操作的話,會出現死鎖。這里我們可以使用Lua腳本去處理。

Lua腳本的特點:

1.使用方便,redis內置了對Lua腳本的支持。

2.Lua可以在redis服務端原子性的執行多個redis命令

3.由于網絡的原因會影響到redis的性能,因此,使用Lua可以讓多個命令同時執行,降低了網絡給redis帶來的性能問題。

在redis中如何使用Lua腳本:

1.在redis服務端寫好,然后在java業務中調用腳本

2.可以直接在java中直接去寫,寫好后,需要執行時,每次將腳本發送到redis中去執行。

創建Lua腳本:

//用redis.call調用一個redis命令,調的是get命令,這個key是從外面傳進來的keyif redis.call('get',KEYS[1])==ARGV[1] then//如果相等就去操作釋放命令 return redis.call('del',KEYS[1])else return 0end

可以給Lua腳本求一個SHA1和:

cat lua/equal.lua | redis-cli -a root script load --pipe

script load這個命令會在Redis中緩存Lua腳本,并返回腳本內容的SHA1校驗和,然后在java中調用時,傳入SHA1校驗和作為參數,這樣redis服務端就知道執行那個腳本了。

接下來在java中編寫

public static void main(String[] args) { Redis redis = new Redis(); for (int i = 0; i < 2; i++) { redis.execute(jedis -> {//1.先獲取一個隨機字符串String value = UUID.randomUUID().toString();//2.獲取鎖String k1 = jedis.set('k1', value, new SetParams().nx().ex(5));//3.判斷是否成功拿到鎖if (k1 != null && 'OK'.equals(k1)) { //4. 具體的業務操作 jedis.set('site', 'zl'); String site = jedis.get('site'); System.out.println(site); //5.釋放鎖 jedis.evalsha('b8059ba43af6ffe8bed3db65bac35d452f8115d8', Arrays.asList('k1'), Arrays.asList(value));} else { System.out.println('沒拿到鎖');} }); } }}

這樣處理的話,就解決了死鎖的問題。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網。

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品调教| 国产精品久久久一区二区| 免费观看在线综合| 日产欧产美韩系列久久99| 国产v综合v| 日韩欧美中文字幕一区二区三区| 欧美成人久久| 欧洲一区二区三区精品| 日韩精品视频在线看| 国产一区二区中文| 不卡专区在线| 国产精品网址| 青草久久视频| 伊人久久视频| 老司机久久99久久精品播放免费| 久久丁香四色| 91av亚洲| 麻豆精品久久| 国产剧情一区二区在线观看| 午夜在线精品偷拍| 麻豆一区在线| 欧美一区不卡| 精品国产免费人成网站| 老牛影视精品| 国产成人77亚洲精品www| 成人亚洲欧美| 亚洲伊人精品酒店| 精品视频高潮| 成人va天堂| 久久久影院免费| av在线最新| 欧美www视频在线观看| 日韩精品一区二区三区免费观影 | 日本欧美一区| 福利一区和二区| 国产精品一区二区三区av| 日韩综合小视频| 午夜亚洲精品| 亚洲91网站| 美女尤物国产一区| 久久国产亚洲| 视频一区中文字幕| 国产黄大片在线观看| 日本亚洲不卡| 天堂av在线一区| 欧美/亚洲一区| 欧美va天堂在线| 久久久久久一区二区| 久久久久久夜| 国产综合亚洲精品一区二| 亚洲综合三区| 亚洲综合精品| 成人羞羞视频在线看网址| 精品视频国内| 久久av在线| 成午夜精品一区二区三区软件| 亚洲精品日韩久久| 日韩精品午夜| 久久久久久色| 色网在线免费观看| 国产欧美一区二区精品久久久| 日本亚洲欧美天堂免费| 欧美成人久久| 播放一区二区| 欧美黑人巨大videos精品| 国产精品久久久久久久久久白浆| 麻豆精品新av中文字幕| 黄色亚洲大片免费在线观看| 亚洲天堂av影院| 国产精品视频一区二区三区| 黄色在线一区| 欧美成人一二区| 日韩国产在线观看| 老司机精品视频在线播放| 蜜桃伊人久久| 蜜臀va亚洲va欧美va天堂| 欧美一级一区| 欧美一级二级视频| 在线亚洲欧美| 国产精品av一区二区| 在线手机中文字幕| 日本一区二区中文字幕| 免费在线观看日韩欧美| 伊人精品在线| 一区二区三区网站| 亚洲人成精品久久久| 亚洲久久一区| 国产精品亚洲产品| 久久午夜视频| 中文一区一区三区免费在线观| 亚洲毛片网站| а√天堂中文在线资源8| 国产精品xvideos88| 国产精品一区二区美女视频免费看| 亚洲三级av| 日韩精品五月天| 日韩中文av| 日韩成人一级| 国产精品一区三区在线观看| 国产精品白丝一区二区三区| 久久不卡日韩美女| 欧美日韩国产免费观看| 精品捆绑调教一区二区三区| 日本不良网站在线观看| 欧美13videosex性极品| 欧美大黑bbbbbbbbb在线| 亚洲一级淫片| 日韩国产欧美在线视频| 三级一区在线视频先锋| 久久婷婷久久| 久久久国产精品网站| 久久中文欧美| 六月婷婷综合| 婷婷成人基地| 久久福利一区| 日本欧美一区二区在线观看| 久久精品超碰| 热久久久久久| 国产成人1区| 欧美日韩黑人| 免费亚洲婷婷| 一区二区三区国产在线| 亚洲国产专区校园欧美| 国产精品久久乐| 视频一区免费在线观看| 婷婷中文字幕一区| 日韩一区电影| 国产精品蜜月aⅴ在线| 激情综合自拍| 日韩精品一二区| 久久国产精品美女| 国产精品成人国产| 久久激情网站| 9色精品在线| 91中文字幕精品永久在线| 久久久精品网| 欧美日韩高清| 精品久久精品| 国产精品主播| 亚洲91网站| 日韩精品一区第一页| 视频一区中文字幕精品| 婷婷亚洲精品| 欧美激情网址| 久久国产欧美| 日本成人中文字幕在线视频| 久久久精品区| 精品国产亚洲一区二区三区| 国产精品一区三区在线观看| 男女男精品网站| 精品无人区麻豆乱码久久久| 另类中文字幕国产精品| 午夜精品网站| 欧美交a欧美精品喷水| 色偷偷色偷偷色偷偷在线视频| 久久午夜精品一区二区| 国产精品二区不卡| 亚洲一区成人| 国产一区2区| 亚洲一级大片| 毛片在线网站| 欧美偷窥清纯综合图区| 国产一区日韩一区| 美女视频黄久久| 午夜在线精品偷拍| 成人免费一区| 911亚洲精品| 亚洲男女自偷自拍| 美女精品久久| 一区二区国产在线| 欧美日韩中文一区二区| 国产精品大片| 午夜亚洲一区| 午夜精品成人av| 亚洲色图网站| 秋霞影院一区二区三区| 国产成人精品三级高清久久91| 激情欧美日韩一区| 欧美日韩va| 三级精品视频| 日韩高清二区| 国产视频一区欧美| 国产精品99一区二区三区| 日韩精品久久久久久久软件91| 日韩在线黄色| 日韩精选在线| 日韩天堂av| 久久一区二区中文字幕| 国产精品一区二区av日韩在线 | 日韩午夜av| 久久婷婷久久| 国产自产自拍视频在线观看| 久久毛片亚洲| 国产日韩免费| 亚洲欧洲一区| 视频在线观看国产精品| 99国产精品私拍| 亚洲精品婷婷| 美女高潮久久久| 国产一区二区三区亚洲综合|