WLock
● 項(xiàng)目名稱:WLock
● Github地址:
https://github.com/wuba/WLock.git
● 簡(jiǎn)介:WLock是一套基于58已開源的一致性算法組件WPaxos實(shí)現(xiàn)的高可靠、高吞吐分布式鎖服務(wù),可應(yīng)用于分布式環(huán)境下協(xié)調(diào)多進(jìn)程/線程對(duì)共享資源的訪問(wèn)控制、多節(jié)點(diǎn)Master選主等業(yè)務(wù)場(chǎng)景。
核心特性
豐富的鎖類型:可重入鎖、公平鎖、優(yōu)先級(jí)鎖、讀寫鎖、進(jìn)程鎖、線程鎖;
靈活的鎖操作:支持阻塞/非阻塞、同步/異步watch等方式獲取鎖,支持鎖續(xù)約,TTL等機(jī)制;
高可靠性:基于Paxos算法實(shí)現(xiàn)多副本數(shù)據(jù)同步,Master節(jié)點(diǎn)故障時(shí)主從自動(dòng)切換,在無(wú)Master或者M(jìn)aster漂移過(guò)程仍可保證鎖狀態(tài)的持續(xù)一致性,不影響正常鎖操作;
高吞吐:多Paxos分組的Master均勻分布在所有集群節(jié)點(diǎn),不同Paxos分組的鎖操作并行處理,相同Paxos分組鎖操作批量合并處理,大大提升了系統(tǒng)的吞吐量;
多租戶:提供秘鑰作為集群分配、鎖操作隔離、權(quán)限控制的租戶單位,支持單個(gè)秘鑰跨集群動(dòng)態(tài)平滑遷移;
易用性:豐富的鎖接口封裝,開箱即用;
01 項(xiàng)目背景
在分布式部署的應(yīng)用集群中,經(jīng)常會(huì)存在一些業(yè)務(wù)場(chǎng)景,為了保證某些業(yè)務(wù)邏輯的準(zhǔn)確性,或者避免某些邏輯被重復(fù)執(zhí)行,需要限制多個(gè)應(yīng)用進(jìn)程或線程對(duì)共享數(shù)據(jù)資源進(jìn)行互斥訪問(wèn),例如秒殺下單、商品搶購(gòu)等場(chǎng)景,通常的解決方案是引入分布式鎖技術(shù)。
對(duì)于一些比較復(fù)雜的分布式場(chǎng)景,除了要求分布式鎖具有互斥性、避免死鎖、可重入等基本特性外,同時(shí)對(duì)分布式鎖服務(wù)的吞吐性能、數(shù)據(jù)一致性、可靠性等方面也有很強(qiáng)的要求,了解CAP理論的都知道,這是分布式系統(tǒng)設(shè)計(jì)的難點(diǎn)。當(dāng)前已有的分布式鎖解決方案,也很難同時(shí)滿足這幾個(gè)特性,通常需要做出取舍,如基于Redis封裝實(shí)現(xiàn)的分布式鎖犧牲數(shù)據(jù)強(qiáng)一致性來(lái)保證吞吐量,或基于Zookeeper、Etcd封裝實(shí)現(xiàn)的分布式鎖犧牲一定的可用性保證數(shù)據(jù)強(qiáng)一致性。本項(xiàng)目希望提供一種分布式鎖方案,不僅滿足高吞吐的業(yè)務(wù)場(chǎng)景需求,還能夠保證服務(wù)具有比較高的可用性和可靠性。
02 設(shè)計(jì)實(shí)踐
功能架構(gòu)如下:
目前開源的模塊主要包括負(fù)責(zé)鎖核心交互的客戶端、服務(wù)端,以及負(fù)責(zé)配置管理的注冊(cè)中心三部分。其中核心實(shí)現(xiàn)有以下幾個(gè)部分:
2.1 可靠存儲(chǔ)設(shè)計(jì)
WLock選擇高吞吐的鍵值存儲(chǔ)系統(tǒng)RocksDB來(lái)持久化鎖的狀態(tài)信息,基于WPaxos組件實(shí)現(xiàn)多副本數(shù)據(jù)同步以及主從自動(dòng)切換能力;每個(gè)節(jié)點(diǎn)配置相同數(shù)量的Paxos分組,客戶端根據(jù)鎖名稱,將鎖哈希到某一個(gè)固定Paxos分組,默認(rèn)將鎖請(qǐng)求發(fā)送到該P(yáng)axos分組對(duì)應(yīng)的Master節(jié)點(diǎn),鎖狀態(tài)更新時(shí),由Master節(jié)點(diǎn)發(fā)起Propose請(qǐng)求同步給其它Slave節(jié)點(diǎn),最終在執(zhí)行狀態(tài)機(jī)時(shí)寫入RocksDB,保證多副本數(shù)據(jù)的強(qiáng)一致性,如下圖所示:
我們知道Zookeeper、Etcd同樣也采用一致性協(xié)議實(shí)現(xiàn)多副本可靠存儲(chǔ),但不同的是,它們只有單個(gè)Zab或Raft實(shí)例串行同步數(shù)據(jù),而WLock采用多Paxos分組機(jī)制,不同分組的Master在集群中均勻分布,集群節(jié)點(diǎn)對(duì)等部署,可并行同步數(shù)據(jù),大大提升了系統(tǒng)的吞吐能力;另外,得益于Paxos協(xié)議的靈活性,不對(duì)Master強(qiáng)依賴,當(dāng)Master節(jié)點(diǎn)關(guān)閉或者出現(xiàn)異常時(shí),未選出新的Master之前,可將鎖操作請(qǐng)求發(fā)送到指定的候選節(jié)點(diǎn)來(lái)處理,保證系統(tǒng)持續(xù)提供服務(wù),具有更高的可用性。
2.2 鎖操作實(shí)現(xiàn)
WLock封裝提供了豐富的鎖類型如可重入鎖、公平鎖、優(yōu)先級(jí)鎖、讀寫鎖等,下面以可重入鎖為例,介紹下加鎖/釋放鎖實(shí)現(xiàn)。
阻塞/非阻塞獲取鎖
WLock提供有阻塞與非阻塞方式獲取鎖,區(qū)別在于是否等待服務(wù)端加鎖成功。非阻塞方式根據(jù)服務(wù)端鎖當(dāng)時(shí)的狀態(tài),直接返回客戶端加鎖成功或失敗;而阻塞方式在鎖已被其它owner搶占的情況下,會(huì)在服務(wù)端內(nèi)存注冊(cè)一個(gè)WatchEvent事件等待獲取鎖,當(dāng)鎖被釋放時(shí),服務(wù)端立即從Watch等待隊(duì)列中選擇一個(gè)優(yōu)先級(jí)最高的WatchEvent直接執(zhí)行加鎖,并通知喚醒監(jiān)聽的客戶端。
相對(duì)于其它分布式鎖通過(guò)客戶端定時(shí)輪詢實(shí)現(xiàn)的阻塞機(jī)制,WLock的阻塞機(jī)制在鎖競(jìng)爭(zhēng)度比較高時(shí),獲取鎖的延遲低、實(shí)時(shí)性更強(qiáng),還能夠更好支持優(yōu)先級(jí)鎖,但也存在一個(gè)缺陷,WatchEvent長(zhǎng)期存儲(chǔ)于服務(wù)端緩存隊(duì)列,若客戶端所在機(jī)器宕機(jī)或者出現(xiàn)一些網(wǎng)絡(luò)異常,服務(wù)端不能及時(shí)感知到客戶端異常變化時(shí),掛起在服務(wù)端的WatchEvent變?yōu)闊o(wú)效狀態(tài)且不會(huì)被立即剔除,這時(shí)喚醒該WatchEvent加鎖成功后,不能成功通知到客戶端,鎖過(guò)期前又不能被其它客戶端搶占。為此,WLock引入兩種機(jī)制來(lái)優(yōu)化這個(gè)問(wèn)題,
1)WatchEvent添加心跳;顧C(jī)制。客戶端每隔20s定時(shí)向服務(wù)端發(fā)起WatchEvent心跳,服務(wù)端接收到后,發(fā)現(xiàn)WatchEvent已存在,便延長(zhǎng)WatchEvent的有效時(shí)間,服務(wù)端定時(shí)檢測(cè)內(nèi)存中WatchEvent是否有效,做過(guò)期剔除處理。
2)通過(guò)監(jiān)聽WatchEvent獲取到鎖時(shí),客戶端首先進(jìn)行續(xù)約Touch。服務(wù)端在選擇WatchEvent執(zhí)行加鎖時(shí),會(huì)先把鎖的過(guò)期時(shí)間調(diào)整為Math.min(鎖真實(shí)過(guò)期時(shí)間,10s),客戶端收到加鎖成功通知后需要立即發(fā)起續(xù)約Touch,服務(wù)端收到續(xù)約請(qǐng)求后再延長(zhǎng)鎖的過(guò)期時(shí)間為客戶端接口設(shè)置的真實(shí)過(guò)期時(shí)間。這樣,若通知的客戶端已不活躍,最長(zhǎng)阻塞10s鎖不能被其它客戶端搶占。
該WatchEvent處理機(jī)制,同樣應(yīng)用于異步Watch方式的加鎖處理。
可重入實(shí)現(xiàn)
WLock可重入機(jī)制是由客戶端通過(guò)鎖上下文中的AcquireCount原子變量計(jì)數(shù)控制,第一次獲取鎖時(shí)請(qǐng)求服務(wù)端加鎖,成功后進(jìn)行本地計(jì)數(shù),其它情況下,將加鎖請(qǐng)求轉(zhuǎn)為續(xù)約鎖請(qǐng)求發(fā)送到服務(wù)端;釋放鎖過(guò)程,只有AcquireCount小于等于0時(shí),才向服務(wù)端釋放鎖,否則只是本地計(jì)數(shù)減一處理。這樣設(shè)計(jì)考慮的是,若在服務(wù)端計(jì)數(shù)控制,在某些異常情況下,當(dāng)返回客戶端的加鎖請(qǐng)求超時(shí),實(shí)際服務(wù)端執(zhí)行加鎖計(jì)數(shù)成功時(shí),可能會(huì)導(dǎo)致客戶端與服務(wù)端重入鎖計(jì)數(shù)不一致而產(chǎn)生死鎖。
TTL機(jī)制
為了避免死鎖,服務(wù)端要求每個(gè)鎖都設(shè)有過(guò)期時(shí)間,過(guò)期時(shí)間需要根據(jù)客戶端對(duì)共享資源正常訪問(wèn)時(shí)間合理設(shè)置。如果設(shè)置太短,有可能在客戶端完成對(duì)共享資源訪問(wèn)之前,鎖就發(fā)生過(guò)期,從而破壞鎖的安全性;如果設(shè)置太長(zhǎng),一旦某個(gè)持有鎖的客戶端釋放鎖失敗,就會(huì)導(dǎo)致一段時(shí)間內(nèi)其它客戶端都無(wú)法獲到取到鎖。
WLock服務(wù)端限制鎖的過(guò)期時(shí)間最多為5分鐘,但是對(duì)客戶端設(shè)置的鎖過(guò)期時(shí)間則不做限制,對(duì)于過(guò)期時(shí)間超過(guò)5分鐘的加鎖請(qǐng)求,通過(guò)自動(dòng)定時(shí)續(xù)約來(lái)延長(zhǎng)鎖的過(guò)期時(shí)間,客戶端發(fā)送到服務(wù)端的加鎖和續(xù)約鎖請(qǐng)求中,攜帶的鎖過(guò)期時(shí)間最大也只能為5分鐘。自動(dòng)續(xù)約周期默認(rèn)為Math.min(鎖過(guò)期時(shí)間,5分鐘)的1/3(最小為1秒),這樣在鎖過(guò)期前,允許客戶端至少有兩次容錯(cuò)機(jī)會(huì)。
WLock計(jì)算過(guò)期時(shí)間戳的方式是[加鎖成功的起始時(shí)間/續(xù)約鎖成功的起始時(shí)間+鎖過(guò)期時(shí)間],鎖過(guò)期檢測(cè)嚴(yán)格依賴機(jī)器時(shí)鐘,為了避免集群服務(wù)節(jié)點(diǎn)間的時(shí)鐘差異,導(dǎo)致不同節(jié)點(diǎn)計(jì)算鎖過(guò)期觸發(fā)時(shí)機(jī)不一致,WLock限制服務(wù)端只有Master節(jié)點(diǎn)主動(dòng)檢測(cè)鎖的過(guò)期狀態(tài),檢測(cè)到鎖過(guò)期時(shí),由Master發(fā)起Propose請(qǐng)求同步Slave節(jié)點(diǎn)對(duì)過(guò)期鎖進(jìn)行刪除處理,并將ExpireEvent通知到客戶端,降低了時(shí)鐘不一致對(duì)鎖服務(wù)的影響。由于鎖過(guò)期檢測(cè)Task僅存儲(chǔ)在Master內(nèi)存,當(dāng)Master發(fā)生漂移時(shí),新的Master需要從RocksDB中重新加載分組下所有Lockkey信息,生成鎖過(guò)期檢測(cè)Task分發(fā)到根據(jù)過(guò)期時(shí)間排序的優(yōu)先級(jí)隊(duì)列,并恢復(fù)檢測(cè)任務(wù),這個(gè)過(guò)程通常在幾秒內(nèi)完成,這期間可能會(huì)導(dǎo)致服務(wù)端檢測(cè)鎖過(guò)期存在延遲。為了不受服務(wù)端或網(wǎng)絡(luò)異常影響,WLock客戶端同時(shí)也開啟有鎖的過(guò)期檢測(cè)任務(wù),鎖過(guò)期時(shí)間比服務(wù)端延遲了加鎖或續(xù)約請(qǐng)求Response網(wǎng)絡(luò)返回時(shí)間,客戶端對(duì)于過(guò)期回調(diào)的執(zhí)行做了冪等判斷,避免并發(fā)重復(fù)執(zhí)行。
大神 Martin Kleppmann在文章《How to do distributed locking》中對(duì)分布式鎖原理進(jìn)行論證時(shí),指出Redlock可能存在的安全問(wèn)題:當(dāng)客戶端獲取到鎖后發(fā)生GC pause或者服務(wù)端出現(xiàn)時(shí)鐘回退,有可能在鎖持有者釋放鎖之前,鎖就發(fā)生過(guò)期,此時(shí)如果另外一個(gè)客戶端搶占到鎖,鎖的互斥性會(huì)被破壞。WLock同樣是引入了鎖版本號(hào)(fencing token)來(lái)解決這個(gè)問(wèn)題,但是需要用戶自己在訪問(wèn)共享資源時(shí),攜帶并比較當(dāng)前資源更新操作的鎖最大版本號(hào)(類似于樂(lè)觀鎖機(jī)制),再結(jié)合事務(wù)機(jī)制保證數(shù)據(jù)操作的一致性。
續(xù)約機(jī)制
WLock支持主動(dòng)和自動(dòng)兩種續(xù)約機(jī)制,主動(dòng)續(xù)約機(jī)制可通過(guò)客戶端調(diào)用續(xù)約接口觸發(fā),自動(dòng)續(xù)約機(jī)制可在加鎖時(shí)通過(guò)參數(shù)配置啟動(dòng)。由于續(xù)約線程與鎖持有線程通常為兩個(gè)線程,自動(dòng)續(xù)約機(jī)制存在一定的安全風(fēng)險(xiǎn),業(yè)務(wù)在加鎖處理邏輯的外層finally邏輯中一定要釋放鎖(遠(yuǎn)程釋放鎖前,會(huì)先停止自動(dòng)續(xù)約任務(wù)),否則鎖持有線程異常退出時(shí),鎖自動(dòng)續(xù)約還會(huì)一直執(zhí)行,導(dǎo)致鎖永遠(yuǎn)不過(guò)期,出現(xiàn)死鎖。
事件補(bǔ)償
WLock通過(guò)[Host, Pid,ThreadID]來(lái)定義一個(gè)鎖Owner,ThreadID為-1時(shí)鎖為進(jìn)程粒度,否則為線程粒度。鎖owner不會(huì)隨著客戶端與服務(wù)端連接狀態(tài)的更新而變化,但鎖狀態(tài)發(fā)生變更時(shí),服務(wù)端會(huì)向鎖owner或者鎖監(jiān)聽者主動(dòng)推送一些事件如WatchEvent、ExpireEvent,為此,服務(wù)端需要維護(hù)鎖owner或鎖監(jiān)聽者與客戶端連接的對(duì)應(yīng)關(guān)系。
當(dāng)WLock服務(wù)端Master發(fā)生漂移或者網(wǎng)絡(luò)連接異常重連時(shí),客戶端連接綁定關(guān)系會(huì)同時(shí)發(fā)生變更,此時(shí)就需要客戶端主動(dòng)進(jìn)行事件補(bǔ)償,補(bǔ)償類型包括兩種:
1)WatchEvent事件補(bǔ)償,重新向服務(wù)端注冊(cè)監(jiān)聽事件,服務(wù)端更新WatchEvent與客戶端連接綁定關(guān)系。
2)AcquireEvent事件補(bǔ)償,客戶端對(duì)已持有的鎖進(jìn)行續(xù)約,服務(wù)端收到請(qǐng)求后不更新鎖的過(guò)期時(shí)間,只更新鎖owner與客戶端連接的對(duì)應(yīng)關(guān)系。
2.3. 高并發(fā)優(yōu)化
前面提到,WLock通過(guò)引入多Paxos分組,多節(jié)點(diǎn)互為主備對(duì)等部署并行同步數(shù)據(jù)的集群架構(gòu),已經(jīng)一定程度上提升了系統(tǒng)的吞吐能力。此外,Wlock還充分利用了WPaxos組件批量Propose的功能,對(duì)單分組的鎖操作實(shí)現(xiàn)做了以下優(yōu)化,進(jìn)一步提升了系統(tǒng)的并發(fā)處理能力:
1)單個(gè)Paxos分組采用多線程并行處理鎖請(qǐng)求,相同Lockkey的鎖請(qǐng)求哈希到同一個(gè)線程串行處理;
2)對(duì)單個(gè)Paxos分組下不同線程阻塞的鎖請(qǐng)求進(jìn)行合并,批量發(fā)起Propose同步數(shù)據(jù),降低了網(wǎng)絡(luò)傳輸與多任務(wù)調(diào)用切換成本。
03 為什么選擇WLock
在分布式領(lǐng)域中,分布式鎖已經(jīng)是一種比較成熟的技術(shù),現(xiàn)有的實(shí)現(xiàn)方案已有很多,為什么還開發(fā)WLock,優(yōu)勢(shì)又有哪些?接下來(lái)我們從功能、服務(wù)特性、性能三個(gè)維度,介紹下常見的幾種分布式鎖的差異點(diǎn)。
功能
服務(wù)特性
性能
測(cè)試運(yùn)行環(huán)境
機(jī)器配置:CPU:20 x Intel(R) Xeon(R) Silver 4114 CPU @ 2.20GHz
內(nèi)存:192 GB
硬盤:SSD
網(wǎng)卡:萬(wàn)兆網(wǎng)卡
服務(wù)端集群機(jī)器個(gè)數(shù):3臺(tái)
測(cè)試結(jié)果
1. 單客戶端qps:
2. 相同并發(fā)下,請(qǐng)求響應(yīng)延遲(單位ms)
說(shuō)明:以上對(duì)比測(cè)試的中數(shù)據(jù),Redis、ZK、Etcd相關(guān)非官方數(shù)據(jù),均由我們?cè)谙嗤h(huán)境下實(shí)際壓測(cè)得到。其中,對(duì)于QPS的統(tǒng)計(jì),客戶端請(qǐng)求一次加鎖再請(qǐng)求一次釋放鎖合并為一次計(jì)數(shù),更詳細(xì)的壓測(cè)數(shù)據(jù)及壓測(cè)條件可查看開源對(duì)比文檔。
通過(guò)以上幾個(gè)維度的測(cè)試分析,WLock的優(yōu)勢(shì)在于可靠性與系統(tǒng)吞吐量比較高,處理延遲略低于Redis,但明顯高于Zookeeper與Etcd,為此,對(duì)于分布式鎖選型有以下建議:
對(duì)可靠性要求不高,響應(yīng)延遲比較敏感的場(chǎng)景,鎖并發(fā)低于3W時(shí)可使用Redis,高于3W建議用WLock;
對(duì)可靠性要求比較高,同時(shí)鎖并發(fā)高于500的場(chǎng)景,可使用WLock;
04 未來(lái)規(guī)劃
1. 提供GO、PHP、Node等多語(yǔ)言SDK
2. 開源WEB管控中心、監(jiān)控模塊
3. 支持分布式信號(hào)量機(jī)制
參考資料
WPaxos源碼地址:https://github.com/wuba/WPaxos
開源|WPaxos:一致性算法Paxos的生產(chǎn)級(jí)高性能Java實(shí)現(xiàn):https://mp.weixin.qq.com/s/bydpMwTWAamS3u8Ko57iYg
How to do distributed locking:
https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html
作者簡(jiǎn)介
劉丹,58同城后端架構(gòu)師,58分布式消息隊(duì)列、分布式鎖、分布式鏈路追蹤等系統(tǒng)負(fù)責(zé)人
文章內(nèi)容僅供閱讀,不構(gòu)成投資建議,請(qǐng)謹(jǐn)慎對(duì)待。投資者據(jù)此操作,風(fēng)險(xiǎn)自擔(dān)。
2024年的Adobe MAX 2024發(fā)布會(huì)上,Adobe推出了最新版本的Adobe Creative Cloud。
奧維云網(wǎng)(AVC)推總數(shù)據(jù)顯示,2024年1-9月明火炊具線上零售額94.2億元,同比增加3.1%,其中抖音渠道表現(xiàn)優(yōu)異,同比有14%的漲幅,傳統(tǒng)電商略有下滑,同比降低2.3%。
“以前都要去窗口辦,一套流程下來(lái)都要半個(gè)月了,現(xiàn)在方便多了!”打開“重慶公積金”微信小程序,按照提示流程提交相關(guān)材料,僅幾秒鐘,重慶市民曾某的賬戶就打進(jìn)了21600元。
華碩ProArt創(chuàng)藝27 Pro PA279CRV顯示器,憑借其優(yōu)秀的性能配置和精準(zhǔn)的色彩呈現(xiàn)能力,為您的創(chuàng)作工作帶來(lái)實(shí)質(zhì)性的幫助,雙十一期間低至2799元,性價(jià)比很高,簡(jiǎn)直是創(chuàng)作者們的首選。
9月14日,2024全球工業(yè)互聯(lián)網(wǎng)大會(huì)——工業(yè)互聯(lián)網(wǎng)標(biāo)識(shí)解析專題論壇在沈陽(yáng)成功舉辦。