etcd簡介
etcd是一個非常可靠的kv存儲系統,常在分布式系統中存儲着關鍵的數據。它是由coreos團隊開發並開源的分布式鍵值存儲系統,具備以下特點:
- 簡單:提供定義明確且面向用戶的API
- 安全:支持SSL證書驗證
- 性能:基准壓測支持1w+/sec寫入
- 可靠:采用Raft協議保證分布式系統數據的可用性和一致性。
etcd的這些特性,使得它常常出現在分布式設計場景下的工具集中。它在現代化的集群運行中能夠起到關鍵性的作用。
etcd項目地址:https://github.com/coreos/etcd/
etcd常見功能
- 鍵值存儲、查詢功能:支持精准查詢、range操作、ttl機制、key版本等。
- 一致性機制:采用raft協議保證強一致性。
- 可用性機制:提供集群和leader選舉機制。
- SSL認證機制。
- watch機制。
etcd常見應用場景
1. 配置中心
etcd是一個分布式的鍵值存儲系統,其優秀的讀寫性能、一致性和可用性的機制,非常適合用來做配置中心角色。
2. 分布式鎖

etcd 使用 Raft 算法保持了數據的強一致性,某次操作存儲到集群中的值必然是全局一致的,所以很容易實現分布式鎖。鎖服務有兩種使用方式,一是保持獨占,二是控制時序。
- 保持獨占即所有獲取鎖的用戶最終只有一個可以得到。etcd 為此提供了一套實現分布式鎖原子操作 CAS(CompareAndSwap)的 API。通過設置prevExist值,可以保證在多個節點同時去創建某個目錄時,只有一個成功。而創建成功的用戶就可以認為是獲得了鎖。
- 控制時序,即所有想要獲得鎖的用戶都會被安排執行,但是獲得鎖的順序也是全局唯一的,同時決定了執行順序。etcd 為此也提供了一套 API(自動創建有序鍵),對一個目錄建值時指定為POST動作,這樣 etcd 會自動在目錄下生成一個當前最大的值為鍵,存儲這個新的值(客戶端編號)。同時還可以使用 API 按順序列出所有當前目錄下的鍵值。此時這些鍵的值就是客戶端的時序,而這些鍵中存儲的值可以是代表客戶端的編號。
3. leader選舉組件

通過 etcd 來進行監控實現起來非常簡單並且實時性強。
- 前面幾個場景已經提到 Watcher 機制,當某個節點消失或有變動時,Watcher 會第一時間發現並告知用戶。
- 節點可以設置TTL key,比如每隔 30s 發送一次心跳使代表該機器存活的節點繼續存在,否則節點消失。
這樣就可以第一時間檢測到各節點的健康狀態,以完成集群的監控要求。
另外,使用分布式鎖,可以完成 Leader 競選。這種場景通常是一些長時間 CPU 計算或者使用 IO 操作的機器,只需要競選出的 Leader 計算或處理一次,就可以把結果復制給其他的 Follower。從而避免重復勞動,節省計算資源。
這個的經典場景是搜索系統中建立全量索引。如果每個機器都進行一遍索引的建立,不但耗時而且建立索引的一致性不能保證。通過在 etcd 的 CAS 機制同時創建一個節點,創建成功的機器作為 Leader,進行索引計算,然后把計算結果分發到其它節點。
分布式場景下,常采用leader-follower模式來保證有狀態服務的高可用(即使leader掛掉,其他follower立馬補上),比如k8s和kafka partition高可用機制。可以很方便的借助etcd來實現leader選舉機制,這里有個leader election實現:https://github.com/willstudy/leaderelection
4. 服務注冊與服務發現

為了解決微服務場景下,服務地址的注冊和發現問題。和配置中心功能類似,不同之處在於服務注冊和服務發現,還伴隨着狀態檢測。
在同一個分布式集群中的進程或服務如何才能找到對方並建立連接。從本質上說,服務發現就是要了解集群中是否有進程在監聽udp或者tcp端口,並且通過名字就可以進行查找和鏈接。
要解決服務發現的問題,需要下面三大支柱,缺一不可。
- 一個強一致性、高可用的服務存儲目錄。
基於Ralf算法的etcd天生就是這樣一個強一致性、高可用的服務存儲目錄。
- 一種注冊服務和健康服務健康狀況的機制。
用戶可以在etcd中注冊服務,並且對注冊的服務配置key TTL,定時保持服務的心跳以達到監控健康狀態的效果。
- 一種查找和連接服務的機制。
通過在etcd指定的主題下注冊的服務業能在對應的主題下查找到。為了確保連接,我們可以在每個服務機器上都部署一個proxy模式的etcd,這樣就可以確保訪問etcd集群的服務都能夠互相連接。
5. 消息訂閱和發布
etcd內置watch機制,完全可以實現一個小型的消息訂閱和發布組件。
在分布式系統中,最適用的一種組件間通信方式就是消息發布與訂閱。即構建一個配置共享中心,數據提供者在這個配置中心發布消息,而消息使用者則訂閱他們關心的主題,一旦主題有消息發布,就會實時通知訂閱者。通過這種方式可以做到分布式系統配置的集中式管理與動態更新。
- 應用中用到的一些配置信息放到 etcd 上進行集中管理。這類場景的使用方式通常是這樣:應用在啟動的時候主動從 etcd 獲取一次配置信息,同時,在 etcd 節點上注冊一個 Watcher 並等待,以后每次配置有更新的時候,etcd 都會實時通知訂閱者,以此達到獲取最新配置信息的目的。
- 分布式搜索服務中,索引的元信息和服務器集群機器的節點狀態存放在 etcd 中,供各個客戶端訂閱使用。使用 etcd 的key TTL功能可以確保機器狀態是實時更新的。
- 分布式日志收集系統。這個系統的核心工作是收集分布在不同機器的日志。收集器通常是按照應用(或主題)來分配收集任務單元,因此可以在 etcd 上創建一個以應用(主題)命名的目錄 P,並將這個應用(主題相關)的所有機器 ip,以子目錄的形式存儲到目錄 P 上,然后設置一個 etcd 遞歸的 Watcher,遞歸式的監控應用(主題)目錄下所有信息的變動。這樣就實現了機器 IP(消息)變動的時候,能夠實時通知到收集器調整任務分配。
- 系統中信息需要動態自動獲取與人工干預修改信息請求內容的情況。通常是暴露出接口,例如 JMX 接口,來獲取一些運行時的信息。引入 etcd 之后,就不用自己實現一套方案了,只要將這些信息存放到指定的 etcd 目錄中即可,etcd 的這些目錄就可以通過 HTTP 的接口在外部訪問。

6.分布式隊列

分布式隊列的常規用法與場景五中所描述的分布式鎖的控制時序用法類似,即創建一個先進先出的隊列,保證順序。
另一種比較有意思的實現是在保證隊列達到某個條件時再統一按順序執行。這種方法的實現可以在 /queue 這個目錄中另外建立一個 /queue/condition 節點。
- condition 可以表示隊列大小。比如一個大的任務需要很多小任務就緒的情況下才能執行,每次有一個小任務就緒,就給這個 condition 數字加 1,直到達到大任務規定的數字,再開始執行隊列里的一系列小任務,最終執行大任務。
- condition 可以表示某個任務在不在隊列。這個任務可以是所有排序任務的首個執行程序,也可以是拓撲結構中沒有依賴的點。通常,必須執行這些任務后才能執行隊列中的其他任務。
- condition 還可以表示其它的一類開始執行任務的通知。可以由控制程序指定,當 condition 出現變化時,開始執行隊列任務。
7.負載均衡
在場景一中也提到了負載均衡,本文所指的負載均衡均為軟負載均衡。分布式系統中,為了保證服務的高可用以及數據的一致性,通常都會把數據和服務部署多份,以此達到對等服務,即使其中的某一個服務失效了,也不影響使用。由此帶來的壞處是數據寫入性能下降,而好處則是數據訪問時的負載均衡。因為每個對等服務節點上都存有完整的數據,所以用戶的訪問流量就可以分流到不同的機器上。
- etcd 本身分布式架構存儲的信息訪問支持負載均衡。etcd 集群化以后,每個 etcd 的核心節點都可以處理用戶的請求。所以,把數據量小但是訪問頻繁的消息數據直接存儲到 etcd 中也是個不錯的選擇,如業務系統中常用的二級代碼表(在表中存儲代碼,在 etcd 中存儲代碼所代表的具體含義,業務系統調用查表的過程,就需要查找表中代碼的含義)。
- 利用 etcd 維護一個負載均衡節點表。etcd 可以監控一個集群中多個節點的狀態,當有一個請求發過來后,可以輪詢式的把請求轉發給存活着的多個狀態。類似 KafkaMQ,通過ZooKeeper來維護生產者和消費者的負載均衡。同樣也可以用 etcd 來做ZooKeeper的工作。
-

etcd和同類型產品的對比
2.1 etcd vs redis
etcd誕生之日起,就定位成一種分布式存儲系統,並在k8s 服務注冊和服務發現中,為大家所認識。它偏重的是節點之間的通信和一致性的機制保證,並不強調單節點的讀寫性能。
而redis最早作為緩存系統出現在大眾視野,也注定了redis需要更加側重於讀寫性能和支持更多的存儲模式,它不需要care一致性,也不需要側重事務,因此可以達到很高的讀寫性能。
總結一下,redis常用來做緩存系統,etcd常用來做分布式系統中一些關鍵數據的存儲服務,比如服務注冊和服務發現。
2.2 etcd vs consul
consul定位是一個端到端的服務框架,提供了內置的監控檢查、DNS服務等,除此之外,還提供了HTTP API和Web UI,如果要實現簡單的服務發現,基本上可以開箱即用。
但是缺點同樣也存在,封裝有利有弊,就導致靈活性弱了不少。除此之外,consul還比較年輕,暫未在大型項目中實踐,可靠性還未可知。
2.3 etcd vs zookeeper
etcd站在了巨人的肩膀上
3. etcd性能表現
來自於官網介紹:https://etcd.io/docs/v3.4.0/op-guide/performance/ 大致總結一下:
- 讀:1w ~ 10w 之間
- 寫:1w左右
建議:
- etcd需要部署到ssd盤(強烈建議)
- 多個寫采用batch操作。
- 非必要情況下,避免range操作。
etcd集群更偏重一致性和穩定性,並不強調高性能,在絕大部分場景下均不會到達etcd性能瓶頸,如果出現瓶頸的話,需要重新review架構設計,比如拆分或者優化流程。
