etcd淺析

概述

etcd 誕生於CoreOS公司,當前隸屬於CNCF基金會,供高可用、強一致的小型key value數據存儲服務。算法

架構

etcd淺析

  1. 主要的模塊有:
    • gRPC server:負責對外提供gRPC接口,目前最新穩定版本已經支持http訪問接口。用於處理用戶發送的 API 請求以及其它 etcd 節點的同步與心跳信息請求
    • raft 狀態機:Raft 強一致性算法的具體實現,是 etcd 的核心
    • wal 日誌存儲:Write Ahead Log(預寫式日誌),是 etcd 的數據存儲方式。除了在內存中存有全部數據的狀態以及節點的索引之外,etcd 就經過 WAL 進行持久化存儲。WAL 中,全部的數據提交前都會事先記錄日誌。
    • Snapshot 是爲了防止數據過多而進行的狀態快照;Entry 表示存儲的具體日誌內容。
    • boltdb:kv數據的存儲引擎,v3支持不一樣的後端存儲,當前採用boltdb,經過boltdb支持事務操做。
  2. 主要有四種角色:
    • leader:負責日誌的同步管理,處理來自客戶端的請求,與Follower保持心跳的聯繫
    • follower:剛啓動時全部節點爲follower狀態,響應leader的日誌同步請求,響應candidate的請求,把請求到follower的事務轉發給leader
    • candidate:負責選舉投票,Raft剛啓動時由一個節點從Follower轉爲Candidate發起選舉,選舉出;
      leader後從candidate轉爲leader狀態;當follower收不到leadr的心跳以後,也會變成candidate狀態
    • client:請求發起者

      概念

  3. proxy
    etcd的一種模式,爲 etcd 集羣提供反向代理服務
  4. term
    某個節點成爲leader到下一次競選時間,稱爲一個term
  5. revision
    revision 表明的是全局數據的版本。當數據發生變動,包括建立、修改、刪除,其 revision 對應的都會+1。特別的,在集羣中跨 leader 任期之間,revision 都會保持全局單調遞增。正是 revision 的這一特性,使得集羣中任意一次的修改都對應着一個惟一的 revision,所以咱們能夠經過 revision 來支持數據的MVCC,也能夠支持數據的watch。對於每個 key value 數據節點,etcd 中都記錄了三個版本:
    • 第一個版本叫作 create_revision,是 key value 在建立時對應的 revision;
    • 第二個叫作 mod_revision,是其數據被操做的時候對應的 revision;
    • 第三個 version 就是一個計數器,表明了 key value 被修改了多少次。
  6. watch
    使用watch訂閱數據時,能夠支持從任意歷史時刻(指定 revision)開始建立一個 watcher,在客戶端與 etcd 之間創建一個數據管道,etcd 會推送從指定 revision 開始的全部數據變動。etcd 提供的 watch 機制保證,該 Key 的數據後續的被修改以後,經過這個數據管道即時的推送給客戶端。
  7. lease租約
    lease service提供租約的支持。lease 是一種檢測客戶端存活情況的機制。集羣授予具備生存時間的租約。若是 etcd 集羣在給定的 TTL 時間內未收到keepAlive,則租約到期。
    爲了將租約綁定到鍵值存儲中,每一個 key 最多能夠附加一個租約。當租約到期或被撤銷時,該租約所附的全部 key 都將被刪除。每一個過時的密鑰都會在事件歷史記錄中生成一個刪除事件。

    核心raft協議

    Raft協議採用分治的思想,把分佈式協同的問題分爲3個問題:後端

    • 選舉: 一個新的集羣啓動時,或者老的leader故障時,會選舉出一個新的leader。
    • 日誌同步: leader必須接受客戶端的日誌條目而且將他們同步到集羣的全部機器。
    • 數據安全: 保證任何節點只要在它的狀態機中生效了一條日誌條目,就不會在相同的key上生效另外一條日誌條目。
      leader選舉
    • 初始狀態下,你們都是平等的follower,每一個follower內部都維護了一個隨機的timer。在timer時間到了的時候尚未人主動聯繫它的話,那它就要變成candidate,同時發出投票請求(RequestVote)給其餘人。RequestVote通常包含以下信息:
    • term,自身處於的選舉週期
    • lastLogIndex,log中最新的index值
    • lastLogTerm,log中最近的index是在哪一個term中產生的
    • 對於相同條件的candidate,follower們採起先來先投票的策略。若是超過半數的follower都認爲他是合適作領導的,那麼恭喜,新的leader產生了。若是沒有人願意選這個悲劇的candidate,那它只有老老實實的變回小弟的狀態。而follower投票的時候也會和本身對比下RequestVote相關信息,以確保candidate上存儲的數據是最新的:
    • 若是term < currentTerm,也就是說candidate的版本還沒我新,返回 false
    • 若是已經投票給別的candidate了(votedFor),則返回false
    • log匹配,若是和自身的log匹配上了,則返回true
    • 選舉完成以後,leader會定時發送心跳檢測(heart beat)給follower,follower經過心跳來感知leader的存在的。
    • 若是follower在timer期間內沒有收到leader的心跳,這時極可能leader已經跪了,新的一輪(term)選舉就開始了。
      數據同步

      同步的流程以下:緩存

    • 集羣某個節點收到 client 的 put 請求要求修改數據。節點會生成一個 Type 爲 MsgProp 的 Message,發送給 leader。
    • leader 收到 Message 之後,會處理 Message 中的日誌條目,將其 append 到 raftLog 的 unstable 的日誌中,而且調用 bcastAppend()廣播 append 日誌的消息。
    • leader 中有協程處理 unstable 日誌和剛剛準備發送的消息,newReady 方法會把這些都封裝到 Ready 結構中。
    • leader 的另外一個協程處理這個 Ready,先發送消息,而後調用 WAL 將日誌持久化到本地磁盤。WAL 中保存的持久化的日誌條目會有一個定時任務定時刪除。
    • follower 收到 append 日誌的消息,會調用它本身的 raftLog,將消息中的日誌 append 到本地緩存中。隨後 follower 也像 leader 同樣,有協程將緩存中的日誌條目經過WAL持久化到磁盤中並將當前已經持久化的最新日誌 index 返回給 leader。
    • leader收到follower的回覆以後,若是超過半數的節點都寫日誌成功,那麼leader會把更新數據commit到boltdb存儲,而後給全部follower發起第二次持久化數據到boltdb的廣播,超過半數的follower commit成功則這次寫成功。
數據安全

raft爲了保證數據的強一致性,全部的數據流向都是一個方向,從 leader 流向 follower,也就是全部 follower 的數據必須與 leader 保持一致,若是不一致會被覆蓋。即全部用戶更新數據的請求都最早由 leader 得到,而後存下來通知其餘節點也存下來,等到大多數節點反饋時再把數據提交。一個已提交的數據項纔是 raft 真正穩定存儲下來的數據項,再也不被修改,最後再把提交的數據同步給其餘 follower。由於每一個節點都有 raft 已提交數據準確的備份(最壞的狀況也只是已提交數據還未徹底同步),因此讀的請求任意一個節點均可以處理。安全

應用場景

和zookeeper同樣網絡

優缺點

對比zookeeper的優勢

  • 簡單:易於部署,易使用。基於 HTTP+JSON 的 API 讓你用 curl 就能夠輕鬆使用
  • 安全:可選 SSL 客戶認證機制
  • 快速:每一個實例每秒支持一千次寫操做
  • 可信:使用一致性 Raft 算法充分實現了分佈式

    缺點

  • 在網絡分區時,當 leader 處於小分區時,讀請求會繼續被處理

    總結

    etcd目前背靠CNCF,有k8s背書,做爲新一代的協調服務將來可期,應該會逐步取代zookeeper。架構

相關文章
相關標籤/搜索