這才是真正的分布式鎖

2018-09-06 18:04 更新

技術(shù)領(lǐng)域,我覺得了解來龍去脈,了解本質(zhì)原理,比用什么工具實現(xiàn)更重要

(1)進程多線程如何互斥?

(2)一個手機上兩個APP訪問一個文件如何互斥?

(3)分布式環(huán)境下多個服務(wù)訪問一個資源如何互斥?

歸根結(jié)底,是利用一個互斥方能夠訪問的公共資源來實現(xiàn)分布式鎖,具體這個公共資源是redis來setnx,還是zookeeper,相反沒有這么重要。


言歸正傳,今天把昨天文章的緣起講一講,并通過Google Chubby的論文閱讀筆記聊一聊分布式鎖。

一、需求緣起

58到家APP新上線了導(dǎo)入通訊錄好友功能,測試的同學(xué)發(fā)現(xiàn),連續(xù)點擊導(dǎo)入會導(dǎo)入重復(fù)數(shù)據(jù):

數(shù)據(jù)重復(fù)導(dǎo)入
客戶端同一個用戶同時發(fā)出了多個請求,分布式環(huán)境下,多臺機器上部署的多個service進行了并發(fā)操作,故插入了冗余數(shù)據(jù)。

解決思路同一個用戶同時只能有一個導(dǎo)入請求,需要做互斥,最簡易的方案,使用setnx快速解決。
使用setnx解決數(shù)據(jù)重復(fù)

(1)同一個用戶,多個service進行并發(fā)操作,service需要先去搶鎖

(2)搶到鎖的service,才去數(shù)據(jù)庫操作

具體這個鎖用setnx,還是zookeeper都不太重要,利用一個互斥方能夠訪問的公共資源來實現(xiàn)分布式鎖,這才是《一分鐘實現(xiàn)分布式鎖》的重點。


二、Google Chubby分布式鎖閱讀筆記

上一篇文章的評論中,有些朋友提到了zookeeper,會使用不夠,借著Google Chubby了解下分布式鎖的實現(xiàn)也是有必要的。


早年Google的四大基礎(chǔ)設(shè)施,分別是GFS、MapReduce、BigTable、Chubby,其中Chubby用于提供分布式的鎖服務(wù)

1.簡介

Chubby系統(tǒng)提供粗粒度的分布式鎖服務(wù),Chubby的使用者不需要關(guān)注復(fù)雜的同步協(xié)議,而是通過已經(jīng)封裝好的客戶端直接調(diào)用Chubby的鎖服務(wù),就可以保證數(shù)據(jù)操作的一致性。


Chubby具有廣泛的應(yīng)用場景,例如:

(1)GFS選主服務(wù)器;

(2)BigTable中的表鎖;


2.背景

Chubby本質(zhì)上是一個分布式文件系統(tǒng),存儲大量小文件。每個文件就代表一個鎖,并且可以保存一些應(yīng)用層面的小規(guī)模數(shù)據(jù)。用戶通過打開、關(guān)閉、讀取文件來獲取共享鎖或者獨占鎖;并通過反向通知機制,向用戶發(fā)送更新信息。


3.系統(tǒng)設(shè)計

3.1設(shè)計目標

Chubby系統(tǒng)設(shè)計的目標基于以下幾點:

(1)粗粒度的鎖服務(wù);

(2)高可用、高可靠;

(3)可直接存儲服務(wù)信息,而無需另建服務(wù);

(4)高擴展性;


在實現(xiàn)時,使用了以下特性:

(1)緩存機制:客戶端緩存,避免頻繁訪問master;

(2)通知機制:服務(wù)器會及時通知客戶端服務(wù)變化;


3.2整體架構(gòu)
figure 1:system structure

Chubby架構(gòu)并不復(fù)雜,如上圖分為兩個重要組件:

(1)Chubby庫:客戶端通過調(diào)用Chubby庫,申請鎖服務(wù),并獲取相關(guān)信息,同時通過租約保持與服務(wù)器的連接;

(2)Chubby服務(wù)器組:一個服務(wù)器組一般由五臺服務(wù)器組成(至少3臺),其中一臺master,服務(wù)維護與客戶端的所有通信;其他服務(wù)器不斷和主服務(wù)器通信,獲取用戶操作。


4.系統(tǒng)實現(xiàn)

4.1文件系統(tǒng)

Chubby文件系統(tǒng)類似于簡單的unix文件系統(tǒng),但它不支持文件移動操作與硬連接。文件系統(tǒng)由許多Node組成,每個Node代表一個文件,或者一個目錄。文件系統(tǒng)使用Berkeley DB來保存每個Node的數(shù)據(jù)。文件系統(tǒng)提供的API很少:創(chuàng)建文件系統(tǒng)、文件操作、目錄操作等簡易操作。


4.2基于ICE的Chubby通信機制

一種基于ICE的RPC異步機制,核心就是異步,部分組件負責(zé)發(fā)送,部分組件負責(zé)接收。


4.3客戶端與master的通信

(1)長連接保持連接,連接有效期內(nèi),客戶端句柄、鎖服務(wù)、緩存數(shù)據(jù)均一直有效;

(2)定時雙向keep alive;

(3)出錯回調(diào)是客戶端與服務(wù)器通信的重點。


下面將說明正常、客戶端租約過期、主服務(wù)器租約過期、主服務(wù)器出錯等情況。

(1)正常情況

keep alive是周期性發(fā)送的一種消息,它有兩方面功能:延長租約有效期,攜帶事件信息告訴客戶端更新。正常情況下,租約會由keep alive一直不斷延長。

潛在回調(diào)事件包括:文件內(nèi)容修改、子節(jié)點增刪改、master出錯等。


(2)客戶端租約過期

客戶端沒有收到master的keep alive,租約隨之過期,將會進入一個“危險狀態(tài)”。由于此時不能確定master是否已經(jīng)終止,客戶端必須主動讓cache失效,同時,進入一個尋找新的master的階段。


這個階段中,客戶端會輪詢Chubby Cell中非master的其他服務(wù)器節(jié)點,當(dāng)客戶端收到一個肯定的答復(fù)時,他會向新的master發(fā)送keep alive信息,告之自己處于“危險狀態(tài)”,并和新的master建立session,然后把cache中的handler發(fā)送給master刷新。

一段時間后,例如45s,新的session仍然不能建立,客戶端立馬認為session失效,將其終止。當(dāng)然這段時間內(nèi),不能更改cache信息,以求保證數(shù)據(jù)的一致性。

(3)master租約過期

master一段時間沒有收到客戶端的keep alive,則其進入一段等待期,此期間內(nèi)仍沒有響應(yīng),則master認為客戶端失效。失效后,master會把客戶端獲得的鎖,機器打開的臨時文件清理掉,并通知各副本,以保持一致性。


(4)主服務(wù)器出錯

master出錯,需要內(nèi)部進行重新選舉,各副本只響應(yīng)客戶端的讀取命令,而忽略其他命令。新上任的master會進行以下幾步操作:

a,選擇新的編號,不再接受舊master的消息;

b,只處理master位置相關(guān)消息,不處理session相關(guān)消息;

c,等待處理“危險狀態(tài)”的客戶端keep alive;

d,響應(yīng)客戶端的keep alive,建立新的session,同時拒絕其他session相關(guān)操作;同事向客戶端返回keep alive,警告客戶端master fail-over,客戶端必須更新handle和lock;

e,等待客戶端的session確認keep alive,或者讓session過期;

f,再次響應(yīng)客戶端所有操作;

g,一段時間后,檢查是否有臨時文件,以及是否存在一些lock沒有handle;如果臨時文件或者lock沒有對應(yīng)的handle,則清除臨時文件,釋放lock,當(dāng)然這些操作都需要保持數(shù)據(jù)的一致性。


4.4服務(wù)器間的一致性操作

這塊考慮的問題是:當(dāng)master收到客戶端請求時(主要是寫),如何將操作同步,以保證數(shù)據(jù)的一致性。

(1)節(jié)點數(shù)目

一般來說,服務(wù)器節(jié)點數(shù)為5,如果臨時有節(jié)點被拿走,可預(yù)期不久的將來就會加進來。


(2)關(guān)于復(fù)制

服務(wù)器接受客戶端請求時,master會將請求復(fù)制到所有成員,并在消息中添加最新被提交的請求序號。member收到這個請求后,獲取master處被提交的請求序號,然后執(zhí)行這個序列之前的所有請求,并把其記錄到內(nèi)存的日志里。如果請求沒有被master接受,就不能執(zhí)行。


各member會向master發(fā)送消息,master收到>=3個以上的消息,才能夠進行確認,發(fā)送commit給各member,執(zhí)行請求,并返回客戶端。

如果某個member出現(xiàn)暫時的故障,沒有收到部分消息也無礙,在收到來自master的新請求后,主動從master處獲得已執(zhí)行的,自己卻還沒有完成的日志,并進行執(zhí)行。

最終,所有成員都會獲得一致性的數(shù)據(jù),并且,在系統(tǒng)正常工作狀態(tài)中,至少有3個服務(wù)器保持一致并且是最新的數(shù)據(jù)狀態(tài)。

4.5Chubby系統(tǒng)鎖機制

客戶端和服務(wù)器除了要保存lease對象外,服務(wù)器和客戶端還需要保存另一張表,用于描述已經(jīng)加鎖的文件及相關(guān)信息。由于Chubby系統(tǒng)所使用鎖是建議性而非強制性的,這代表著如果有多個鎖請求,后達的請求會進入鎖等待隊列,直到鎖被釋放。


5.Chubby使用例子(重點)

5.1選master

(1)每個server都試圖創(chuàng)建/打開同一個文件,并在該文件中記錄自己的服務(wù)信息,任何時刻都只有一個服務(wù)器能夠獲得該文件的控制權(quán);

(2)首先創(chuàng)建該文件的server成為主,并寫入自己的信息;

(3)后續(xù)打開該文件的server成為從,并讀取主的信息;


5.2進程監(jiān)控

(1)各個進程都把自己的狀態(tài)寫入指定目錄下的臨時文件里;

(2)監(jiān)控進程通過閱讀該目錄下的文件信息來獲得進程狀態(tài);

(3)各個進程隨時有可能死亡,因此指定目錄的數(shù)據(jù)狀態(tài)會發(fā)生變化;

(4)通過事件機制通知監(jiān)控進程,讀取相關(guān)內(nèi)容,獲取最新狀態(tài),達到監(jiān)控目的;


6.總結(jié)

Google Chubby提供粗粒度鎖服務(wù),它的本質(zhì)是一個松耦合分布式文件系統(tǒng);開發(fā)者不需要關(guān)注復(fù)雜的同步協(xié)議,直接調(diào)用庫來取得鎖服務(wù),并保證了數(shù)據(jù)的一致性。


最后要說明的是,最終Chubby系統(tǒng)代碼共13700多行,其中ice自動生成6400行,手動編寫約8000行,這就是Google牛逼的地方:強大的工程能力,快速穩(wěn)定的實現(xiàn),然后用來解決各種業(yè)務(wù)問題。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號