什麼是ETCD及其應用場景
源自公眾號:BiggerBoy
一、什麼是etcd?
etcd 發音為/ˈɛtsiːdiː/,名字的由來,「distributed etc directory.」,意思是「分佈式etc目錄」,說明它存的是大型分佈式系統的配置信息。
官網的一句話
A distributed, reliable key-value store for the most critical data of a distributed system.
翻譯並理解過來就是:一個用於存儲分佈式系統中最關鍵的數據的倉庫,它是分佈式的、可靠的鍵值對倉庫。
首先它是個數據存儲倉庫,它的特性是分佈式的、可靠性的,數據存儲格式是鍵值對存儲,它主要用於存儲分佈式系統中的關鍵數據。
另外在官方的FAQ文檔中
//etcd.io/docs/v3.5/faq/是這麼解釋etcd的:
etcd 是一個一致的分佈式鍵值存儲。在分佈式系統中主要用作單獨的協調服務。並且旨在保存可以完全放入內存的少量數據。
說明它的數據是存在於內存的,並且建議存少量數據。看到協調服務我們很快會想到Zookeeper,並且Zookeeper也是分佈式的高可用的分佈式協調者,數據也是存在於內存。那二者有什麼區別呢?下文會講。
二、etcd的由來
隨着CoreOS和Kubernetes等項目在開源社區日益火熱,它們項目中都用到的etcd組件作為一個高可用、強一致性的服務發現存儲倉庫,漸漸為開發人員所關注。在雲計算時代,如何讓服務快速透明地接入到計算集群中,如何讓共享配置信息快速被集群中的所有機器發現,更為重要的是,如何構建這樣一套高可用、安全、易於部署以及響應快速的服務集群,已經成為了迫切需要解決的問題。etcd為解決這類問題帶來了福音
實際上,etcd作為一個受到Zookeeper與doozer啟發而催生的項目,除了擁有與之類似的功能外,更具有以下4個特點{![引自Docker官方文檔]}。
-
簡單:基於HTTP+JSON的API讓你用curl命令就可以輕鬆使用。
-
安全:可選SSL客戶認證機制。
-
快速:每個實例每秒支持一千次寫操作。
-
可信:使用Raft算法充分實現了分佈式。
隨着雲計算的不斷發展,分佈式系統中涉及的問題越來越受到人們重視。受上一篇
三、etcd的應用場景
3.1 場景一:服務發現
服務發現(Service Discovery)要解決的是分佈式系統中最常見的問題之一,即在同一個分佈式集群中的進程或服務如何才能找到對方並建立連接。從本質上說,服務發現就是想要了解集群中是否有進程在監聽udp或tcp端口,並且通過名字就可以進行查找和連接。要解決服務發現的問題,需要有下面三大支柱,缺一不可。
一個強一致性、高可用的服務存儲目錄。基於Raft算法的etcd天生就是這樣一個強一致性高可用的服務存儲目錄。
一種註冊服務和監控服務健康狀態的機制。用戶可以在etcd中註冊服務,並且對註冊的服務設置key TTL,定時保持服務的心跳以達到監控健康狀態的效果。
一種查找和連接服務的機制。通過在etcd指定的主題下註冊的服務也能在對應的主題下查找到。為了確保連接,我們可以在每個服務機器上都部署一個proxy模式的etcd,這樣就可以確保能訪問etcd集群的服務都能互相連接。
圖1所示為服務發現示意圖。
圖1 服務發現示意圖
下面我們來看一下服務發現對應的具體應用場景。
微服務協同工作架構中,服務動態添加。隨着Docker容器的流行,多種微服務共同協作,構成一個功能相對強大的架構的案例越來越多。透明化的動態添加這些服務的需求也日益強烈。通過服務發現機制,在etcd中註冊某個服務名字的目錄,在該目錄下存儲可用的服務節點的IP。在使用服務的過程中,只要從服務目錄下查找可用的服務節點進行使用即可。微服務協同工作如圖2所示。
圖2 微服務協同工作
PaaS平台中應用多實例與實例故障重啟透明化。PaaS平台中的應用一般都有多個實例,通過域名,不僅可以透明地對多個實例進行訪問,而且還可以實現負載均衡。但是應用的某個實例隨時都有可能故障重啟,這時就需要動態地配置域名解析(路由)中的信息。通過etcd的服務發現功能就可以輕鬆解決這個動態配置的問題,如圖33所示。
雲平台多實例透明化
圖3 雲平台多實例透明化
3.2 場景二:消息發佈與訂閱
在分佈式系統中,最為適用的組件間通信方式是消息發佈與訂閱機制。具體而言,即構建一個配置共享中心,數據提供者在這個配置中心發佈消息,而消息使用者則訂閱他們關心的主題,一旦相關主題有消息發佈,就會實時通知訂閱者。通過這種方式可以實現分佈式系統配置的集中式管理與實時動態更新。
應用中用到的一些配置信息存放在etcd上進行集中管理。這類場景的使用方式通常是這樣的:應用在啟動的時候主動從etcd獲取一次配置信息,同時,在etcd節點上註冊一個Watcher並等待,以後每次配置有更新的時候,etcd都會實時通知訂閱者,以此達到獲取最新配置信息的目的。
分佈式搜索服務中,索引的元信息和服務器集群機器的節點狀態信息存放在etcd中,供各個客戶端訂閱使用。使用etcd的key TTL
功能可以確保機器狀態是實時更新的。
分佈式日誌收集系統。這個系統的核心工作是收集分佈在不同機器上的日誌。收集器通常按照應用(或主題)來分配收集任務單元,因此可以在etcd上創建一個以應用(或主題)命名的目錄P,並將這個應用(或主題)相關的所有機器ip,以子目錄的形式存儲在目錄P下,然後設置一個遞歸的etcd Watcher,遞歸式地監控應用(或主題)目錄下所有信息的變動。這樣就實現了在機器IP(消息)發生變動時,能夠實時通知收集器調整任務分配。
系統中信息需要動態自動獲取與人工干預修改信息請求內容的情況。通常的解決方案是對外暴露接口,例如JMX接口,來獲取一些運行時的信息或提交修改的請求。而引入etcd之後,只需要將這些信息存放到指定的etcd目錄中,即可通過HTTP接口直接被外部訪問。
圖4 消息發佈與訂閱
3.3 場景三:負載均衡
在場景一
中也提到了負載均衡,本文提及的負載均衡均指軟負載均衡。在分佈式系統中,為了保證服務的高可用以及數據的一致性,通常都會把數據和服務部署多份,以此達到對等服務,即使其中的某一個服務失效了,也不影響使用。這樣的實現雖然會導致一定程度上數據寫入性能的下降,但是卻能實現數據訪問時的負載均衡。因為每個對等服務節點上都存有完整的數據,所以用戶的訪問流量就可以分流到不同的機器上。
etcd本身分佈式架構存儲的信息訪問支持負載均衡。etcd集群化以後,每個etcd的核心節點都可以處理用戶的請求。所以,把數據量小但是訪問頻繁的消息數據直接存儲到etcd中也是個不錯的選擇,如業務系統中常用的二級代碼表。二級代碼表的工作過程一般是這樣,在表中存儲代碼,在etcd中存儲代碼所代表的具體含義,業務系統調用查表的過程,就需要查找表中代碼的含義。所以如果把二級代碼表中的小量數據存儲到etcd中,不僅方便修改,也易於大量訪問。
利用etcd維護一個負載均衡節點表。etcd可以監控一個集群中多個節點的狀態,當有一個請求發過來後,可以輪詢式地把請求轉發給存活着的多個節點。類似KafkaMQ,通過Zookeeper來維護生產者和消費者的負載均衡。同樣也可以用etcd來做Zookeeper的工作。
圖5 負載均衡
3.4 場景四:分佈式通知與協調
這裡討論的分佈式通知與協調,與消息發佈和訂閱有些相似。兩者都使用了etcd中的Watcher機制,通過註冊與異步通知機制,實現分佈式環境下不同系統之間的通知與協調,從而對數據變更進行實時處理。實現方式通常為:不同系統都在etcd上對同一個目錄進行註冊,同時設置Watcher監控該目錄的變化(如果對子目錄的變化也有需要,可以設置成遞歸模式),當某個系統更新了etcd的目錄,那麼設置了Watcher的系統就會收到通知,並作出相應處理。
通過etcd進行低耦合的心跳檢測。檢測系統和被檢測系統通過etcd上某個目錄關聯而非直接關聯起來,這樣可以大大減少系統的耦合性。
通過etcd完成系統調度。某系統有控制台和推送系統兩部分組成,控制台的職責是控制推送系統進行相應的推送工作。管理人員在控制台做的一些操作,實際上只需要修改etcd上某些目錄節點的狀態,而etcd就會自動把這些變化通知給註冊了Watcher的推送系統客戶端,推送系統再做出相應的推送任務。
通過etcd完成工作彙報。大部分類似的任務分發系統,子任務啟動後,到etcd來註冊一個臨時工作目錄,並且定時將自己的進度進行彙報(將進度寫入到這個臨時目錄),這樣任務管理者就能夠實時知道任務進度。
圖6 分佈式協同工作
3.5 場景五:分佈式鎖
因為etcd使用Raft算法保持了數據的強一致性,某次操作存儲到集群中的值必然是全局一致的,所以很容易實現分佈式鎖。鎖服務有兩種使用方式,一是保持獨佔,二是控制時序。
保持獨佔,即所有試圖獲取鎖的用戶最終只有一個可以得到。etcd為此提供了一套實現分佈式鎖原子操作CAS(CompareAndSwap
)的API。通過設置prevExist
值,可以保證在多個節點同時創建某個目錄時,只有一個成功,而該用戶即可認為是獲得了鎖。
控制時序,即所有試圖獲取鎖的用戶都會進入等待隊列,獲得鎖的順序是全局唯一的,同時決定了隊列執行順序。etcd為此也提供了一套API(自動創建有序鍵),對一個目錄建值時指定為POST
動作,這樣etcd會自動在目錄下生成一個當前最大的值為鍵,存儲這個新的值(客戶端編號)。同時還可以使用API按順序列出所有當前目錄下的鍵值。此時這些鍵的值就是客戶端的時序,而這些鍵中存儲的值可以是代表客戶端的編號。
圖7 分佈式鎖
3.6 場景六:分佈式隊列
分佈式隊列的常規用法與場景五中所描述的分佈式鎖的控制時序用法類似,即創建一個先進先出的隊列,保證順序。另一種比較有意思的實現是在保證隊列達到某個條件時再統一按順序執行。這種方法的實現可以在/queue
這個目錄中另外建立一個/queue/condition
節點。
condition可以表示隊列大小。比如一個大的任務需要很多小任務就緒的情況下才能執行,每次有一個小任務就緒,就給這個condition數字加1,直到達到大任務規定的數字,再開始執行隊列里的一系列小任務,最終執行大任務。
condition可以表示某個任務在不在隊列。這個任務可以是所有排序任務的首個執行程序,也可以是拓撲結構中沒有依賴的點。通常,必須執行這些任務後才能執行隊列中的其他任務。
condition還可以表示其它的一類開始執行任務的通知。可以由控制程序指定,當condition出現變化時,開始執行隊列任務。
圖8 分佈式隊列
3.7 場景七:集群監控與Leader競選
通過etcd來進行監控實現起來非常簡單並且實時性強,用到了以下兩點特性。
-
前面幾個場景已經提到Watcher機制,當某個節點消失或有變動時,Watcher會第一時間發現並告知用戶。
-
節點可以設置TTL key,比如每隔30s向etcd發送一次心跳使代表該節點仍然存活,否則說明節點消失。
這樣就可以第一時間檢測到各節點的健康狀態,以完成集群的監控要求。
另外,使用分佈式鎖,可以完成Leader競選。對於一些長時間CPU計算或者使用IO操作,只需要由競選出的Leader計算或處理一次,再把結果複製給其他Follower即可,從而避免重複勞動,節省計算資源。
Leader應用的經典場景是在搜索系統中建立全量索引。如果每個機器分別進行索引的建立,不但耗時,而且不能保證索引的一致性。通過在etcd的CAS機制競選Leader,由Leader進行索引計算,再將計算結果分發到其它節點。
圖9 Leader競選
3.8 場景八:為什麼用etcd而不用Zookeeper?
閱讀了「
相較之下,Zookeeper有如下缺點:
-
複雜。Zookeeper的部署維護複雜,管理員需要掌握一系列的知識和技能;而Paxos強一致性算法也是素來以複雜難懂而聞名於世;另外,Zookeeper的使用也比較複雜,需要安裝客戶端,官方只提供了java和C兩種語言的接口。
-
Java編寫。這裡不是對Java有偏見,而是Java本身就偏向於重型應用,它會引入大量的依賴。而運維人員則普遍希望機器集群儘可能簡單,維護起來也不易出錯。
-
發展緩慢。Apache基金會項目特有的「Apache Way」在開源界飽受爭議,其中一大原因就是由於基金會龐大的結構以及鬆散的管理導致項目發展緩慢。
而etcd作為一個後起之秀,其優點也很明顯。
-
簡單。使用Go語言編寫部署簡單;使用HTTP作為接口使用簡單;使用Raft算法保證強一致性讓用戶易於理解。
-
數據持久化。etcd默認數據一更新就進行持久化。
-
安全。etcd支持SSL客戶端安全認證。
最後,etcd作為一個年輕的項目,正在高速迭代和開發中,這既是一個優點,也是一個缺點。優點在於它的未來具有無限的可能性,缺點是版本的迭代導致其使用的可靠性無法保證,無法得到大項目長時間使用的檢驗。然而,目前CoreOS、Kubernetes和Cloudfoundry等知名項目均在生產環境中使用了etcd,所以總的來說,etcd值得你去嘗試。
參考//etcd.io/docs/v3.5/faq/
摘自
//www.sel.zju.edu.cn/blog/2015/02/01/etcd%E4%BB%8E%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%E5%88%B0%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86%E7%9A%84%E5%85%A8%E6%96%B9%E4%BD%8D%E8%A7%A3%E8%AF%BB/