分佈式鍵值存儲系統ETCD調研

分佈式鍵值存儲系統ETCD調研 html

簡介

etcd是一個開源的分佈式鍵值存儲工具——爲CoreOS集羣提供配置服務、發現服務和協同調度。Etcd運行在集羣的每一個coreos節點上,能夠保證coreos集羣的穩定,可靠的運行。當集羣網絡出現動盪,或者當前master節點出現異常時,etcd能夠進行master節點的選舉工做,同時恢復集羣中損失的數據。 算法

 

目的: apache

一個高可用的 Key/Value 存儲系統,主要用於分享配置和服務發現 安全

接口: 服務器

REST接口(HTTP+JSON)方便集羣中每個主機訪問 網絡

功能: 多線程

提供了key/value存儲服務,集羣隊列同步服務,觀察一個key的數值變化,以及查詢歷史key值信息等 架構

分佈式協議: app

Raft一致性協議。提供強一致性保證 負載均衡

部署形態: 

採用小集羣(etcd server節點組成一個集羣)+大集羣(其它節點來直接使用服務)的形式,集羣能夠達到上千節點

實現語言: 

go 擁有幾乎不輸於C的效率,特別是go語言自己就是面向多線程,進程通訊的語言。在小規模集羣中性能很是突出

 

摘自:http://www.infoq.com/cn/articles/etcd-interpretation-application-scenario-implement-principle

經典應用場景

要問etcd是什麼?不少人第一反應多是一個鍵值存儲倉庫,卻沒有重視官方定義的後半句,用於配置共享和服務發現。

A highly-available key value store for shared configuration and service discovery.

實際上,etcd做爲一個受到ZooKeeper與doozer啓發而催生的項目,除了擁有與之相似的功能外,更專一於如下四點。

簡單:基於HTTP+JSON的API讓你用curl就能夠輕鬆使用。

安全:可選SSL客戶認證機制。

快速:每一個實例每秒支持一千次寫操做。

可信:使用Raft算法充分實現了分佈式。

隨着雲計算的不斷髮展,分佈式系統中涉及到的問題愈來愈受到人們重視。受阿里中間件團隊對ZooKeeper典型應用場景一覽一文的啓發,筆者根據本身的理解也總結了一些etcd的經典使用場景。讓咱們來看看etcd這個基於Raft強一致性算法的分佈式存儲倉庫能給咱們帶來哪些幫助。

值得注意的是,分佈式系統中的數據分爲控制數據和應用數據。使用etcd的場景默認處理的數據都是控制數據,對於應用數據,只推薦數據量很小,可是更新訪問頻繁的狀況

 

場景一:服務發現(Service Discovery)

服務發現要解決的也是分佈式系統中最多見的問題之一,即在同一個分佈式集羣中的進程或服務,要如何才能找到對方並創建鏈接。

本質上來講,服務發現就是想要了解集羣中是否有進程在監聽udp或tcp端口,而且經過名字就能夠查找和鏈接。

要解決服務發現的問題,須要有下面三大支柱,缺一不可。

  1. 一個強一致性、高可用的服務存儲目錄。基於Raft算法的etcd天生就是這樣一個強一致性高可用的服務存儲目錄。
  2. 一種註冊服務和監控服務健康狀態的機制。用戶能夠在etcd中註冊服務,而且對註冊的服務設置key TTL,定時保持服務的心跳以達到監控健康狀態的效果。
  3. 一種查找和鏈接服務的機制。經過在etcd指定的主題下注冊的服務也能在對應的主題下查找到。爲了確保鏈接,咱們能夠在每一個服務機器上都部署一個Proxy模式的etcd,這樣就能夠確保能訪問etcd集羣的服務都能互相鏈接。

圖1 服務發現示意圖

 

下面咱們來看服務發現對應的具體場景。

微服務協同工做場景

微服務協同工做架構中,服務動態添加。隨着Docker容器的流行,多種微服務共同協做,構成一個相對功能強大的架構的案例愈來愈多。透明化的動態添加這些服務的需求也日益強烈。經過服務發現機制,在etcd中註冊某個服務名字的目錄,在該目錄下存儲可用的服務節點的IP。在使用服務的過程當中,只要從服務目錄下查找可用的服務節點去使用便可。

圖2 微服務協同工做

雲平臺多實例透明化

PaaS平臺中應用多實例與實例故障重啓透明化。PaaS平臺中的應用通常都有多個實例,經過域名,不只能夠透明的對這多個實例進行訪問,並且還能夠作到負載均衡。可是應用的某個實例隨時都有可能故障重啓,這時就須要動態的配置域名解析(路由)中的信息。經過etcd的服務發現功能就能夠輕鬆解決這個動態配置的問題。

圖3 雲平臺多實例透明化

 

場景二:消息發佈與訂閱

在分佈式系統中,最適用的一種組件間通訊方式就是消息發佈與訂閱。即構建一個配置共享中心,數據提供者在這個配置中心發佈消息,而消息使用者則訂閱他們關心的主題,一旦主題有消息發佈,就會實時通知訂閱者。經過這種方式能夠作到分佈式系統配置的集中式管理與動態更新。

應用中用到的一些配置信息放到etcd上進行集中管理。這類場景的使用方式一般是這樣:應用在啓動的時候主動從etcd獲取一次配置信息,同時,在etcd節點上註冊一個Watcher並等待,之後每次配置有更新的時候,etcd都會實時通知訂閱者,以此達到獲取最新配置信息的目的。

  • 分佈式搜索服務中,索引的元信息和服務器集羣機器的節點狀態存放在etcd中,供各個客戶端訂閱使用。使用etcd的key TTL功能能夠確保機器狀態是實時更新的。
  • 分佈式日誌收集系統。這個系統的核心工做是收集分佈在不一樣機器的日誌。收集器一般是按照應用(或主題)來分配收集任務單元,所以能夠在etcd上建立一個以應用(主題)命名的目錄P,並將這個應用(主題相關)的全部機器ip,以子目錄的形式存儲到目錄P上,而後設置一個etcd遞歸的Watcher,遞歸式的監控應用(主題)目錄下全部信息的變更。這樣就實現了機器IP(消息)變更的時候,可以實時通知到收集器調整任務分配。
  • 系統中信息須要動態自動獲取與人工干預修改信息請求內容的狀況。一般是暴露出接口,例如JMX接口,來獲取一些運行時的信息。引入etcd以後,就不用本身實現一套方案了,只要將這些信息存放到指定的etcd目錄中便可,etcd的這些目錄就能夠經過HTTP的接口在外部訪問。

圖4 消息發佈與訂閱

場景三:負載均衡

場景一中也提到了負載均衡,本文所指的負載均衡均爲軟負載均衡。分佈式系統中,爲了保證服務的高可用以及數據的一致性,一般都會把數據和服務部署多份,以此達到對等服務,即便其中的某一個服務失效了,也不影響使用。由此帶來的壞處是數據寫入性能降低,而好處則是數據訪問時的負載均衡。由於每一個對等服務節點上都存有完整的數據,因此用戶的訪問流量就能夠分流到不一樣的機器上。

  • etcd自己分佈式架構存儲的信息訪問支持負載均衡。etcd集羣化之後,每一個etcd的核心節點均可以處理用戶的請求。因此,把數據量小可是訪問頻繁的消息數據直接存儲到etcd中也是個不錯的選擇,如業務系統中經常使用的二級代碼表(在表中存儲代碼,在etcd中存儲代碼所表明的具體含義,業務系統調用查表的過程,就須要查找表中代碼的含義)。
  • 利用etcd維護一個負載均衡節點表。etcd能夠監控一個集羣中多個節點的狀態,當有一個請求發過來後,能夠輪詢式的把請求轉發給存活着的多個狀態。相似KafkaMQ,經過ZooKeeper來維護生產者和消費者的負載均衡。一樣也能夠用etcd來作ZooKeeper的工做。

圖5 負載均衡

場景四:分佈式通知與協調

這裏說到的分佈式通知與協調,與消息發佈和訂閱有些類似。都用到了etcd中的Watcher機制,經過註冊與異步通知機制,實現分佈式環境下不一樣系統之間的通知與協調,從而對數據變動作到實時處理。

實現方式一般是這樣:不一樣系統都在etcd上對同一個目錄進行註冊,同時設置Watcher觀測該目錄的變化(若是對子目錄的變化也有須要,能夠設置遞歸模式),當某個系統更新了etcd的目錄,那麼設置了Watcher的系統就會收到通知,並做出相應處理。

  • 經過etcd進行低耦合的心跳檢測。檢測系統和被檢測系統經過etcd上某個目錄關聯而非直接關聯起來,這樣能夠大大減小系統的耦合性。
  • 經過etcd完成系統調度。某系統有控制檯和推送系統兩部分組成,控制檯的職責是控制推送系統進行相應的推送工做。管理人員在控制檯做的一些操做,其實是修改了etcd上某些目錄節點的狀態,而etcd就把這些變化通知給註冊了Watcher的推送系統客戶端,推送系統再做出相應的推送任務。
  • 經過etcd完成工做彙報。大部分相似的任務分發系統,子任務啓動後,到etcd來註冊一個臨時工做目錄,而且定時將本身的進度進行彙報(將進度寫入到這個臨時目錄),這樣任務管理者就可以實時知道任務進度。

圖6 分佈式協同工做

場景五:分佈式鎖

由於etcd使用Raft算法保持了數據的強一致性,某次操做存儲到集羣中的值必然是全局一致的,因此很容易實現分佈式鎖。鎖服務有兩種使用方式,一是保持獨佔,二是控制時序。

  • 保持獨佔即全部獲取鎖的用戶最終只有一個能夠獲得。etcd爲此提供了一套實現分佈式鎖原子操做CAS(CompareAndSwap)的API。經過設置prevExist值,能夠保證在多個節點同時去建立某個目錄時,只有一個成功。而建立成功的用戶就能夠認爲是得到了鎖。
  • 控制時序,即全部想要得到鎖的用戶都會被安排執行,可是得到鎖的順序也是全局惟一的,同時決定了執行順序。etcd爲此也提供了一套API(自動建立有序鍵),對一個目錄建值時指定爲POST動做,這樣etcd會自動在目錄下生成一個當前最大的值爲鍵,存儲這個新的值(客戶端編號)。同時還可使用API按順序列出全部當前目錄下的鍵值。此時這些鍵的值就是客戶端的時序,而這些鍵中存儲的值能夠是表明客戶端的編號。

圖7 分佈式鎖

場景六:分佈式隊列

分佈式隊列的常規用法與場景五中所描述的分佈式鎖的控制時序用法相似,即建立一個先進先出的隊列,保證順序。

另外一種比較有意思的實現是在保證隊列達到某個條件時再統一按順序執行。這種方法的實現能夠在/queue這個目錄中另外創建一個/queue/condition節點。

  • condition能夠表示隊列大小。好比一個大的任務須要不少小任務就緒的狀況下才能執行,每次有一個小任務就緒,就給這個condition數字加1,直到達到大任務規定的數字,再開始執行隊列裏的一系列小任務,最終執行大任務。
  • condition能夠表示某個任務在不在隊列。這個任務能夠是全部排序任務的首個執行程序,也能夠是拓撲結構中沒有依賴的點。一般,必須執行這些任務後才能執行隊列中的其餘任務。
  • condition還能夠表示其它的一類開始執行任務的通知。能夠由控制程序指定,當condition出現變化時,開始執行隊列任務。

圖8 分佈式隊列

場景七:集羣監控與Leader競選

經過etcd來進行監控實現起來很是簡單而且實時性強。

  1. 前面幾個場景已經提到Watcher機制,當某個節點消失或有變更時,Watcher會第一時間發現並告知用戶。
  2. 節點能夠設置TTL key,好比每隔30s發送一次心跳使表明該機器存活的節點繼續存在,不然節點消失。

    這樣就能夠第一時間檢測到各節點的健康狀態,以完成集羣的監控要求。

    另外,使用分佈式鎖,能夠完成Leader競選。這種場景一般是一些長時間CPU計算或者使用IO操做的機器,只須要競選出的Leader計算或處理一次,就能夠把結果複製給其餘的Follower。從而避免重複勞動,節省計算資源。

    這個的經典場景是搜索系統中創建全量索引。若是每一個機器都進行一遍索引的創建,不但耗時並且創建索引的一致性不能保證。經過在etcd的CAS機制同時建立一個節點,建立成功的機器做爲Leader,進行索引計算,而後把計算結果分發到其它節點。

    圖9 Leader競選

    場景八:爲何用etcd而不用ZooKeeper?

    閱讀了"ZooKeeper典型應用場景一覽"一文的讀者可能會發現,etcd實現的這些功能,ZooKeeper都能實現。那麼爲何要用etcd而非直接使用ZooKeeper呢?

    相較之下,ZooKeeper有以下缺點:

  3. 複雜。ZooKeeper的部署維護複雜,管理員須要掌握一系列的知識和技能;而Paxos強一致性算法也是素來以複雜難懂而聞名於世;另外,ZooKeeper的使用也比較複雜,須要安裝客戶端,官方只提供了Java和C兩種語言的接口。
  4. Java編寫。這裏不是對Java有偏見,而是Java自己就偏向於重型應用,它會引入大量的依賴。而運維人員則廣泛但願保持強一致、高可用的機器集羣儘量簡單,維護起來也不易出錯。
  5. 發展緩慢。Apache基金會項目特有的"Apache Way"在開源界飽受爭議,其中一大緣由就是因爲基金會龐大的結構以及鬆散的管理致使項目發展緩慢。

    而etcd做爲一個後起之秀,其優勢也很明顯。

  6. 簡單。使用Go語言編寫部署簡單;使用HTTP做爲接口使用簡單;使用Raft算法保證強一致性讓用戶易於理解
  7. 數據持久化。etcd默認數據一更新就進行持久化。
  8. 安全。etcd支持SSL客戶端安全認證。

    最後,etcd做爲一個年輕的項目,真正告訴迭代和開發中,這既是一個優勢,也是一個缺點。優勢是它的將來具備無限的可能性,缺點是沒法獲得大項目長時間使用的檢驗。然而,目前CoreOS、Kubernetes和CloudFoundry等知名項目均在生產環境中使用了etcd,因此總的來講,etcd值得你去嘗試。

     

    etcd實現原理解讀

    上一節中,咱們歸納了許多etcd的經典場景,這一節,咱們將從etcd的架構開始,深刻到源碼中解析etcd。

    架構

    圖10 etcd架構圖

    從etcd的架構圖中咱們能夠看到,etcd主要分爲四個部分。

  • HTTP Server: 用於處理用戶發送的API請求以及其它etcd節點的同步與心跳信息請求。
  • Store:用於處理etcd支持的各種功能的事務,包括數據索引、節點狀態變動、監控與反饋、事件處理與執行等等,是etcd對用戶提供的大多數API功能的具體實現。
  • Raft:Raft強一致性算法的具體實現,是etcd的核心。
  • WAL:Write Ahead Log(預寫式日誌),是etcd的數據存儲方式。除了在內存中存有全部數據的狀態以及節點的索引之外,etcd就經過WAL進行持久化存儲。WAL中,全部的數據提交前都會事先記錄日誌。Snapshot是爲了防止數據過多而進行的狀態快照;Entry表示存儲的具體日誌內容。

一般,一個用戶的請求發送過來,會經由HTTP Server轉發給Store進行具體的事務處理,若是涉及到節點的修改,則交給Raft模塊進行狀態的變動、日誌的記錄,而後再同步給別的etcd節點以確認數據提交,最後進行數據的提交,再次同步。

 

新版etcd重要變動列表

  • 得到了IANA認證的端口,2379用於客戶端通訊,2380用於節點通訊,與原先的(4001 peers / 7001 clients)共用。
  • 每一個節點可監聽多個廣播地址。監聽的地址由原來的一個擴展到多個,用戶能夠根據需求實現更加複雜的集羣環境,如一個是公網IP,一個是虛擬機(容器)之類的私有IP。
  • etcd能夠代理訪問leader節點的請求,因此若是你能夠訪問任何一個etcd節點,那麼你就能夠無視網絡的拓撲結構對整個集羣進行讀寫操做。
  • etcd集羣和集羣中的節點都有了本身獨特的ID。這樣就防止出現配置混淆,不是本集羣的其餘etcd節點發來的請求將被屏蔽。
  • etcd集羣啓動時的配置信息目前變爲徹底固定,這樣有助於用戶正確配置和啓動。
  • 運行時節點變化(Runtime Reconfiguration)。用戶不須要重啓 etcd 服務便可實現對 etcd 集羣結構進行變動。啓動後能夠動態變動集羣配置。
  • 從新設計和實現了Raft算法,使得運行速度更快,更容易理解,包含更多測試代碼。
  • Raft日誌如今是嚴格的只能向後追加、預寫式日誌系統,而且在每條記錄中都加入了CRC校驗碼。
  • 啓動時使用的_etcd/* 關鍵字再也不暴露給用戶
  • 廢棄集羣自動調整功能的standby模式,這個功能使得用戶維護集羣更困難。
  • 新增Proxy模式,不加入到etcd一致性集羣中,純粹進行代理轉發。
  • ETCD_NAME(-name)參數目前是可選的,再也不用於惟一標識一個節點。
  • 摒棄經過配置文件配置 etcd 屬性的方式,你能夠用環境變量的方式代替。
  • 經過自發現方式啓動集羣必需要提供集羣大小,這樣有助於用戶肯定集羣實際啓動的節點數量。

 

etcd概念詞彙表

  • Raft:etcd所採用的保證分佈式系統強一致性的算法。
  • Node:一個Raft狀態機實例。
  • Member: 一個etcd實例。它管理着一個Node,而且能夠爲客戶端請求提供服務。
  • Cluster:由多個Member構成能夠協同工做的etcd集羣。
  • Peer:對同一個etcd集羣中另一個Member的稱呼。
  • Client: 向etcd集羣發送HTTP請求的客戶端。
  • WAL:預寫式日誌,etcd用於持久化存儲的日誌格式。
  • snapshot:etcd防止WAL文件過多而設置的快照,存儲etcd數據狀態。
  • Proxy:etcd的一種模式,爲etcd集羣提供反向代理服務。
  • Leader:Raft算法中經過競選而產生的處理全部數據提交的節點。
  • Follower:競選失敗的節點做爲Raft中的從屬節點,爲算法提供強一致性保證。
  • Candidate:當Follower超過必定時間接收不到Leader的心跳時轉變爲Candidate開始競選。
  • Term:某個節點成爲Leader到下一次競選時間,稱爲一個Term。
  • Index:數據項編號。Raft中經過Term和Index來定位數據。

 

 

 集羣啓動

etcd做爲一個高可用鍵值存儲系統,天生就是爲集羣化而設計的。因爲Raft算法在作決策時須要多數節點的投票,因此etcd通常部署集羣推薦奇數個節點,推薦的數量爲三、5或者7個節點構成一個集羣。

etcd有三種集羣化啓動的配置方案,分別爲靜態配置啓動、etcd自身服務發現、經過DNS進行服務發現。

經過配置內容的不一樣,你能夠對不一樣的方式進行選擇。值得一提的是,這也是新版etcd區別於舊版的一大特性,它摒棄了使用配置文件進行參數配置的作法,轉而使用命令行參數或者環境變量的作法來配置參數。

 

靜態配置

這種方式比較適用於離線環境,在啓動整個集羣以前,你就已經預先清楚所要配置的集羣大小,以及集羣上各節點的地址和端口信息。那麼啓動時,你就能夠經過配置initial-cluster參數進行etcd集羣的啓動。

若是你所在的網絡環境配置了多個etcd集羣,爲了不意外發生,最好使用-initial-cluster-token參數爲每一個集羣單獨配置一個token認證。這樣就能夠確保每一個集羣和集羣的成員都擁有獨特的ID。

 

etcd自發現模式

 

 

DNS自發現模式

 

 

Proxy模式

Proxy模式也是新版etcd的一個重要變動,etcd做爲一個反向代理把客戶的請求轉發給可用的etcd集羣。這樣,就能夠在每一臺機器都部署一個Proxy模式的etcd做爲本地服務,若是這些etcd Proxy都能正常運行,那麼服務發現必然是穩定可靠的。

圖11 Proxy模式示意圖

因此Proxy並非直接加入到符合強一致性的etcd集羣中,也一樣的,Proxy並無增長集羣的可靠性,固然也沒有下降集羣的寫入性能。

Proxy取代Standby模式的緣由

那麼,爲何要有Proxy模式而不是直接增長etcd核心節點呢?

實際上etcd每增長一個核心節點(peer),都會增長Leader節點必定程度的包括網絡、CPU和磁盤的負擔,由於每次信息的變化都須要進行同步備份。增長etcd的核心節點可讓整個集羣具備更高的可靠性,可是當數量達到必定程度之後,增長可靠性帶來的好處就變得不那麼明顯,反卻是下降了集羣寫入同步的性能。所以,增長一個輕量級的Proxy模式etcd節點是對直接增長etcd核心節點的一個有效代替。

熟悉0.4.6這個舊版本etcd的用戶會發現,Proxy模式其實是取代了原先的Standby模式。Standby模式除了轉發代理的功能之外,還會在覈心節點由於故障致使數量不足的時候,從Standby模式轉爲正常節點模式。而當那個故障的節點恢復時,發現etcd的核心節點數量已經達到的預先設置的值,就會轉爲Standby模式。

可是新版etcd中,只會在最初啓動etcd集羣時,發現核心節點的數量已經知足要求時,自動啓用Proxy模式,反之則並未實現。主要緣由以下。

  • etcd是用來保證高可用的組件,所以它所須要的系統資源(包括內存、硬盤和CPU等)都應該獲得充分保障以保證高可用。任由集羣的自動變換隨意地改變核心節點,沒法讓機器保證性能。因此etcd官方鼓勵你們在大型集羣中爲運行etcd準備專有機器集羣。
  • 由於etcd集羣是支持高可用的,部分機器故障並不會致使功能失效。因此機器發生故障時,管理員有充分的時間對機器進行檢查和修復。
  • 自動轉換使得etcd集羣變得複雜,尤爲是現在etcd支持多種網絡環境的監聽和交互。在不一樣網絡間進行轉換,更容易發生錯誤,致使集羣不穩定。

基於上述緣由,目前Proxy模式有轉發代理功能,而不會進行角色轉換

 

數據存儲

etcd的存儲分爲內存存儲和持久化(硬盤)存儲兩部分,內存中的存儲除了順序化的記錄下全部用戶對節點數據變動的記錄外,還會對用戶數據進行索引、建堆等方便查詢的操做。而持久化則使用預寫式日誌(WAL:Write Ahead Log)進行記錄存儲。

在WAL的體系中,全部的數據在提交以前都會進行日誌記錄。

在etcd的持久化存儲目錄中,有兩個子目:一個是WAL,存儲着全部事務的變化記錄;另外一個則是snapshot,用於存儲某一個時刻etcd全部目錄的數據。經過WAL和snapshot相結合的方式,etcd能夠有效的進行數據存儲和節點故障恢復等操做。

既然有了WAL實時存儲了全部的變動,爲何還須要snapshot呢?隨着使用量的增長,WAL存儲的數據會暴增,爲了防止磁盤很快就爆滿,etcd默認每10000條記錄作一次snapshot,通過snapshot之後的WAL文件就能夠刪除。而經過API能夠查詢的歷史etcd操做默認爲1000條。

首次啓動時,etcd會把啓動的配置信息存儲到data-dir參數指定的數據目錄中。配置信息包括本地節點的ID、集羣ID和初始時集羣信息。用戶須要避免etcd從一個過時的數據目錄中從新啓動,由於使用過時的數據目錄啓動的節點會與集羣中的其餘節點產生不一致(如:以前已經記錄並贊成Leader節點存儲某個信息,重啓後又向Leader節點申請這個信息)。因此,爲了最大化集羣的安全性,一旦有任何數據損壞或丟失的可能性,你就應該把這個節點從集羣中移除,而後加入一個不帶數據目錄的新節點。

預寫式日誌(WAL)

WAL(Write Ahead Log)最大的做用是記錄了整個數據變化的所有歷程。在etcd中,全部數據的修改在提交前,都要先寫入到WAL中。使用WAL進行數據的存儲使得etcd擁有兩個重要功能。

  • 故障快速恢復: 當你的數據遭到破壞時,就能夠經過執行全部WAL中記錄的修改操做,快速從最原始的數據恢復到數據損壞前的狀態。
  • 數據回滾(undo)/重作(redo):由於全部的修改操做都被記錄在WAL中,須要回滾或重作,只須要方向或正向執行日誌中的操做便可。

 

7Raft

新版etcd中,raft包就是對Raft一致性算法的具體實現。關於Raft算法的講解,網上已經有不少文章,有興趣的讀者能夠去閱讀一下Raft算法論文很是精彩。本文則再也不對Raft算法進行詳細描述,而是結合etcd,針對算法中一些關鍵內容以問答的形式進行講解。有關Raft算法的術語若是不理解,能夠參見概念詞彙表一節。

Raft常見問答一覽

  • Raft中一個Term(任期)是什麼意思? Raft算法中,從時間上,一個任期講即從一次競選開始到下一次競選開始。從功能上講,若是Follower接收不到Leader節點的心跳信息,就會結束當前任期,變爲Candidate發起競選,有助於Leader節點故障時集羣的恢復。發起競選投票時,任期值小的節點不會競選成功。若是集羣不出現故障,那麼一個任期將無限延續下去。而投票出現衝突也有可能直接進入下一任再次競選。

    圖12 Term示意圖

  • Raft狀態機是怎樣切換的? Raft剛開始運行時,節點默認進入Follower狀態,等待Leader發來心跳信息。若等待超時,則狀態由Follower切換到Candidate進入下一輪term發起競選,等到收到集羣多數節點的投票時,該節點轉變爲Leader。Leader節點有可能出現網絡等故障,致使別的節點發起投票成爲新term的Leader,此時原先的老Leader節點會切換爲Follower。Candidate在等待其它節點投票的過程當中若是發現別的節點已經競選成功成爲Leader了,也會切換爲Follower節點。

    圖13 Raft狀態機

  • 如何保證最短期內競選出Leader,防止競選衝突? 在Raft狀態機一圖中能夠看到,在Candidate狀態下, 有一個times out,這裏的times out時間是個隨機值,也就是說,每一個機器成爲Candidate之後,超時發起新一輪競選的時間是各不相同的,這就會出現一個時間差。在時間差內,若是Candidate1收到的競選信息比本身發起的競選信息term值大(即對方爲新一輪term),而且新一輪想要成爲Leader的Candidate2包含了全部提交的數據,那麼Candidate1就會投票給Candidate2。這樣就保證了只有很小的機率會出現競選衝突。
  • 如何防止別的Candidate在遺漏部分數據的狀況下發起投票成爲Leader? Raft競選的機制中,使用隨機值決定超時時間,第一個超時的節點就會提高term編號發起新一輪投票,通常狀況下別的節點收到競選通知就會投票。可是,若是發起競選的節點在上一個term中保存的已提交數據不完整,節點就會拒絕投票給它。經過這種機制就能夠防止遺漏數據的節點成爲Leader。
  • Raft某個節點宕機後會如何? 一般狀況下,若是是Follower節點宕機,若是剩餘可用節點數量超過半數,集羣能夠幾乎沒有影響的正常工做。若是是Leader節點宕機,那麼Follower就收不到心跳而超時,發起競選得到投票,成爲新一輪term的Leader,繼續爲集羣提供服務。須要注意的是;etcd目前沒有任何機制會自動去變化整個集羣總共的節點數量,即若是沒有人爲的調用API,etcd宕機後的節點仍然被計算爲總節點數中,任何請求被確認須要得到的投票數都是這個總數的半數以上。

    圖14 節點宕機

  • 爲何Raft算法在肯定可用節點數量時不須要考慮拜占庭將軍問題? 拜占庭問題中提出,容許n個節點宕機還能提供正常服務的分佈式架構,須要的總節點數量爲3n+1,而Raft只須要2n+1就能夠了。其主要緣由在於,拜占庭將軍問題中存在數據欺騙的現象,而etcd中假設全部的節點都是誠實的。etcd在競選前須要告訴別的節點自身的term編號以及前一輪term最終結束時的index值,這些數據都是準確的,其餘節點能夠根據這些值決定是否投票。另外,etcd嚴格限制Leader到Follower這樣的數據流向保證數據一致不會出錯。
  • 用戶從集羣中哪一個節點讀寫數據? Raft爲了保證數據的強一致性,全部的數據流向都是一個方向,從Leader流向Follower,也就是全部Follower的數據必須與Leader保持一致,若是不一致會被覆蓋。即全部用戶更新數據的請求都最早由Leader得到,而後存下來通知其餘節點也存下來,等到大多數節點反饋時再把數據提交。一個已提交的數據項纔是Raft真正穩定存儲下來的數據項,再也不被修改,最後再把提交的數據同步給其餘Follower。由於每一個節點都有Raft已提交數據準確的備份(最壞的狀況也只是已提交數據還未徹底同步),因此讀的請求任意一個節點均可以處理。
  • etcd實現的Raft算法性能如何? 單實例節點支持每秒1000次數據寫入。節點越多,因爲數據同步涉及到網絡延遲,會根據實際狀況愈來愈慢,而讀性能會隨之變強,由於每一個節點都能處理用戶請求。

     

     

    參考文獻

    [01] http://openstack.wiaapp.com/?p=766

    [02] http://www.infoq.com/cn/articles/etcd-interpretation-application-scenario-implement-principle

相關文章
相關標籤/搜索