您好,登錄后才能下訂單哦!
這篇文章主要講解了“Raft算法在分布式存儲系統Curve中的方法教程”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Raft算法在分布式存儲系統Curve中的方法教程”吧!
Raft算法中,有Leader、Follower、Candidate三種角色,它們之間的轉換關系如下圖:
在同一時刻,只能有一個Leader,當選Leader后到發起下一次選舉稱為一個任期(term),Leader負責通過心跳向follower保持統治,并同步數據給Follower。Follower發起選舉的前提是超時未收到Leader的心跳。
Leader競選:RAFT是一種Majority的協議,即贏得選舉的條件是獲得包括自己以內的大多數節點的投票。Follower超時未收到Leader的心跳,則會成為Candidate,發起新一輪的選舉。每個節點在每個Term內只能投一次票,且服從先到先服務原則。為了避免多個Follower同時超時,raft中的選舉超時時間是一個固定時間加一個隨機時間。
日志復制:在任期內,Leader接收來自client的請求,并將其封裝成一個日志條目(Raft Log Entry)把它append到自己的raft log中,然后并行地向其它服務器發起AppendEntries RPC,當確定該entry被大多數節點成功復制后(這個過程叫commit),就可以執行命令(這一步叫apply),并返回給client結果。log entry由三個部分組成,分別是:1、log index,2、log所屬的term,3、要執行的命令。
配置變更:在Raft中,稱復制組有哪些成員稱為配置,配置并不是固定的,會根據需求增刪節點或異常情況下需要替換掉有問題的節點。從一個配置直接切換到另一個配置是不安全的,因為不同的服務器會在不同的時間點進行切換。因此Raft配置變更時,會先創建一個特殊的log entry Cold,new,這條entry被commit后,會進入共同一致階段,即新舊配置一起做決定。這時候,再生成一個Cnew的log entry,等這條entry被commit后,就可以由新配置獨立做決定了。
安裝快照:Raft快照指的是某個時刻保存下來的系統狀態的集合。快照有兩方面的作用:一個是日志壓縮,打了快照之后,在此時刻之前的log entry就可以刪除了。另一個是啟動加速,系統起來的時候不需要重新回放所有日志。當Leader同步日志給Follower的時候,發現所需的log entry已經被快照刪掉了,即可通過發送InstallSnapshot RPC給Follower進行同步。
Curve系統是一個分布式存儲系統,在Curve系統中,數據分片的最小單位稱之為Chunk,默認的Chunk大小是16MB。在大規模的存儲容量下,會產生大量的Chunk,如此眾多的Chunk,會對元數據的存儲、管理產生一定壓力。因此引入CopySet的概念。CopySet可以理解為一組ChunkServer的集合,一個Copyset管理多個Chunk,多副本間的同步和管理已Copyset為單位組織。ChunkServer,Copyset和Chunk三者之間的關系如下圖:
Curve copyset選用了braft作為一致性協議的組件,使用方式為multi-raft,即同一個機器,可以屬于多個復制組,反過來說,一個機器上,可以存在多個raft實例。基于braft,我們實現了副本間數據同步,系統調度,輕量級raft快照等功能,下面一一詳細介紹。
CopysetNode在ChunkServer端封裝了braft node,具體關系如下圖所示:
Curve client發送一個寫請求時,三副本情況下的具體的步驟如下:
Client發送寫請求給Leader ChunkServer。
ChunkServer收到請求,將請求封裝成一個log entry,提交給raft。
braft模塊在本地持久化entry的同時發送entry給其他副本(ChunkServer)。
本地持久化entry成功,且另一個副本也落盤成功則commit。
commit后執行apply,apply即執行我們的寫盤操作。
在此過程中,用戶的數據和操作,通過braft中的log entry的方式在副本間傳遞,進行數據同步。在三副本場景下,向上層返回的時間取決于兩個較快的副本的速度,因此可以減少慢盤的影響。對于較慢的那個副本,leader也會通過無限重試的方式同步數據,因此在系統正常工作的前提下,最終三個副本的數據是一致的。
在Curve中,ChunkServer定期向元數據節點MDS上報心跳,心跳中除了ChunkServer自身的一些統計信息,還包含ChunkServer上面的CopySet的統計信息,包含它的leader,復制組成員,是否有配置變更執行中,配置的epoch等。MDS基于這些統計信息,會生成一系列的Raft配置變更請求并下發給Copyset的leader所在的ChunkServer。
Curve ChunkServer會定期向MDS上報心跳。MDS調度下發配置變更是在心跳的response中完成的。上報心跳的過程如下圖:
心跳是定時任務觸發的,ChunkServer除了上報一些自己的容量信息等統計信息外,還會上報Copyset的一些信息,比如leader,成員,epoch,是否有進行中的配置變更等。
MDS在心跳response中下發配置變更的過程如下圖:
ChunkServer收到response后,解析其中的配置變更信息,并下發給每個Copyset。
epoch同步配置。MDS生成的調度信息,是由后臺定時任務觸發,并在ChunkServer下一次請求到來時在response中下發的,因此MDS下發的配置變更有可能是過期的。為了實現MDS和ChunkServer之間的配置同步,Curve引入了epoch機制,初始狀態,epoch初始為0,每進行一次配置變更(包括leader變更),epoch都會加一。當MDS中的epoch等于ChunkServer端的epoch時,即將下發的配置變更才被認為是有效的。epoch與term有何區別?term用于表示Leader的任期,即只跟選舉有關,而epoch是與配置變更相關的,也包括了Leader選舉這種情況。
epoch的更新。epoch是在ChunkServer端更新的,braft在實現上提供了一個用戶狀態機,在braft內部發生變化,比如apply,出錯,關閉,打快照,加載快照,leader變更,配置變更等時會調用用戶狀態機中對應的函數。Curve copyset通過繼承的方式實現這個用戶狀態機來完成與braft的交互,epoch是在on_configuration_committed函數中加一的。在braft中,當Leader變更的時候會把當前的配置再提交一遍,因此在on_configuration_committed中增加epoch即可保證在配置發生變化或者Leader變更時epoch順序遞增。
epoch的持久化。在MDS端,epoch隨著CopySet的其他信息一起持久化在etcd中。ChunkServer也對epoch進行了持久化,但是ChunkServer中持久化epoch并不是每次epoch發生變化都需要持久化的。這是利用了raft的日志回放和快照功能。考慮以下兩種情況:
假設raft沒有打快照,那么就不需要持久化epoch,因為所有操作日志,包括配置變更的entry都已持久化,當服務重啟的時候,回放這些日志的時候會依次再調用一遍on_configuration_committed,最后epoch會恢復到重啟前的值。
當raft有快照時,打快照前的entry都會被刪除,就不能通過上面的方式回放,因此必須要持久化。但我們只需要在打raft快照時持久化epoch的當前值即可。這樣當系統重啟的時候,會先安裝raft快照,安裝后epoch恢復到快照時的值,再通過執行后面的log entry,最終epoch恢復到重啟前的值。在打快照時更新epoch是在on_snapshot_save函數中完成的。
上面介紹Raft算法的時候介紹過,Raft需要定時打快照,以清理老的log entry,否則Raft日志會無限增長下去。打快照的時候需要保存系統當前的狀態,對于Curve塊存儲場景來說,系統狀態就是Chunk當前的數據。直觀的方案是將打快照時刻的全部chunk拷貝一遍備份起來。但是這樣有兩個問題:
空間上要多出一倍,空間浪費非常嚴重。
Curve默認打快照的間隔是30分鐘一次,這種方案下會有頻繁的數據拷貝,對磁盤造成很大的壓力,影響正常的IO。
因此,Curve中使用的Raft快照是輕量級的,即打快照的時候只保存當前的Chunk文件的列表,不對Chunk本身做備份。具體流程如下:
這樣操作,Follower下載到的chunk文件不是打快照時的狀態,而是最新的狀態,在回放日志的時候,會把這些新數據再寫一遍。但這對于我們的場景是可以接受的,因為底層都是覆蓋寫是冪等的,即寫一次和寫多次結果是一致的。
感謝各位的閱讀,以上就是“Raft算法在分布式存儲系統Curve中的方法教程”的內容了,經過本文的學習后,相信大家對Raft算法在分布式存儲系統Curve中的方法教程這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。