Raft演算法系列教程3:日誌複製

楚楚99發表於2020-12-27

1、日誌複製的過程

Leader選出後,就開始接收客戶端的請求。Leader把請求作為日誌條目(Log entries)加入到它的日誌中,然後並行的向其他伺服器發起 AppendEntries RPC 複製日誌條目。當這條日誌被複制到大多數伺服器上,Leader將這條日誌應用到它的狀態機並向客戶端返回執行結果。

客戶端的每一個請求都包含被複制狀態機執行的指令。Leader把這個指令作為一條新的日誌條目新增到日誌中,然後並行發起 RPC 給其他的伺服器,讓它們複製這條資訊。假如這條日誌被安全的複製,Leader就應用這條日誌到自己的狀態機中,並返回給客戶端。如果Follower當機或者執行緩慢或者丟包,Leader會不斷的重試,直到所有的Follower最終都複製了所有的日誌條目。

2、日誌的組成

日誌由有序編號(log index)的日誌條目組成。每個日誌條目包含它被建立時的任期號(term)和用於狀態機執行的命令。如果一個日誌條目被複制到大多數伺服器上,就被認為可以提交(commit)了。

上圖顯示,共有 8 條日誌,提交了 7 條。提交的日誌都將通過狀態機持久化到磁碟中,防止當機。

3、日誌複製的詳細介紹

當Leader接收到由客戶端傳送的請求(請求中包含可以被複制狀態機執行的命令)時,Leader將會把該請求作為新的內容新增到日誌中(任期號為當前Leader所處的任期號,索引號為當前Leader本地儲存的日誌集合中的日誌的最高索引號加1)。

備註:Leader在當前任期內最多隻能建立一個給定索引號的日誌(即不可能在一個任期內建立兩個以上的具有相同索引的日誌條目)

然後將該日誌通過AppendEntries RPC訊息傳送到網路中其他的伺服器(以下簡稱Follower),從而複製該日誌。

在網路中Follower接收到該日誌訊息後則會返回複製成功的回覆。

在Leader接收到網路中大部分的Follower的成功複製的回覆之後,Leader便認為該日誌可以被提交。此時Leader將會同時做三件事:

(1)將該日誌應用到Leader本地的複製狀態機
(2)向所有Follower傳送訊息通知所有接收到該日誌的Follower將該日誌進行提交,然後應用到各自本地的複製狀態機
(3)將執行結果通知客戶端

當該日誌訊息成功在網路中大部分Follower本地的複製狀態機執行過後,則可認為該日誌已被提交。在當前日誌被提交的過程中,如果Leader先前的某些日誌還沒有被提交,則將會一同提交。

而網路中有些Follower可能由於網路狀態原因反應緩慢或者崩潰,那麼Leader將會無限次地嘗試重複傳送AppendEntries RPC訊息到該Follower。直到成功為止。

4、日誌的一致性檢查

如上所述,Follower在接收到AppendEntries RPC訊息後則會返回複製成功的回覆。實際上在接收到訊息後會首先進行日誌的一致性檢查(正常情況下Leader與Follower的日誌會保持一致,所以一致性檢查不會失敗),一致性檢查內容如下:

在Leader建立AppendEntries RPC訊息時,訊息中將會包含當前日誌之前日誌條目的任期號與索引號。
Follower在接受到AppendEntries RPC訊息後,將會檢查之前日誌的任期號與索引號是否匹配到。如果匹配到則說明和Leader之前的日誌是保持一致的,否則,如果沒有匹配則會拒絕AppendEntries RPC訊息。

一致性檢查是一個歸納的過程。正常情況下,網路中第一條日誌一定滿足日誌的一致性檢查,然後第二條日誌中包含第一條日誌的任期號與索引號,所以只要Leader與Follower的第一條日誌保持一致,那麼第二條日誌也會滿足一致性檢查,從而之後的每一條日誌都會滿足一致性檢查。

從而得出了日誌匹配屬性:

(1)如果兩個不同的日誌實體具有相同的索引和任期號,那麼它們儲存有相同的命令。
(2)如果兩個不同的日誌實體具有相同的索引和任期號,則所有先前條目中的日誌都相同。(由一致性檢查結果得出)

相關文章