亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務,提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

分布式鎖使用場景

現(xiàn)在的系統(tǒng)都是集群部署,每個服務都不是單節(jié)點的了。比如庫存服務,可能部署到3臺機器上分別命名為節(jié)點1,節(jié)點2,節(jié)點3。庫存服務需要扣減庫存,扣減庫存肯定需要鎖吧,如果使用Lock或者synchronized,只能鎖住自己的節(jié)點。而從前臺訪問是隨機路由到這3臺節(jié)點的。如果線程一進來使節(jié)點1上了鎖,當線程二進來可能訪問到的是節(jié)點2,這時節(jié)點2還沒有上鎖,那么庫存就會扣減錯誤。而庫存扣減還是一個核心操作,現(xiàn)在居然有Bug,想想就可怕。

這時我們就需要一個全局的鎖了。

實現(xiàn)全局的鎖不一定是redis。MySQL,Zookeeper也可設計為分布式鎖。本篇主要講的是Redis分布式鎖的實現(xiàn)方式,其他的實現(xiàn)方式不做講解。MySQL用作分布式鎖在性能上并不好,這里不建議使用。對Zookeeper分布式鎖有興趣的可以看看我寫的這篇文章。

手寫分布式鎖

手寫Redis分布式鎖

 

Zookeeper鎖示意圖

手寫Redis分布式鎖

 

當然市面已經(jīng)有成熟的框架去實現(xiàn)分布式鎖了,不需要你重復造輪子了。

手寫Redis分布式鎖

 

分布式鎖實現(xiàn)

Redis分布式鎖底層分析

記得之前面試被問Redis分布式鎖的底層原理,我是這么回答的

手寫Redis分布式鎖

 

Redis分布式鎖底層

setnx保證鎖的唯一性。過期時間保證鎖在異常情況下也能解鎖。采用Lua腳本操作Redis,使操作具有原子性。后臺進程心跳檢測,如果當前時間持有鎖并且鎖還未失效,延長鎖的失效時間。如果當前線程沒有獲取到鎖,會一直自旋,直到獲取到鎖為止。

手寫Redis分布式鎖

編寫加鎖方法

手寫Redis分布式鎖

 

我們來看看這段代碼,redisTemplate.execute參數(shù)解釋如下

String result = (String) redisTemplate.execute(scriptLock,
        redisTemplate.getStringSerializer(),        redisTemplate.getStringSerializer(),        Collections.singletonList(key),        uuid.toString(),        String.valueOf(timeOut));

scriptLock為執(zhí)行的Redis命令,里面是Lua腳本

手寫Redis分布式鎖

 

腳本里面有setnx操作,還設置了超時時間。

兩個redisTemplate.getStringSerializer()為key和value序列化工具。

后面3個參數(shù)為設置key,設置value,設置超時時間。分別對應Lua腳本中的KEYS[1],ARGV[1],ARGV[2]。

如果setnx操作成功,說明鎖創(chuàng)建成功,返回new RedisLock(key, uuid.toString())。

如果失敗,則一直循環(huán)拿鎖,直到成功。

另外,這里的value為隨機生成的uuid,這是為什么呢?

因為如果某個客戶端獲取到了鎖,但是阻塞了很長時間才執(zhí)行完,此時可能已經(jīng)自動釋放鎖了,此時可能別的客戶端已經(jīng)獲取到了這個鎖,要是你這個時候直接刪除key的話會有問題,所以得用隨機值加上面的Lua腳本來釋放鎖。

編寫釋放鎖的方法

手寫Redis分布式鎖

 

執(zhí)行scriptLock2,Lua腳本如下:

手寫Redis分布式鎖

 

測試代碼

手寫Redis分布式鎖

 

測試結(jié)果

2020-08-29 20:54:43.484  INFO 21880 --- [main] com.lvshen.demo.RedisLockTest            : 獲得鎖
2020-08-29 20:54:49.532  INFO 21880 --- [main] com.lvshen.demo.RedisLockTest            : 未獲得鎖

這里沒有做可重入功能,所以第二次訪問的時候,鎖還沒有釋放,所以未獲得鎖。

我們畫一個流程圖,完善下上面的流程

手寫Redis分布式鎖

 

Redis鎖邏輯

有關Redis主從同步問題

在Redis集群中,如果Master節(jié)點數(shù)據(jù)還沒同步到Slave節(jié)點,Slave節(jié)點就掛了,下次Slave節(jié)點好了之后,就沒有保存鎖的數(shù)據(jù),從而導致鎖失效。那該怎么辦?

這個場景是假設有一個Redis Cluster,有5個Redis Master實例。然后執(zhí)行如下步驟獲取一把鎖:

  • 獲取當前時間戳,單位是毫秒
  • 跟上面類似,輪流嘗試在每個Master節(jié)點上創(chuàng)建鎖,過期時間較短,一般就幾十毫秒
  • 嘗試在大多數(shù)節(jié)點上建立一個鎖,比如5個節(jié)點就要求是3個節(jié)點(n / 2 +1)
  • 客戶端計算建立好鎖的時間,如果建立鎖的時間小于超時時間,就算建立成功了
  • 要是鎖建立失敗了,那么就依次刪除這個鎖
  • 只要別人建立了一把分布式鎖,你就得不斷輪詢?nèi)L試獲取鎖
手寫Redis分布式鎖

 

當超半數(shù)的主從同步成功了,才能判定為上鎖成功。

Redis分布式鎖缺點

我們來說說Redis分布式鎖的缺點:

Redis分布式鎖,其實需要自己不斷去嘗試獲取鎖,比較消耗性能。

如果是Redis獲取鎖的那個客戶端出Bug了或者掛了,那么只能等待超時時間之后才能釋放鎖。

Redis主從同步RedLock算法存在缺陷,鎖的續(xù)命設計也很麻煩。

文中涉及的源碼見Github

https://github.com/lvshen9/demo/tree/lvshen-dev/src/main/JAVA/com/lvshen/demo/redis/dislock

分享到:
標簽:分布式 Redis
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定