分佈式鎖專題-分佈式鎖入門

1.引入業務場景

業務場景一

因爲小T剛接手項目,正在吭哧吭哧對熟悉着代碼、部署架構。在看代碼過程中發現,下單這塊代碼可能會出現問題,這可是分佈式部署的,如果多個用戶同時購買同一個商品,就可能導致商品出現 庫存超賣 (數據不一致) 現象,對於這種情況代碼中並沒有做任何控制。

原來一問才知道,以前他們都是售賣的虛擬商品,沒啥庫存一說,所以當時沒有考慮那麼多…

這次不一樣啊,這次是售賣的實體商品,那就有庫存這麼一說了,起碼要保證不能超過庫存設定的數量吧。

小T大眼對着屏幕,屏住呼吸,還好提前發現了這個問題,趕緊想辦法修復,不賺錢還賠錢,老闆不得瘋了,還想不想幹了~

業務場景二

小T下面的一位兄弟正在壓測,發現個小問題,因爲在終端設備上跟鵝廠有緊密合作,調用他們的接口時需要獲取到access_token,但是這個access_token過期時間是2小時,過期後需要重新獲取。

壓測時發現當到達過期時間時,日誌看刷出來好幾個不一樣的access_token,因爲這個服務也是分佈式部署的,多個節點同時發起了第三方接口請求導致。

雖然以最後一次獲取的access_token爲準,也沒什麼不良副作用,但是會導致多次不必要的對第三方接口的調用,也會短時間內造成access_token的 重複無效獲取(重複工作)。

以上便於大家理解爲什麼要用分佈式鎖才能解決,勾勒出的幾個業務場景。上面的問題無一例外,都是針對共享資源要求串行化處理,才能保證安全且合理的操作。

用一張圖來體驗一下:
在這裏插入圖片描述
此時,使用Java提供的SynchronizedReentrantLockReentrantReadWriteLock…,僅能在單個JVM進程內對多線程對共享資源保證線程安全,在分佈式系統環境下統統都不好使,心情是不是拔涼呀。這個問題得請教 分佈式鎖 家族來支持一下,聽說他們家族內有很多成員,每個成員都有這個分佈式鎖功能,接下來就開始探索一下。

2.分佈式鎖概述

2.1.爲什麼需要分佈式鎖才能解決?

聽聽 Martin 大佬們給出的說法,請你自己看 Maritin 博客文章:

https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html

Martin kleppmann 是英國劍橋大學的分佈式系統的研究員,曾經跟 Redis 之父 Antirez 進行過關於 RedLock (Redis裏分佈式鎖的實現算法)是否安全的激烈討論。

2.2.分佈式鎖考慮的問題

效率
使用分佈式鎖可以避免多個客戶端重複相同的工作,這些工作會浪費資源。

比如業務場景二,重複獲取access_token。

對共享資源的操作是冪等性操作,無論你操作多少次都不會出現不同結果。
本質上就是爲了避免對共享資源重複操作,從而提高效率。

正確性:

使用分佈式鎖同樣可以避免鎖失效的發生,一旦發生會引起正確性的破壞,可能會導致數據不一致,數據缺失或者其他嚴重的問題。

2.3.分佈式鎖特點

以下是分佈式鎖的一些特點,分佈式鎖家族成員並不一定都滿足這個要求,實現機制不大一樣。

互斥性: 分佈式鎖要保證在多個客戶端之間的互斥。
可重入性:同一客戶端的相同線程,允許重複多次加鎖。
鎖超時:和本地鎖一樣支持鎖超時,防止死鎖。
非阻塞: 能與 ReentrantLock 一樣支持 trylock() 非阻塞方式獲得鎖。
支持公平鎖和非公平鎖:公平鎖是指按照請求加鎖的順序獲得鎖,非公平鎖真好相反請求加鎖是無序的。

3.分佈式鎖家族實現者介紹

分佈式鎖家族實現者一覽:

在這裏插入圖片描述
下面讓他們分別來做下自我介紹:

3.1.數據庫實現

排它鎖(悲觀鎖)

基於 select * from table where xx=yy for update SQL語句來實現,有很多缺陷,一般不推薦使用。

樂觀鎖

表中添加一個時間戳或者版本號的字段來實現,update xx set version = new... where id = y and version = old 當更新不成功,客戶端重試,重新讀取最新的版本號或時間戳,再次嘗試更新,類似 CAS 機制,推薦使用。

3.2.Redis實現

特點:CAP模型屬於AP | 無一致性算法 | 性能好

開發常用,如果你的項目中正好使用了redis,不想引入額外的分佈式鎖組件,推薦使用。

業界也提供了多個現成好用的框架予以支持分佈式鎖,比如Redisson、spring-integration-redis、redis自帶的setnx命令,推薦直接使用。

另外,可基於redis命令和redis lua支持的原子特性,自行實現分佈式鎖。

3.3.Zookeeper

特點:CAP模型屬於CP | ZAB一致性算法實現 | 穩定性好

開發常用,如果你的項目中正好使用了zk集羣,推薦使用。

業界有Apache Curator框架提供了現成的分佈式鎖功能,現成的,推薦直接使用。

另外,可基於Zookeeper自身的特性和原生Zookeeper API自行實現分佈式鎖。

3.4.其他

Chubby,Google開發的粗粒度分佈鎖的服務,但是並沒有開源,開放出了論文和一些相關文檔可以進一步瞭解,出門百度一下獲取文檔。

Tair,是阿里開源的一個分佈式KV存儲方案。

Etcd,CAP模型中屬於CP,Raft一致性算法實現。

Hazelcast,是基於內存的數據網格開源項目,提供彈性可擴展的分佈式內存計算,並且被公認是提高應用程序性能和擴展性最好的方案,聽上去很牛逼。

當然了,上面推薦的常用分佈式鎖Zookeeper和Redis,使用時還需要根據具體的業務場景,做下權衡,實現功能上都能達到你要的效果,原理上有很大的不同。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章