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

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

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

瀏覽:28日期: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久久,三上悠亚国产精品一区二区三区
日韩成人在线看| 午夜久久美女| 在线免费观看亚洲| 怡红院精品视频在线观看极品| 久久国产日本精品| 日韩深夜视频| 播放一区二区| 久久精品国产www456c0m| 色爱av综合网| 亚洲一级网站| 久久一级电影| 激情婷婷综合| 老司机精品久久| 亚洲人亚洲人色久| 国产亚洲高清在线观看| 久久不卡国产精品一区二区| 久久久精品区| 国产91在线播放精品| 日韩电影免费网址| 久久国产影院| 免费视频久久| 欧美欧美黄在线二区| 久久一区精品| 欧美亚洲国产一区| 亚洲制服一区| 欧美日韩中文| 在线天堂中文资源最新版| 91精品啪在线观看国产18 | 欧美影院精品| 精品午夜av| 99精品在线观看| 亚洲综合欧美| 国产欧美日韩综合一区在线播放| 麻豆精品视频在线观看视频| 97se综合| 一区二区三区四区日韩| 久久精品国产在热久久| 久久蜜桃av| 影音先锋久久精品| 国产免费久久| 久久久蜜桃一区二区人| 亚洲中字黄色| 国产精品久久久久久模特| 亚洲不卡av不卡一区二区| 亚洲日韩视频| 国产精品精品| 天堂av在线一区| 免费日韩一区二区三区| 欧美另类综合| 国产极品一区| 女人天堂亚洲aⅴ在线观看| 欧美日韩亚洲一区在线观看| 国产伦久视频在线观看| 视频一区视频二区在线观看| 国产亚洲一区二区三区不卡 | 欧美aa在线视频| 亚洲高清成人| 国产欧美日韩视频在线 | 三级精品视频| 日本少妇精品亚洲第一区| 久久精品国内一区二区三区水蜜桃| 视频在线观看91| 国产欧洲在线| 欧美日韩1区| 91高清一区| 久久三级中文| 国产一区成人| 超碰成人av| 欧美亚洲tv| 一本一道久久a久久精品蜜桃| 国产精品17p| 蜜桃一区二区三区在线观看| 国产亚洲一区二区手机在线观看| 欧美中文高清| 99视频一区| 色一区二区三区四区| 日韩av成人高清| re久久精品视频| 欧美激情另类| 国产精品a级| 亚洲精品高潮| 国产99亚洲| 红杏一区二区三区| 日本成人在线视频网站| 影院欧美亚洲| 播放一区二区| 日韩成人精品一区| 久久国产精品色av免费看| 亚洲综合三区| 欧美亚洲精品在线| 麻豆理论在线观看| 国产精品男女| 日韩欧美美女在线观看| 亚洲免费中文| 精品中文在线| 欧美激情三区| 日韩精品第二页| 亚洲视频国产| 久久亚洲风情| 久久国产精品毛片| 午夜欧美精品| 美女亚洲一区| 99久久久国产精品美女| 97精品国产一区二区三区| 精品黄色一级片| 久久这里只有精品一区二区| 国产精品nxnn| 国产精品日韩精品在线播放| 日韩视频1区| 亚洲精品亚洲人成在线观看| 国产精品美女久久久浪潮软件| 国产99精品一区| 欧美亚洲精品在线| 九九久久婷婷| 欧美日韩激情| 一区二区视频欧美| 怡红院精品视频在线观看极品| 精品一区三区| 亚洲二区三区不卡| 最新国产拍偷乱拍精品| 亚洲精品99| 鲁大师影院一区二区三区| 国产亚洲在线| 亚洲男人在线| 日韩av一区二区三区四区| 国产日韩欧美高清免费| 欧美日韩亚洲一区在线观看| 国产精品国码视频| 国内精品伊人| 亚洲成av在线| 极品裸体白嫩激情啪啪国产精品| 欧美日韩国产探花| 亚洲免费网址| 日本亚洲不卡| 国产免费久久| 国产成人免费视频网站视频社区| 国产精品毛片久久| 久久国产小视频| 另类av一区二区| 日本麻豆一区二区三区视频| 国产福利资源一区| 国产精品99久久精品| 四虎4545www国产精品| 悠悠资源网久久精品| 亚洲精品影视| 国产精品久一| 精品捆绑调教一区二区三区| 亚洲男女av一区二区| 亚洲精品视频一二三区| 国产伦理久久久久久妇女| 狠狠久久伊人| 蜜桃一区二区三区| 亚洲免费福利一区| 久久99精品久久久野外观看| 日韩国产一区| 日韩中文字幕区一区有砖一区 | 99精品在线免费在线观看| 夜夜精品视频| 国产精品一区2区3区| 色婷婷久久久| 一区二区亚洲视频| 精品三级久久久| 最新亚洲激情| 国产精品主播| 在线日韩av| 欧美视频久久| 久久天堂精品| 无码日韩精品一区二区免费| 国产欧美高清视频在线| 久久久一本精品| 亚洲一区欧美| 麻豆成全视频免费观看在线看| 亚洲在线国产日韩欧美| 国产精品亚洲欧美| 久久国产中文字幕| 天堂va欧美ⅴa亚洲va一国产| 久久精品国产精品亚洲毛片| 亚洲中字黄色| 久久精品一区| 久久国产88| 成人精品久久| 日韩区一区二| 久久黄色影院| 日本午夜精品久久久| 精品捆绑调教一区二区三区| 日韩和欧美一区二区三区| 999国产精品永久免费视频app| 91精品国产自产精品男人的天堂| 五月激情久久| 国产精品一级| 99综合视频| 水蜜桃精品av一区二区| 日韩欧美中文字幕电影 | 日本不卡免费高清视频在线| 亚洲毛片在线免费| 久久久久91| 欧美激情久久久久久久久久久| 美女亚洲一区| 福利视频一区| 欧美天堂一区二区|