日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Redis怎么實(shí)現(xiàn)分布式鎖

Redis怎么實(shí)現(xiàn)分布式鎖

作者:DNF搬磚摸金達(dá)人 2022-01-06 10:58:07

存儲(chǔ)

存儲(chǔ)軟件

分布式

Redis 阿粉最近迷上了 Redis,為什么呢?感覺 Redis 確實(shí)功能很強(qiáng)大呀,一個(gè)基于內(nèi)存的系統(tǒng) Key-Value 存儲(chǔ)的數(shù)據(jù)庫,竟然有這么多的功能,而阿粉也要實(shí)實(shí)在在地把 Redis 來弄一下,畢竟面試的時(shí)候,Redis 可以說是一個(gè)非常不錯(cuò)的加分項(xiàng)。

長(zhǎng)島網(wǎng)站建設(shè)公司創(chuàng)新互聯(lián),長(zhǎng)島網(wǎng)站設(shè)計(jì)制作,有大型網(wǎng)站制作公司豐富經(jīng)驗(yàn)。已為長(zhǎng)島上千家提供企業(yè)網(wǎng)站建設(shè)服務(wù)。企業(yè)網(wǎng)站搭建\外貿(mào)營(yíng)銷網(wǎng)站建設(shè)要多少錢,請(qǐng)找那個(gè)售后服務(wù)好的長(zhǎng)島做網(wǎng)站的公司定做!

阿粉最近迷上了 Redis,為什么呢?感覺 Redis 確實(shí)功能很強(qiáng)大呀,一個(gè)基于內(nèi)存的系統(tǒng) Key-Value 存儲(chǔ)的數(shù)據(jù)庫,竟然有這么多的功能,而阿粉也要實(shí)實(shí)在在地把 Redis 來弄一下,畢竟面試的時(shí)候,Redis 可以說是一個(gè)非常不錯(cuò)的加分項(xiàng)。

分布式鎖

為什么需要分布式鎖?

目前很多的大型項(xiàng)目全部都是基于分布式的,而分布式場(chǎng)景中的數(shù)據(jù)一致性問題一直是一個(gè)不可忽視的問題,大家知道關(guān)于分布式的 CAP 理論么?

CAP 理論就是說任何一個(gè)分布式系統(tǒng)都無法同時(shí)滿足一致性(Consistency)、可用性(Availability)和分區(qū)容錯(cuò)性(Partition tolerance),最多只能同時(shí)滿足兩項(xiàng)。

而我們的系統(tǒng)最終滿足的永遠(yuǎn)都是最終一致性,而這種最終一致性,有些時(shí)候有人會(huì)喜歡問關(guān)于分布式事務(wù),而有些人則偏重在分布式鎖上。

分布式鎖的種類

  1. 數(shù)據(jù)庫實(shí)現(xiàn)分布式鎖
  2. 緩存實(shí)現(xiàn)分布式鎖
  3. Zookeeper實(shí)現(xiàn)分布式鎖

但是阿粉選擇的就是使用緩存來實(shí)現(xiàn)分布式鎖,也就是我們?cè)陧?xiàng)目中最經(jīng)常使用的 Redis ,談到 Redis,那真是可以用在太多地方了,比如說:

  • 會(huì)話緩存
  • 消息隊(duì)列
  • 分布式鎖
  • 發(fā)布,訂閱消息
  • 商品列表,評(píng)論列表

我們今天就來實(shí)現(xiàn)用 Redis 來實(shí)現(xiàn)分布式鎖,并且要學(xué)會(huì)怎么使用。

準(zhǔn)備工作

1.準(zhǔn)備使用 Jedis 的 jar 包,在項(xiàng)目中導(dǎo)入 jar 包。

  
 
 
 
  1.  
  2.  
  3.     redis.clients 
  4.     jedis 
  5.     2.9.0 
  6.  

直接來寫個(gè)工具類吧! 

  
 
 
 
  1. public class RedisPoolUtil { 
  2.  
  3.     private static final String LOCK_SUCCESS = "OK"; 
  4.     private static final String SET_IF_NOT_EXIST = "NX"; 
  5.     private static final String SET_WITH_EXPIRE_TIME = "PX"; 
  6.  
  7.     private RedisPoolUtil(){} 
  8.     /** 
  9.      *  
  10.      * @param jedis  
  11.      * @param lockKey 加鎖 
  12.      * @param requestId 請(qǐng)求的標(biāo)志位 
  13.      * @param expireTime 超時(shí)時(shí)間 
  14.      * @return 
  15.      */ 
  16.     public static boolean tryGetDistributedLock(Jedis jedis,String lockKey, String requestId, int expireTime) { 
  17.  
  18.         String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); 
  19.  
  20.         if (LOCK_SUCCESS.equals(result)) { 
  21.             return true; 
  22.         }else{ 
  23.             try{ 
  24.                 Thread.sleep(10);//休眠100毫秒 
  25.             }catch(Exception e){ 
  26.                 e.printStackTrace(); 
  27.             } 
  28.         } 
  29.         return false; 
  30.     } 

jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); 這個(gè)加鎖的姿勢(shì)才是我們最需要了解的,不然你用的時(shí)候都不知道怎么使用。

key:加鎖的鍵,實(shí)際上就是相當(dāng)于一個(gè)唯一的標(biāo)志位,不同的業(yè)務(wù),你可以使用不同的標(biāo)志位進(jìn)行加鎖。

requestId:這個(gè)東西實(shí)際上就是用來標(biāo)識(shí)他是哪一個(gè)請(qǐng)求進(jìn)行的加鎖,因?yàn)樵诜植际芥i中,我們要知道一件事,就是加鎖的和解鎖的,必須是同一個(gè)客戶端才可以。

而且還有一種比較經(jīng)典的就是 B 把 A 的鎖給釋放了,導(dǎo)致釋放混亂,如果你不加相同的請(qǐng)求,A 線程處理業(yè)務(wù),執(zhí)行了加鎖,鎖的過期時(shí)間是5s, B線程嘗試獲取鎖,如果 A 處理業(yè)務(wù)時(shí)間超過5s,這時(shí)候 A 就要開始釋放鎖,而B在這時(shí)候沒有檢測(cè)到這個(gè)鎖,從而進(jìn)行了加鎖,這時(shí)候加鎖的時(shí)候,A還沒處理完對(duì)應(yīng)業(yè)務(wù),當(dāng)他處理完了之后,再釋放鎖的話,要是就是直接把 B 剛加的鎖釋放了,要么就是壓根都沒辦法釋放鎖。

SET_IF_NOT_EXIST:看字面意思,如果 key 不存在,我們進(jìn)行Set操作,如果存在,啥都不干,也就不在進(jìn)行加鎖。

SET_WITH_EXPIRE_TIME:是否過期

expireTime:這是給 key 設(shè)置一個(gè)過期的時(shí)間,萬一你這業(yè)務(wù)一直被鎖著了,然后之后的業(yè)務(wù)想加鎖,你直接給一直持有這個(gè)這個(gè)鎖,不進(jìn)行過期之后的釋放,那豈不是要涼了。

上面的方法中 tryGetDistributedLock 這個(gè)方法也就是我們通常使用的加鎖的方法。

解鎖 

  
 
 
 
  1. public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) { 
  2.  
  3.         String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"; 
  4.         Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId)); 
  5.  
  6.         if ("OK".equals(result)) { 
  7.             return true; 
  8.         } 
  9.         return false; 
  10.  
  11.     } 

大家看到這個(gè) script的時(shí)候,會(huì)感覺有點(diǎn)奇怪,實(shí)際上他就是一個(gè) Lua 的腳本,而 Lua 腳本的意思也比較簡(jiǎn)單。

  1. 先獲取鎖對(duì)應(yīng)的value值,檢查是否與requestId相等
  2. 如果相等則刪除鎖(解鎖)
  3. 執(zhí)行eval()方法

其實(shí)這時(shí)候就有些人說,直接 del 刪除不行么?你試試你如果這么寫的話,你們的領(lǐng)導(dǎo)會(huì)不會(huì)把你的腿給你打斷。

這種不先判斷鎖的擁有者而直接解鎖的方式,會(huì)導(dǎo)致任何客戶端都可以隨時(shí)進(jìn)行解鎖,也就是說,這鎖就算不是我加的,我都能開,這怎么能行呢? 

在這里給大家放一段使用的代碼,比較簡(jiǎn)單,但是可以直接用到你們的項(xiàng)目當(dāng)中。 

  
 
 
 
  1. try{ 
  2. Boolean result = RedisPoolUtil.tryGetDistributedLock(jedis, "xxxxx", uuid, 5000); 
  3.  
  4. if(result) { 
  5.         xxxx代碼片段 
  6. }else{ 
  7.  
  8.  
  9. }catch(){ 
  10.  
  11. }finally{ 
  12. RedisPoolUtil.releaseDistributedLock(jedis,"xxxxx", uuid); 

分布式鎖的要求

  1. 滿足互斥性。也就是說不管在什么時(shí)候,只有一個(gè)客戶端能夠持有鎖,不能是多個(gè)客戶端。
  2. 不能出現(xiàn)死鎖。就是說,如果要實(shí)現(xiàn)分布式鎖,不能說當(dāng)一個(gè)鎖沒有釋放的時(shí)候,其他的客戶端不能進(jìn)行加鎖,要保證不影響其他的客戶端加鎖。
  3. 加鎖和解鎖必須是同一個(gè)客戶端

分布式的CAP理論

我們先把這個(gè)實(shí)現(xiàn)方式實(shí)現(xiàn)了,然后我們?cè)賮碚f說大家最不愿意看的理論知識(shí),畢竟這理論知識(shí)是你面試的時(shí)候經(jīng)常會(huì)被問到的。

分布式CAP理論:

加州大學(xué)伯克利分校的 Eric Brewer 教授在 ACM PODC 會(huì)議上提出 CAP 猜想。2年后,麻省理工學(xué)院的 Seth Gilbert 和 Nancy Lynch 從理論上證明了 CAP。之后,CAP 理論正式成為分布式計(jì)算領(lǐng)域的公認(rèn)定理。

也就是說,在二十年前的時(shí)候,CAP 理論只是個(gè)猜想。結(jié)果兩年之后被證實(shí)了,于是,大家在考慮分布式的時(shí)候,就有根據(jù)來想了,不再是空想了。

什么是分布式的 CAP 理論 ?

一個(gè)分布式系統(tǒng)最多只能同時(shí)滿足一致性(Consistency)、可用性(Availability)和分區(qū)容錯(cuò)性(Partition tolerance)這三項(xiàng)中的兩項(xiàng)。 

這個(gè)和(Atomicity)不太一樣,因?yàn)橹翱从行┤苏f,在 CAP 理論中的 A 和數(shù)據(jù)庫事務(wù)中的 A 是一樣的,單詞都不一樣,那能一樣么?

Availability :分布式中的 A 表示的是可用性,也就是說服務(wù)一直可用,而且是正常響應(yīng)時(shí)間。

而你在搭建分布式系統(tǒng)的時(shí)候,要保證每個(gè)節(jié)點(diǎn)都是穩(wěn)定的,不然你的可用性就沒有得到相對(duì)應(yīng)的保證,也談不上是什么分布式了。只能稱之為一個(gè)偽分布式。

Consistency: 一致性

也就是說你的更新操作成功并返回客戶端完成后,所有節(jié)點(diǎn)在同一時(shí)間的數(shù)據(jù)完全一致,這個(gè)如果你在使用 Redis 做數(shù)據(jù)展示的時(shí)候,很多面試官都會(huì)問你,那你們是怎么保證數(shù)據(jù)庫和緩存的一致性的呢?

畢竟你只是讀取的話,沒什么問題,但是設(shè)計(jì)到更新的時(shí)候,不管是先寫數(shù)據(jù)庫,再刪除緩存;還是先刪除緩存,再寫庫,都有可能出現(xiàn)數(shù)據(jù)不一致的情況。

所以如果你對(duì)這個(gè)很感興趣,可以研究一下,比如說:

  1. 延時(shí)雙刪策略
  2. 懶加載 懶加載可采取雙刪+TTL失效來實(shí)現(xiàn)
  3. 主動(dòng)加載

如果你能在面試的時(shí)候把這些都給面試官說清楚,至少感覺你應(yīng)該能達(dá)到你自己的工資要求。

Partition tolerance:分區(qū)容錯(cuò)性

分布式系統(tǒng)在遇到某節(jié)點(diǎn)或網(wǎng)絡(luò)分區(qū)故障的時(shí)候,仍然能夠?qū)ν馓峁M足一致性和可用性的服務(wù)。

其實(shí)在 CAP 理論當(dāng)中,我們是沒有辦法同時(shí)滿足一致性、可用性和分區(qū)容錯(cuò)性這三個(gè)特性,所以有所取舍就可以了。

關(guān)于使用 Redis 分布式鎖,大家學(xué)會(huì)了么?


分享文章:Redis怎么實(shí)現(xiàn)分布式鎖
當(dāng)前路徑:http://www.5511xx.com/article/coghjih.html