Etcd 按照官方介紹
java
Etcd is a distributed, consistent key-value store for shared configuration and service discovery算法
etcd 是一個分佈式一致性鍵值存儲,用於共享配置和服務發現,專一於:apache
簡單: 良好定義的,面向用戶的API (gRPC)
安全: 帶有可選客戶端證書認證的自動 TLS
快速: 測試驗證,每秒 10000 寫入
可靠: 使用Raft適當分佈安全
etcd是Go編寫,並使用 Raft 一致性算法來管理高可用複製日誌。網絡
爲何須要 Etcd 併發
全部的分佈式系統,都面臨的一個問題是多個節點之間的數據共享問題,這個和團隊協做的道理是同樣的,成員能夠分頭幹活,但老是須要共享一些必須的信息,好比誰是 leader, 都有哪些成員,依賴任務之間的順序協調等。因此分佈式系統要麼本身實現一個可靠的共享存儲來同步信息(好比 Elasticsearch ),要麼依賴一個可靠的共享存儲服務,而 Etcd 就是這樣一個服務。分佈式
Etcd 提供什麼能力ide
Etcd 主要提供如下能力,已經熟悉 Etcd 的讀者能夠略過本段。oop
提供存儲以及獲取數據的接口,它經過協議保證 Etcd 集羣中的多個節點數據的強一致性。用於存儲元信息以及共享配置。性能
提供監聽機制,客戶端能夠監聽某個key或者某些key的變動。用於監聽和推送變動。
提供key的過時以及續約機制,客戶端經過定時刷新來實現續約。用於集羣監控以及服務註冊發現。
提供原子的CAS(Compare-and-Swap)和 CAD(Compare-and-Delete)支持(v2經過接口參數實現,v3經過批量事務實現)。用於分佈式鎖以及leader選舉。
Etcd 如何實現一致性的
Etcd使用Raft協議來維護集羣內各個節點狀態的一致性。簡單說,Etcd集羣是一個分佈式系統,由多個節點相互通訊構成總體對外服務,每一個節點都存儲了完整的數據,而且經過Raft協議保證每一個節點維護的數據是一致的。
如圖所示,每一個Etcd節點都維護了一個狀態機,而且,任意時刻至多存在一個有效的主節點。主節點處理全部來自客戶端寫操做,經過Raft協議保證寫操做對狀態機的改動會可靠的同步到其餘節點。
Etcd工做原理核心部分在於Raft協議。本節接下來將簡要介紹Raft協議,具體細節請參考其[論文]。
Raft協議正如論文所述,確實方便理解。主要分爲三個部分:選主,日誌複製,安全性。
1) 選主
Raft協議是用於維護一組服務節點數據一致性的協議。這一組服務節點構成一個集羣,而且有一個主節點來對外提供服務。當集羣初始化,或者主節點掛掉後,面臨一個選主問題。集羣中每一個節點,任意時刻處於Leader, Follower, Candidate這三個角色之一。選舉特色以下:
當集羣初始化時候,每一個節點都是Follower角色;
集羣中存在至多1個有效的主節點,經過心跳與其餘節點同步數據;
當Follower在必定時間內沒有收到來自主節點的心跳,會將本身角色改變爲Candidate,併發起一次選主投票;當收到包括本身在內超過半數節點同意後,選舉成功;當收到票數不足半數選舉失敗,或者選舉超時。若本輪未選出主節點,將進行下一輪選舉(出現這種狀況,是因爲多個節點同時選舉,全部節點均爲得到過半選票)。
Candidate節點收到來自主節點的信息後,會當即終止選舉過程,進入Follower角色。
爲了不陷入選主失敗循環,每一個節點未收到心跳發起選舉的時間是必定範圍內的隨機值,這樣可以避免2個節點同時發起選主。
2) 日誌複製
所謂日誌複製,是指主節點將每次操做造成日誌條目,並持久化到本地磁盤,而後經過網絡IO發送給其餘節點。其餘節點根據日誌的邏輯時鐘(TERM)和日誌編號(INDEX)來判斷是否將該日誌記錄持久化到本地。當主節點收到包括本身在內超過半數節點成功返回,那麼認爲該日誌是可提交的(committed),並將日誌輸入到狀態機,將結果返回給客戶端。
這裏須要注意的是,每次選主都會造成一個惟一的TERM編號,至關於邏輯時鐘。每一條日誌都有全局惟一的編號。
主節點經過網絡IO向其餘節點追加日誌。若某節點收到日誌追加的消息,首先判斷該日誌的TERM是否過時,以及該日誌條目的INDEX是否比當前以及提交的日誌的INDEX跟早。若已過時,或者比提交的日誌更早,那麼就拒絕追加,並返回該節點當前的已提交的日誌的編號。不然,將日誌追加,並返回成功。
當主節點收到其餘節點關於日誌追加的回覆後,若發現有拒絕,則根據該節點返回的已提交日誌編號,發生其編號下一條日誌。
主節點像其餘節點同步日誌,還做了擁塞控制。具體地說,主節點發現日誌複製的目標節點拒絕了某第二天志追加消息,將進入日誌探測階段,一條一條發送日誌,直到目標節點接受日誌,而後進入快速複製階段,可進行批量日誌追加。
按照日誌複製的邏輯,咱們能夠看到,集羣中慢節點不影響整個集羣的性能。另一個特色是,數據只從主節點複製到Follower節點,這樣大大簡化了邏輯流程。
3) 安全性
截止此刻,選主以及日誌複製並不能保證節點間數據一致。試想,當一個某個節點掛掉了,一段時間後再次重啓,並當選爲主節點。而在其掛掉這段時間內,集羣如有超過半數節點存活,集羣會正常工做,那麼會有日誌提交。這些提交的日誌沒法傳遞給掛掉的節點。當掛掉的節點再次當選主節點,它將缺失部分已提交的日誌。在這樣場景下,按Raft協議,它將本身日誌複製給其餘節點,會將集羣已經提交的日誌給覆蓋掉。
這顯然是不可接受的。
其餘協議解決這個問題的辦法是,新當選的主節點會詢問其餘節點,和本身數據對比,肯定出集羣已提交數據,而後將缺失的數據同步過來。這個方案有明顯缺陷,增長了集羣恢復服務的時間(集羣在選舉階段不可服務),而且增長了協議的複雜度。
Raft解決的辦法是,在選主邏輯中,對可以成爲主的節點加以限制,確保選出的節點已定包含了集羣已經提交的全部日誌。若是新選出的主節點已經包含了集羣全部提交的日誌,那就不須要從和其餘節點比對數據了。簡化了流程,縮短了集羣恢復服務的時間。
這裏存在一個問題,加以這樣限制以後,還可否選出主呢?答案是:只要仍然有超過半數節點存活,這樣的主必定可以選出。由於已經提交的日誌必然被集羣中超過半數節點持久化,顯然前一個主節點提交的最後一條日誌也被集羣中大部分節點持久化。當主節點掛掉後,集羣中仍有大部分節點存活,那這存活的節點中必定存在一個節點包含了已經提交的日誌了。
至此,關於Raft協議的簡介就所有結束了。
Etcd的使用場景
和ZK相似,Etcd有不少使用場景,包括:
配置管理
服務註冊於發現
選主
應用調度
分佈式隊列
分佈式鎖
這三個產品是常常被人拿來作選型比較的。 Etcd 和 Zookeeper 提供的能力很是類似,都是通用的一致性元信息存儲,都提供watch機制用於變動通知和分發,也都被分佈式系統用來做爲共享信息存儲,在軟件生態中所處的位置也幾乎是同樣的,能夠互相替代的。兩者除了實現細節,語言,一致性協議上的區別,最大的區別在周邊生態圈。Zookeeper 是apache下的,用java寫的,提供rpc接口,最先從hadoop項目中孵化出來,在分佈式系統中獲得普遍使用(hadoop, solr, kafka, mesos 等)。Etcd 是coreos公司旗下的開源產品,比較新,以其簡單好用的rest接口以及活躍的社區俘獲了一批用戶,在新的一些集羣中獲得使用(好比kubernetes)。雖然v3爲了性能也改爲二進制rpc接口了,但其易用性上比 Zookeeper 仍是好一些。 而 Consul 的目標則更爲具體一些,Etcd 和 Zookeeper 提供的是分佈式一致性存儲能力,具體的業務場景須要用戶本身實現,好比服務發現,好比配置變動。而Consul 則以服務發現和配置變動爲主要目標,同時附帶了kv存儲。