Consensus Algorithm

共識演算法

  1. 初步認識Consensus Problem
  2. Raft Algorithm介紹
  3. Etcd粗淺介紹
  4. Etcd超簡約實作

Consensus Problem

希望所有replica servers能夠達成Strong Consistency

Consistency

一致性的定義
每一個節點儲存相同且順序一致的資料,同時保證使用者的每次讀取操作皆返回最新的資訊。
「共識演算法」便是用來達成「一致性」的方法論。
它需要讓分散式集群中的每一個節點滿足以下條件
  1. 儲存相同的數據
  2. 並且對某一個提案(proposal)達成一致認同並保存

Requirements

  1. Termination: 保證所有參與決策且無故障的節點最終會做一個決定,執行的演算法不會無法終止,也稱為Liveness
  2. Agreement: 當演算法完成時,所有節點都會做相同的決定,不會再變動,也稱為Safety
  3. Validity: 最終的決議一定是來自某一個參與的節點。

FLP定理

No completely asynchronous consensus protocol can tolerate even a single unannounced process death. [Impossibility of Distributed Consensus with One Faulty Process, Journal of the Association for Computing Machinery, Vol. 32, No. 2, April 1985]

在Asynchronous網路環境且允許一個節點失效的情況下,任何Consensus protocol無法確保共識在有限時間內完成。
從理論上也許完美的共識演算法並不存在。但是實作上我們仍然能夠實作出一個演算法,並且降低沒有達成共識的機率到合乎使用

Characteristic

  1. Leader:
    • 負責與client互動
    • log replication
    • 任一時刻,集群只會有一個leader
  2. Follower
    • 相較於leader完全被動
    • 不會主動發送任何RPC,只會回應傳入的RPC
  3. Candidate
    • 暫時的角色,可以被選為新leader

Infinite State Machine

Terms (任期)

Term是一個嚴格遞增的數字,也是Raft中各個Servers的時間單位

改變term的方法有2種:

1. 收到其他Servers的Call後更新自己的Term

2. Election Timeout晉身為Candidate後遞增自己的term
不同的Server紀錄的term可能會不同(因為是asynchronous的可能有failure-server)
因此Term也是Raft Servers判斷過期資訊的重要方式

Call Types

  1. RequestVote RPC: 在選出新的leader時使用
  2. AppendEntries RPC: 在normal operation時,leader發送此RPC來replicate log至其他server

Processes

Leader election
Normal operation
(basic log replication)

Leader Election

每一個server初始為 Follower ,相信著這個cluster有一個leader的存在,被動的接受Leader或是Candidate的RPC並回應。
若是Followers超過了election Timeout 仍然沒有收到任何RPC,則
  1. 認定系統目前沒有leader
  2. follower轉成candidate發起選舉

Election Basics Process

  1. 自己紀錄的 term + 1
  2. 轉成 Candidate state
  3. 投給自己
  4. 發送 RequestVote RPCs 給其餘的servers,不斷嘗試直到
    1. 收到過半數的server的選票
      • 變成 Leader
      • 開始發送 AppendEntries heartbeats 給其他servers
    2. 收到合法Leader的RPC
      • 退回 Follower
    3. 這一輪沒有人拿到過半數的票 (election Timeout超時)
      • current_term 再遞增一次
      • 發起下一輪選舉,回到 步驟1

Normal Operation-HeartBeat

Node1成為Leader之後, 會定期被heartbeat timer觸發去對集群中其他節點發送心跳

刷新其他Follower節點的election timer, 避免超時而觸發新一輪的選舉

所以當Follower收到heartbeat後, 會重置election timer, 並且給出heartbeat response. 讓Leader知道Follower也還正常活著.

Normal Operation-ClientRequest

  1. client 發送請求或是指令給 leader
  2. leader 將該指令存到log中
  3. leader 發送 AppendEntries RPCs 給 followers,follower儲存並回復收到。
  4. 當一個 log entry 被 commited :
    1. Leader可以將該command送去state machine執行,並返回結果給client
    2. Leader在下一次的AppendEntries RPCs通知followerd該log entry被commited
    3. followers也可以把該command送去執行。

Log Structure

到這邊為止我們已經對Raft Algo.的運作有一個基本的認識與想像空間了 => 先來看一次動畫
但是為了滿足前面提到的Consensus Algo的Requirements,Raft必須要再定義清楚更細項的規則
​所以我們接下來的矛頭就會指向這些細節的部分!

Election Main Points

1. Safety-Guaranteed:如何選出 leader,並且保證任一時刻只有一個leader

2. Liveness-Guaranteed:當leader失效如何偵測,並且選出新leader
每一個server在同一個term裡只能投一張票 (這個重要資訊必須存在disk,否則投完票,失敗重啟可能會重複投票)
不可能有兩個candidates同時拿到過半數的選票

Election Safety

因此一定有一個candidate有機會比別人先timeout進入下一輪選舉,讓大家投給他

Election Liveness

我們會先預設Election Timeout一個value
設為T
每個Follower節點的election timeout會落在[T, 2*T - 1]這範圍內的millisecond來倒數

Log Consistency

Raft同時也需要確保Servers之間Log的一致性,它所選用的方法是由Leader => Follower的Log Replication(日誌複製)
  1. 每一個 AppendEntries RPCs 除了包含最新的entry外,還包含 前一個entry的(index, term)
  2. Followers 一定要擁有同樣的前一個entry的(index, term) 才會儲存最新的log entry,否則就不接受該RPC
  3. Leader保存每一個follower的nextIndex,表示下一個AppendEntries RPCs要送哪一個index的entry給該follower,如果發現AppendEntries失敗則遞減nextIndex
  4. 若Followers收到AppendEntries RPC時發現nextIndex指向的位置已經有entry了,會認定該entry不重要並以從leader收到的RPC內容進行覆寫

Commitment Safety

回到Raft最初的目的,我們希望的是集群中的每一個機器皆執行一樣且順序一致的指令。
當一個log entry被state machine執行時,其他的state machine執行同一個log entry時,一定也是執行同一個指令,這樣所有機器的狀態跟結果才會一樣。
如果一個log entry被目前的leader決定committed(過半數都保存該log entry),則
=> 該commited的log entry一定會存在未來的leader中
針對Commitment Safety,我們會需要修正兩個部分
Leader Election
防止選到擁有過期資訊的Leader
Commitment Rules
保持Commitent的嚴謹性

Revised Leader Election

  1. Candidate的 RequestVote RPCs 須包含自己 最後一個log entry的 (index,term)
  2. 收到 server U RequestVote RPCs的 server V,檢查自己最後一個log entry的term與index是否比接收到的RPC還要新,是的話則拒絕投給該Candidates,因為自己的log更多更完整。
  3. 上述保證leader一定擁有最完整的log entries 

Commitment Rules

Leader要確保Append給Followers的Log entry收到過半數來自Followers的回應才可以執行commit並將commit的status append給Followers

Neutralizing Old Leader

假設發生 Network Partition 使得舊的leader聯絡不上followers,導致剩餘的followers發起選舉選出新的leader

此時,舊的leader回復連線,打算commit log entries?
  1. 對於每一個RPC都包含目前發送者的最新Term
  2. 如果接收者發現發送者的Term更舊,就拒絕該RPC請求,回傳最新的Term
  3. 發送者收到回覆退回follower,並更新成新的Term
  4. 如果是接收者的Term更舊,接收者退回follower,並更新成新的Term
這裡再提供另外一個Raft的介紹動畫

http://thesecretlivesofdata.com/raft/

他是以故事的方式去介紹他,我覺得做的蠻不錯的

給推!

ETCD

Etcd是一個開源的分布式鍵值存儲(key-value),它由CoreOS團隊開發,現在由Cloud Native Computing Foundation負責管理
它適用於各種作業系統,包括Linux、BSD和OS X。
相信大家對這個logo並不陌生

Kubernetes底層就是依賴於etcd實現一切與cluster狀態跟配置的相關管理

Advantages

1. 健康檢查:服務節點定期向etcd發送心跳更新自己訊息的TTL
2. 服務主動註冊:同一類型的服務啟動後, 主動註冊到相同服務目錄下
3. 方便透過服務名稱就能查詢到服務提供給外部訪問的IP與Port
4. 服務之間能彼此即時感知, 新增節點、丟棄不可用的服務節點.
其實就是在描述在分散式系統中的重要功能:服務註冊與發現
5. 服務之間共享同一份配置文件, 並且監聽著, 有更新, 服務立刻感知
6. 可靠的分散式KV儲存, 底層用Raft保證一致性
7. etcdV3套件使用gRPC跟etcd服務進行溝通; 相較于v2版本的http+json更加輕巧
8. 能夠容忍單點故障(Fault Tolerance), 能夠應付網路分區

Additional Advantages

分散式鎖

分散任務進度匯報

Distributed Queue

ETCD Data Model

BoltDB

  • BoltDB也是用Go寫的,一個嵌入式ACID key/value pair DB
  • 支援One-Writer / Multi-Readers的MVCC
  • Isolation level為Serializable isolation
  • 內部資料以B+Tree做儲存

 Etcd MVCC implementation

etcd把原始的key當成Btree的索引存放在記憶體中, 資料節點放的是"keyIndex"的資料節點。

所以每次etcd啟動時, 都會去BoltDB把所有的資料撈出來放在記憶體中。

MVCC Process

  1. 先用原始key去找到對應的keyIndex
  2. 再拿這keyIndex取得revision訊息
  3. 再去boldDB去硬碟內找到真正的key以及當時的資料

Data Structures

type keyIndex struct {
	key         []byte // 當前用戶操作的key
	modified    revision // 紀錄最新一次修改對應的revision
	generations []generation //過往修改歷程
}
type generation struct {
	ver     int64 // 從0開始, 0表示第一個版本
	created revision // 表示這generation被建立的時間
	revs    []revision // 表示該世代所有版本
}
type revision struct {
    // 目前的事務操作ID(timestamp), 每次事務操作時, 遞增1
	main int64

    // 子ID, 從0開始; 同一個事務內的操作遞增1
	sub int64
}

Why Generations ?

因為MVCC(多版本控管),不可能讓所有版本都追到同一個revs中

除了不會讓revs長度無限膨脹之外,也因為長度有限便於快速搜尋。

ETCD Demo

ETCD v.3 gRPC services

  1. KV : 負責KV操作, 增刪K-V, 修改Value, 觸發compact
  2. Watch : 負責對指定的Key增加Watch(觀察者模式)
  3. Lease : 負責租約的操作, 新建和回收租約, 續約.
  4. Cluster : 集群節點的管理操作, 增刪集群的節點, 或是查詢節點的狀態
  5. Maintenance : 提供了Alarm功能, 獲取節點的狀態, 進行碎片整理, 取得快照, 轉移Leader
  6. Auth : 負責權限相關的操作, 添加用戶or角色,為用戶分配角色, 啟/停用身份驗證.

Main Focusing

Base CRUD & Revision implement

Fault Tolerance

Thanks for Listening

Made with Slides.com