溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

基于Raft協(xié)議的分布式數(shù)據(jù)庫系統(tǒng)應(yīng)用是怎樣的

發(fā)布時(shí)間:2021-12-02 14:38:44 來源:億速云 閱讀:149 作者:柒染 欄目:大數(shù)據(jù)

基于Raft協(xié)議的分布式數(shù)據(jù)庫系統(tǒng)應(yīng)用是怎樣的,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

下面介紹Raft協(xié)議的原理、以及存儲(chǔ)節(jié)點(diǎn)(Pinetree)如何應(yīng)用 Raft實(shí)現(xiàn)復(fù)制的一些工程實(shí)踐經(jīng)驗(yàn)。

1、引言

在華為分布式數(shù)據(jù)庫的工程實(shí)踐過程中,我們實(shí)現(xiàn)了一個(gè)計(jì)算存儲(chǔ)分離、 底層存儲(chǔ)基于Raft協(xié)議進(jìn)行復(fù)制的分布式數(shù)據(jù)庫系統(tǒng)原型。下面是它的架構(gòu)圖。

?基于Raft協(xié)議的分布式數(shù)據(jù)庫系統(tǒng)應(yīng)用是怎樣的

計(jì)算節(jié)點(diǎn)生成日志經(jīng)過封裝后通過網(wǎng)絡(luò)下發(fā)到存儲(chǔ)節(jié)點(diǎn),在Raft層達(dá)成一致后日志被應(yīng)用到狀態(tài)機(jī)wal Engine,完成日志的回放和數(shù)據(jù)的存儲(chǔ)管理。

?下面簡(jiǎn)單介紹一下Raft的原理、以及存儲(chǔ)節(jié)點(diǎn)(Pinetree)如何應(yīng)用 Raft實(shí)現(xiàn)復(fù)制的一些工程實(shí)踐經(jīng)驗(yàn)。

2、Raft的原理

2.1 Raft的基本原理

Raft 算法一切以領(lǐng)導(dǎo)者為準(zhǔn),實(shí)現(xiàn)一系列值的共識(shí)和各節(jié)點(diǎn)日志的一致。下面重點(diǎn)介紹一下Raft協(xié)議的Leader選舉、log復(fù)制 和 成員變更。

Raft的選舉機(jī)制:

協(xié)議為每個(gè)節(jié)點(diǎn)定義了三個(gè)狀態(tài):Leader、Candidate、Follower,將時(shí)間定義為Term,每個(gè)Term有一個(gè)ID。Term類似邏輯時(shí)鐘,在每個(gè)Term都會(huì)有Leader被選舉出來。

Leader負(fù)責(zé)處理所有的寫請(qǐng)求、發(fā)起日志復(fù)制、定時(shí)心跳,每個(gè)Term期間最多只能有一個(gè)Leader,可能會(huì)存在選舉失敗的場(chǎng)景,那么這個(gè)Term內(nèi)是沒有Leader。

Follower 處于被動(dòng)狀態(tài),負(fù)責(zé)處理Leader發(fā)過來的RPC請(qǐng)求,并且做出回應(yīng)。

Candidate 是用來選舉一個(gè)新的Leader,當(dāng)Follower超時(shí),就會(huì)進(jìn)入Candidate狀態(tài)。

初始狀態(tài),所有的節(jié)點(diǎn)都處于Follower狀態(tài),節(jié)點(diǎn)超時(shí)后,遞增current Term進(jìn)入Candidate,該節(jié)點(diǎn)發(fā)送廣播消息RequestVote RPC給其他Follower請(qǐng)求投票。當(dāng)收到多數(shù)節(jié)點(diǎn)的投票后,該節(jié)點(diǎn)從Candidate進(jìn)入Leader。Follower在收到投票請(qǐng)求后,會(huì)首先比較Term,然后再比較日志index,如果都滿足則更新本地Current Term然后回應(yīng)RequestVote RPC為其投票。每個(gè)Term期間,follower只能投一次票。

基于Raft協(xié)議的分布式數(shù)據(jù)庫系統(tǒng)應(yīng)用是怎樣的

Raft的日志同步機(jī)制:

當(dāng)Leader被選舉出來后,就可以接受寫請(qǐng)求。每個(gè)寫請(qǐng)求即代表了用戶需要復(fù)制的指令或Command。Raft協(xié)議會(huì)給寫請(qǐng)求包裝上Term和Index,由此組成了Raft的Log entry. Leader把Log entry append到日志中,然后給其它的節(jié)點(diǎn)發(fā)AppendEntries RPC請(qǐng)求。當(dāng)Leader確定一個(gè)Log entry被大多數(shù)節(jié)點(diǎn)已經(jīng)寫入日志當(dāng)中,就apply這條Log entry到狀態(tài)機(jī)中然后返回結(jié)果給客戶端。

基于Raft協(xié)議的分布式數(shù)據(jù)庫系統(tǒng)應(yīng)用是怎樣的

Raft成員變更機(jī)制:

成員變更就意味著集群節(jié)點(diǎn)數(shù)的增加或減少以及替換。Raft協(xié)議定義時(shí)考慮了成員變更的場(chǎng)景,從而避免由于集群變化引起的系統(tǒng)不可用。Raft是利用上面的Log Entry和一致性協(xié)議來實(shí)現(xiàn)該功能。成員的變更也是由Leader發(fā)起的,Leader會(huì)在本地生成一個(gè)新的Log entry,同時(shí)將Log entry推送到其他的Follower節(jié)點(diǎn)。

Follower節(jié)點(diǎn)收到Log entry后更新本地日志,并且應(yīng)用該log中的配置關(guān)系。多數(shù)節(jié)點(diǎn)應(yīng)用后,Leader就會(huì)提交這條變更log entry。還要考慮新就配置的更替所帶來的問題。更詳細(xì)的不再贅述。

2.2 Raft的開源實(shí)現(xiàn)

Raft的實(shí)現(xiàn)有coreos的etcd/raft、kudu、consul、logcabin、cockroach等。

Etcd 、LogCabin 、Consul 實(shí)現(xiàn)的是單個(gè)Raft環(huán),無法做到彈性伸縮。而kudu和cockroach實(shí)現(xiàn)了多個(gè)raft環(huán)。kudu的consensus 模塊實(shí)現(xiàn)了副本的數(shù)據(jù)復(fù)制一致性,kudu將數(shù)據(jù)分片稱之為Tablet, 是kudu table的水平分表,TabletPeer就是在Raft環(huán)里面的一個(gè)節(jié)點(diǎn). 一個(gè)Tablet相當(dāng)于一個(gè)Raft環(huán),一個(gè)Tablet對(duì)應(yīng)一個(gè)Raft Consensus,這些對(duì)應(yīng)Raft里面的一個(gè)環(huán),Consensus Round相當(dāng)于同步的消息,一個(gè)環(huán)之間會(huì)有多個(gè)Consensus Round做同步。而cockroach則是基于etcd/raft實(shí)現(xiàn)的多Raft環(huán),它維護(hù)了多個(gè)Raft實(shí)例,被稱之為multiraft。

因?yàn)镋tcd的Raft是目前功能較全的Raft實(shí)現(xiàn)之一,最早應(yīng)用于生產(chǎn)環(huán)境,并且做到了很好的模塊化。其中Raft內(nèi)核部分實(shí)現(xiàn)了Raft大部分協(xié)議,而對(duì)外則提供了storage和transport所用的interface,對(duì)于使用者可以單獨(dú)實(shí)現(xiàn)靈活性較高,用戶還可以自主實(shí)現(xiàn) snapshot、wal ,Raft非常便于移植和應(yīng)用,因此存儲(chǔ)節(jié)點(diǎn)Pinetree采用了開源的Etcd中的Raft實(shí)現(xiàn)來構(gòu)建我們的原型系統(tǒng),也便于后期向Multiraft演進(jìn)。。

3、工程實(shí)踐

3.1 實(shí)現(xiàn)Raft的存儲(chǔ)接口和網(wǎng)絡(luò)傳輸

Raft存儲(chǔ)部分指的是raft- log的存儲(chǔ),是對(duì)日志條目進(jìn)行持久化的存儲(chǔ),通過benchmark測(cè)試發(fā)現(xiàn),raft-log引擎性能是影響整體ops的主要瓶頸,為了更靈活的支持底層存儲(chǔ)引擎的快速替換,增加可插拔的存儲(chǔ)引擎框架,我們對(duì)底層存儲(chǔ)引擎進(jìn)行解耦。Pinetree封裝了第三方獨(dú)立存儲(chǔ)接口來適配etcd raft的log存儲(chǔ)接口;

通訊部分即Raft Transport、snapShot傳輸?shù)?,采用GRPC+Protobuf來實(shí)現(xiàn),心跳、日志傳輸AppendEntries RPC、選舉RequestVote RPC等應(yīng)用場(chǎng)景將GRPC設(shè)置為簡(jiǎn)單式,snapShot設(shè)置為流式的形式。

3.2 選舉問題

Raft可以實(shí)現(xiàn)自我選舉。但是在實(shí)踐中發(fā)現(xiàn)缺點(diǎn)也很明顯,Raft自主選主可能存在如下的問題:

1、不可控:可能隨意選擇一個(gè)滿足Raft條件的節(jié)點(diǎn)

2、網(wǎng)絡(luò)閃斷導(dǎo)致Leader變動(dòng)

3、節(jié)點(diǎn)忙導(dǎo)致的Leader變動(dòng)

4、破壞性的節(jié)點(diǎn)

為了防止存儲(chǔ)節(jié)點(diǎn)Leader在不同的AZ或者節(jié)點(diǎn)間進(jìn)行切換,Pinetree采用的方案是由集群管理模塊來指定 Leader。Pinetree中將electionTimeout設(shè)置為無窮大,關(guān)閉Follower可能觸發(fā)的自動(dòng)選舉過程,一切選舉過程由集群管理的建議選主模塊來控制。

3.3 讀一致性模型

在 Raft 集群中,一般會(huì)有 default、consistent、stale 三種一致性模型,如何實(shí)現(xiàn)讀操作關(guān)乎一致性的實(shí)現(xiàn)。一般的做法是將一致性的選擇權(quán)交給用戶,讓用戶根據(jù)實(shí)際業(yè)務(wù)特點(diǎn),按需選擇,靈活使用。

Consistent具有最高的讀一致性,但是實(shí)現(xiàn)上要求所有的讀請(qǐng)求都要走一遍Raft 內(nèi)核并且將會(huì)與寫操作串行,會(huì)給集群造成一定的壓力。stale具有很好的性能優(yōu)勢(shì),但是讀操作可能會(huì)落到數(shù)據(jù)有延遲的節(jié)點(diǎn)上。在Pinetree的設(shè)計(jì)中,集群管理負(fù)責(zé)維護(hù)存儲(chǔ)節(jié)點(diǎn)的信息,管理所有節(jié)點(diǎn)的Raft主副本的狀態(tài),一方面可以對(duì)讀請(qǐng)求進(jìn)行負(fù)載均衡,另一方面可以根據(jù)AZ親和性、副本上的數(shù)據(jù)是否有最新的log 來路由讀請(qǐng)求。這樣在性能和一致性之間進(jìn)行了最大的tradeoff。

3.4 日志問題

Raft以Leader為中心進(jìn)行復(fù)制需要考慮幾個(gè)問題:

1、性能問題,如果leader為慢節(jié)點(diǎn)會(huì)導(dǎo)致長尾

2、日志的同步必須是有序提交

3、切換leader時(shí)有一段時(shí)間的不可用

問題3我們通過集群管理來最大程度的防止Leader的切換。

對(duì)于問題2,因?yàn)镻inetree的日志類似innodb的redo log ,采用LSN來編號(hào)的,所以應(yīng)用到Pinetree存儲(chǔ)層的的日志必須要保序,不能出現(xiàn)跳過日志段或日志空洞的情況。這就要求發(fā)給Raft的日志要做保序處理。計(jì)算層產(chǎn)生的wal log都對(duì)應(yīng)一個(gè)LSN,LSN代表的是日志在文件中的偏移量,具有單調(diào)遞增且不連續(xù)的特點(diǎn)。因此要求Wal log產(chǎn)生的順序和apply到pinetree storage的順序要保證一致。為了滿足這一需求,我們?cè)谟?jì)算層和Raft層中間增加一個(gè)適配層,維護(hù)一個(gè)隊(duì)列負(fù)責(zé)進(jìn)行排序,同時(shí)為了應(yīng)對(duì)計(jì)算層主備的切換,對(duì)消息增加Term以保證日志不會(huì)亂序。Raft指令還可能會(huì)被重復(fù)提交和執(zhí)行,所以存儲(chǔ)層要考慮冪等性的問題。因?yàn)镻inetree storage的日志用LSN進(jìn)行編號(hào),所以可以進(jìn)行重復(fù)apply。

3.5 如何解決假主問題?

計(jì)算節(jié)點(diǎn)需要獲取某些元數(shù)據(jù)信息,每次都必須從Leader中讀取數(shù)據(jù)防止出現(xiàn)備機(jī)延遲。在網(wǎng)絡(luò)隔離的情況下,老的leader不會(huì)主動(dòng)退出,會(huì)出現(xiàn)雙主的情況,這個(gè)假主可能永遠(yuǎn)不知道自己其實(shí)已經(jīng)不是真正的Raft主節(jié)點(diǎn),導(dǎo)致真Leader和假Leader同時(shí)存在并提供讀服務(wù),這在無延遲系統(tǒng)是不允許的。

如果每次讀請(qǐng)求都走一遍Raft協(xié)議可以識(shí)別出假主,但是將會(huì)嚴(yán)重的影響系統(tǒng)的性能。

Pinetree是通過租約(lease)的方式,讓一個(gè)Pinetree主節(jié)點(diǎn)在提供服務(wù)之前,保守地檢查自身在這一時(shí)刻是否擁有l(wèi)ease,再?zèng)Q定自身能不能提供讀服務(wù)。因此,就算訪問了一個(gè)Pinetree假主,假主也因?yàn)闆]有l(wèi)ease而不能提供服務(wù)。

3.6 性能問題

涉及到性能Pinetree考慮和優(yōu)化的地方:

1 如果使用 Raft 算法 保證強(qiáng)一致性,那么讀寫操作都應(yīng)該在領(lǐng)導(dǎo)者節(jié)點(diǎn)上進(jìn)行。這樣的話,讀的性能相當(dāng)于單機(jī),不是很理想, 優(yōu)化實(shí)現(xiàn)了基于leader+lease的方式來提供讀服務(wù)即能保證一致性又不影響性能。

2 優(yōu)化raft參數(shù) :in-flight的數(shù)目;transport queue的數(shù)量

3 最大限度的異步化,例如:指令在raft達(dá)成一致完成持久化后傳遞給狀態(tài)機(jī)存入消息隊(duì)列立即返回,后續(xù)對(duì)消息進(jìn)行異步并行解析。

4 最大限度的進(jìn)行Batch和Cache。例如:把一個(gè)事務(wù)內(nèi)的寫操作緩存到客戶端,在事務(wù)提交時(shí),再把所有的寫打包成一個(gè)batch與事務(wù)commit請(qǐng)求一起發(fā)送給服務(wù)端。

看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI