溫馨提示×

溫馨提示×

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

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

Raft算法在分布式存儲系統(tǒng)Curve中的方法教程

發(fā)布時間:2021-10-23 10:21:00 來源:億速云 閱讀:272 作者:iii 欄目:編程語言

這篇文章主要講解了“Raft算法在分布式存儲系統(tǒng)Curve中的方法教程”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Raft算法在分布式存儲系統(tǒng)Curve中的方法教程”吧!

Raft一致性算法介紹

Raft算法中,有Leader、Follower、Candidate三種角色,它們之間的轉(zhuǎn)換關(guān)系如下圖:

Raft算法在分布式存儲系統(tǒng)Curve中的方法教程

在同一時刻,只能有一個Leader,當(dāng)選Leader后到發(fā)起下一次選舉稱為一個任期(term),Leader負(fù)責(zé)通過心跳向follower保持統(tǒng)治,并同步數(shù)據(jù)給Follower。Follower發(fā)起選舉的前提是超時未收到Leader的心跳。

Leader競選:RAFT是一種Majority的協(xié)議,即贏得選舉的條件是獲得包括自己以內(nèi)的大多數(shù)節(jié)點的投票。Follower超時未收到Leader的心跳,則會成為Candidate,發(fā)起新一輪的選舉。每個節(jié)點在每個Term內(nèi)只能投一次票,且服從先到先服務(wù)原則。為了避免多個Follower同時超時,raft中的選舉超時時間是一個固定時間加一個隨機時間。

日志復(fù)制:在任期內(nèi),Leader接收來自client的請求,并將其封裝成一個日志條目(Raft Log Entry)把它append到自己的raft log中,然后并行地向其它服務(wù)器發(fā)起AppendEntries RPC,當(dāng)確定該entry被大多數(shù)節(jié)點成功復(fù)制后(這個過程叫commit),就可以執(zhí)行命令(這一步叫apply),并返回給client結(jié)果。log entry由三個部分組成,分別是:1、log index,2、log所屬的term,3、要執(zhí)行的命令。

配置變更:在Raft中,稱復(fù)制組有哪些成員稱為配置,配置并不是固定的,會根據(jù)需求增刪節(jié)點或異常情況下需要替換掉有問題的節(jié)點。從一個配置直接切換到另一個配置是不安全的,因為不同的服務(wù)器會在不同的時間點進行切換。因此Raft配置變更時,會先創(chuàng)建一個特殊的log entry Cold,new,這條entry被commit后,會進入共同一致階段,即新舊配置一起做決定。這時候,再生成一個Cnew的log entry,等這條entry被commit后,就可以由新配置獨立做決定了。

安裝快照:Raft快照指的是某個時刻保存下來的系統(tǒng)狀態(tài)的集合??煺沼袃煞矫娴淖饔茫阂粋€是日志壓縮,打了快照之后,在此時刻之前的log entry就可以刪除了。另一個是啟動加速,系統(tǒng)起來的時候不需要重新回放所有日志。當(dāng)Leader同步日志給Follower的時候,發(fā)現(xiàn)所需的log entry已經(jīng)被快照刪掉了,即可通過發(fā)送InstallSnapshot RPC給Follower進行同步。

Raft算法在Curve中的應(yīng)用

Curve系統(tǒng)是一個分布式存儲系統(tǒng),在Curve系統(tǒng)中,數(shù)據(jù)分片的最小單位稱之為Chunk,默認(rèn)的Chunk大小是16MB。在大規(guī)模的存儲容量下,會產(chǎn)生大量的Chunk,如此眾多的Chunk,會對元數(shù)據(jù)的存儲、管理產(chǎn)生一定壓力。因此引入CopySet的概念。CopySet可以理解為一組ChunkServer的集合,一個Copyset管理多個Chunk,多副本間的同步和管理已Copyset為單位組織。ChunkServer,Copyset和Chunk三者之間的關(guān)系如下圖:

Raft算法在分布式存儲系統(tǒng)Curve中的方法教程

Curve copyset選用了braft作為一致性協(xié)議的組件,使用方式為multi-raft,即同一個機器,可以屬于多個復(fù)制組,反過來說,一個機器上,可以存在多個raft實例?;赽raft,我們實現(xiàn)了副本間數(shù)據(jù)同步,系統(tǒng)調(diào)度,輕量級raft快照等功能,下面一一詳細(xì)介紹。

副本間數(shù)據(jù)同步

CopysetNode在ChunkServer端封裝了braft node,具體關(guān)系如下圖所示:

Raft算法在分布式存儲系統(tǒng)Curve中的方法教程

Curve client發(fā)送一個寫請求時,三副本情況下的具體的步驟如下:

  1. Client發(fā)送寫請求給Leader ChunkServer。

  2. ChunkServer收到請求,將請求封裝成一個log entry,提交給raft。

  3. braft模塊在本地持久化entry的同時發(fā)送entry給其他副本(ChunkServer)。

  4. 本地持久化entry成功,且另一個副本也落盤成功則commit。

  5. commit后執(zhí)行apply,apply即執(zhí)行我們的寫盤操作。

在此過程中,用戶的數(shù)據(jù)和操作,通過braft中的log entry的方式在副本間傳遞,進行數(shù)據(jù)同步。在三副本場景下,向上層返回的時間取決于兩個較快的副本的速度,因此可以減少慢盤的影響。對于較慢的那個副本,leader也會通過無限重試的方式同步數(shù)據(jù),因此在系統(tǒng)正常工作的前提下,最終三個副本的數(shù)據(jù)是一致的。

基于Raft的系統(tǒng)調(diào)度

在Curve中,ChunkServer定期向元數(shù)據(jù)節(jié)點MDS上報心跳,心跳中除了ChunkServer自身的一些統(tǒng)計信息,還包含ChunkServer上面的CopySet的統(tǒng)計信息,包含它的leader,復(fù)制組成員,是否有配置變更執(zhí)行中,配置的epoch等。MDS基于這些統(tǒng)計信息,會生成一系列的Raft配置變更請求并下發(fā)給Copyset的leader所在的ChunkServer。

下發(fā)配置變更

Curve ChunkServer會定期向MDS上報心跳。MDS調(diào)度下發(fā)配置變更是在心跳的response中完成的。上報心跳的過程如下圖:

Raft算法在分布式存儲系統(tǒng)Curve中的方法教程

心跳是定時任務(wù)觸發(fā)的,ChunkServer除了上報一些自己的容量信息等統(tǒng)計信息外,還會上報Copyset的一些信息,比如leader,成員,epoch,是否有進行中的配置變更等。

MDS在心跳response中下發(fā)配置變更的過程如下圖:

Raft算法在分布式存儲系統(tǒng)Curve中的方法教程

ChunkServer收到response后,解析其中的配置變更信息,并下發(fā)給每個Copyset。

Curve epoch

epoch同步配置。MDS生成的調(diào)度信息,是由后臺定時任務(wù)觸發(fā),并在ChunkServer下一次請求到來時在response中下發(fā)的,因此MDS下發(fā)的配置變更有可能是過期的。為了實現(xiàn)MDS和ChunkServer之間的配置同步,Curve引入了epoch機制,初始狀態(tài),epoch初始為0,每進行一次配置變更(包括leader變更),epoch都會加一。當(dāng)MDS中的epoch等于ChunkServer端的epoch時,即將下發(fā)的配置變更才被認(rèn)為是有效的。epoch與term有何區(qū)別?term用于表示Leader的任期,即只跟選舉有關(guān),而epoch是與配置變更相關(guān)的,也包括了Leader選舉這種情況。

epoch的更新。epoch是在ChunkServer端更新的,braft在實現(xiàn)上提供了一個用戶狀態(tài)機,在braft內(nèi)部發(fā)生變化,比如apply,出錯,關(guān)閉,打快照,加載快照,leader變更,配置變更等時會調(diào)用用戶狀態(tài)機中對應(yīng)的函數(shù)。Curve copyset通過繼承的方式實現(xiàn)這個用戶狀態(tài)機來完成與braft的交互,epoch是在on_configuration_committed函數(shù)中加一的。在braft中,當(dāng)Leader變更的時候會把當(dāng)前的配置再提交一遍,因此在on_configuration_committed中增加epoch即可保證在配置發(fā)生變化或者Leader變更時epoch順序遞增。

epoch的持久化。在MDS端,epoch隨著CopySet的其他信息一起持久化在etcd中。ChunkServer也對epoch進行了持久化,但是ChunkServer中持久化epoch并不是每次epoch發(fā)生變化都需要持久化的。這是利用了raft的日志回放和快照功能??紤]以下兩種情況:

  1. 假設(shè)raft沒有打快照,那么就不需要持久化epoch,因為所有操作日志,包括配置變更的entry都已持久化,當(dāng)服務(wù)重啟的時候,回放這些日志的時候會依次再調(diào)用一遍on_configuration_committed,最后epoch會恢復(fù)到重啟前的值。

  2. 當(dāng)raft有快照時,打快照前的entry都會被刪除,就不能通過上面的方式回放,因此必須要持久化。但我們只需要在打raft快照時持久化epoch的當(dāng)前值即可。這樣當(dāng)系統(tǒng)重啟的時候,會先安裝raft快照,安裝后epoch恢復(fù)到快照時的值,再通過執(zhí)行后面的log entry,最終epoch恢復(fù)到重啟前的值。在打快照時更新epoch是在on_snapshot_save函數(shù)中完成的。

Raft輕量級快照

上面介紹Raft算法的時候介紹過,Raft需要定時打快照,以清理老的log entry,否則Raft日志會無限增長下去。打快照的時候需要保存系統(tǒng)當(dāng)前的狀態(tài),對于Curve塊存儲場景來說,系統(tǒng)狀態(tài)就是Chunk當(dāng)前的數(shù)據(jù)。直觀的方案是將打快照時刻的全部chunk拷貝一遍備份起來。但是這樣有兩個問題:

  1. 空間上要多出一倍,空間浪費非常嚴(yán)重。

  2. Curve默認(rèn)打快照的間隔是30分鐘一次,這種方案下會有頻繁的數(shù)據(jù)拷貝,對磁盤造成很大的壓力,影響正常的IO。

因此,Curve中使用的Raft快照是輕量級的,即打快照的時候只保存當(dāng)前的Chunk文件的列表,不對Chunk本身做備份。具體流程如下:

Raft算法在分布式存儲系統(tǒng)Curve中的方法教程Raft算法在分布式存儲系統(tǒng)Curve中的方法教程

這樣操作,F(xiàn)ollower下載到的chunk文件不是打快照時的狀態(tài),而是最新的狀態(tài),在回放日志的時候,會把這些新數(shù)據(jù)再寫一遍。但這對于我們的場景是可以接受的,因為底層都是覆蓋寫是冪等的,即寫一次和寫多次結(jié)果是一致的。

感謝各位的閱讀,以上就是“Raft算法在分布式存儲系統(tǒng)Curve中的方法教程”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Raft算法在分布式存儲系統(tǒng)Curve中的方法教程這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

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

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

AI