日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

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

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

分布式鎖使用場景

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

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

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

手寫分布式鎖

手寫Redis分布式鎖

 

Zookeeper鎖示意圖

手寫Redis分布式鎖

 

當然市面已經有成熟的框架去實現分布式鎖了,不需要你重復造輪子了。

手寫Redis分布式鎖

 

分布式鎖實現

Redis分布式鎖底層分析

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

手寫Redis分布式鎖

 

Redis分布式鎖底層

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

手寫Redis分布式鎖

編寫加鎖方法

手寫Redis分布式鎖

 

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

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

scriptLock為執行的Redis命令,里面是Lua腳本

手寫Redis分布式鎖

 

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

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

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

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

如果失敗,則一直循環拿鎖,直到成功。

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

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

編寫釋放鎖的方法

手寫Redis分布式鎖

 

執行scriptLock2,Lua腳本如下:

手寫Redis分布式鎖

 

測試代碼

手寫Redis分布式鎖

 

測試結果

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節點數據還沒同步到Slave節點,Slave節點就掛了,下次Slave節點好了之后,就沒有保存鎖的數據,從而導致鎖失效。那該怎么辦?

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

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

 

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

Redis分布式鎖缺點

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

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

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

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

文中涉及的源碼見Github

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

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

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

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

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

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

運動步數有氧達人2018-06-03

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

每日養生app2018-06-03

每日養生,天天健康

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

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