當etcd收到Client發出的操作請求時, 會呼叫AppendEntries把操作命令當成一個指令的Entry寫在log裡, 並標上Index.
然後再把log當成message傳送給Follower.
Follower收到log後也是會Append entry, 並且返回對應的回應訊息給Leader.
Leader一樣收到半數以上的回應後, 就把Entry給commit成committed, 並返回操作結果給Client, 然後也把commit給包成raftlog給Append Entry.
等到下一次heartbeat發送時, 就把Entries也帶過去通知Follower們執行commit.

這時候集群的狀態就完成一致了, 這個過程就是日誌複製Log Replication
當然以上是Raft的日誌複製.
其實也很像二階段提交(2PC),
第一階段做把日誌對Folloer做日誌複製, 等過半都複製完成時, 做本地commit, 就回應給Client.
第二階段是異步的, Leader就週期性地把提交資訊透過heartbeat提交給Follower, 所以Follower們也會完成commit.
etcd的話, 內部核心稍微複雜點
主要定義了etcd對client的核心接口.
還有跟內部其他模組的設定與溝通.
其中id該節點的IDappliedINdex就是用來紀錄目前這server節點已經Apply的Entry紀錄的最大索引值.committedIndex就是紀錄已經提交成功的Entry紀錄的索引值.inflightSnapshots已經發送出去但還沒收到ack的快照數量.leadElecttedTime紀錄該節點最近一次當上Leader狀態的時間戳記.cluster目前cluster中所有節點的資訊.snapshotter讀寫快照檔案snapCount一個門閥值, 當目前的entry數量距離上一次快照的entry數量, 超過這閥值時, 就會觸發快照.compactor用來控制定期壓縮的頻率
非常多配置QQ
實現了Raft演算法的功能, 就這三篇一直介紹的內容.
主要用來儲存Raft節點臨時的資料與數據, 像是entry, snapshot, 節點狀態...etc, 還沒提交之前暫存用.
也用來存放之前提及的KeyIndex.
就在執行操作命令前先寫入一條日誌(很像MySQL的redo log).
這日誌會以xxxxxxxxx.wal的檔名存在於節點的文件上.
每個WAL檔案大小為64MB, 超過就會生成新的檔案, 該檔案用flock文件鎖做鎖定, 所以同時間也只有一個執行緒能操作.
儲存和讀取快照用.
檔名是xxxx.snap.
如果節點當機了, 要從WAL日誌文件來復原, 很耗時.
從快照來加載, 在從快照之後的相對位置來開始讀取WAL日誌文件, 就快非常多了.
藉由EtcdSever:triggerSnapshot來決定是否觸發快照行為, 裡面會判斷SnapshotCount.
EtcdSErver:snapshot執行完快照後, 會把被載入快照的WAL檔都刪除(Storage:Release).
etcd V3的backend store預設使用的就是BoltDB.
這部份在之前介紹過了.
參考:
In Search of an Understandable Consensus Algorithm這份論文對Raft和日誌複製有詳細的說明.
Raft演算法動畫
接著數篇就介紹些Client API跟做點範例.