etcd 笔记(01)— etcd 简介、特点、应用场景、常用术语、分布式 CAP 理论、分布式原理
1. etcd 簡介
etcd 官網(wǎng)定義:
A highly-available key value store for shared configuration and service discovery.
即一個用于配置共享和服務(wù)發(fā)現(xiàn)的鍵值存儲系統(tǒng)。
etcd 是一款分布式存儲中間件,使用 Go 語言編寫,并通過 Raft 一致性算法處理和確保分布式一致性,解決了分布式系統(tǒng)中數(shù)據(jù)一致性的問題。
而且作為一款分布式、可靠的鍵值存儲組件,etcd 常用于微服務(wù)架構(gòu)中的服務(wù)注冊與發(fā)現(xiàn)中心,相較于 ZooKeeper 部署更簡單,而且具有數(shù)據(jù)持久化、支持 SSL 客戶端安全認證的獨特優(yōu)勢。
etcd 作為一個可信賴的分布式鍵值存儲服務(wù),它能夠為整個分布式集群存儲一些關(guān)鍵數(shù)據(jù),協(xié)助分布式集群的正常運轉(zhuǎn)。
etcd 可集中管理配置信息。服務(wù)端將配置信息存儲于 etcd,客戶端通過 etcd 得到服務(wù)配置信息,etcd 監(jiān)聽配置信息的改變,發(fā)現(xiàn)改變通知客戶端。
而 etcd 滿足 CAP 理論中的 CP(一致性和分區(qū)容錯性) 指標,由此我們知道,etcd 解決了分布式系統(tǒng)中一致性存儲的問題。
2. etcd 特點
etcd 可以用來構(gòu)建高可用的分布式鍵值數(shù)據(jù)庫,總結(jié)來說有如下特點。
- 簡單:安裝簡單,且為用戶提供了
HTTP API,使用起來也很簡單; - 存儲:數(shù)據(jù)分層存儲在文件目錄中,類似于我們?nèi)粘J褂玫奈募到y(tǒng);
- Watch 機制:
Watch指定的鍵、前綴目錄的更改,并對更改時間進行通知; - 安全通信:支持
SSL證書驗證; - 高性能:
etcd單實例可以支持 2K/s 讀操作,官方也有提供基準測試腳本; - 一致可靠:基于
Raft共識算法,實現(xiàn)分布式系統(tǒng)內(nèi)部數(shù)據(jù)存儲、服務(wù)調(diào)用的一致性和高可用性; Revision機制:每個Key帶有一個Revision號,每進行一次事務(wù)便加一,因此它是全局唯一的,如初始值為 0,進行一次Put操作,Key的Revision變?yōu)?1,同樣的操作,再進行一次,Revision變?yōu)?2;換成Key1進行Put操作,Revision將變?yōu)?3。這種機制有一個作用,即通過Revision的大小就可知道寫操作的順序,這對于實現(xiàn)公平鎖,隊列十分有益;Lease機制:即租約機制(TTL,Time To Live),Etcd可以為存儲的Key-Value對設(shè)置租約,當租約到期,Key-Value將失效刪除;同時也支持續(xù)約,通過客戶端可以在租約到期之前續(xù)約,以避免Key-Value對過期失效;此外,還支持解約,一旦解約,與該租約綁定的Key-Value將失效刪除;
etcd 是一個實現(xiàn)了分布式一致性鍵值對存儲的中間件,支持跨平臺,etcd 集群中的節(jié)點基于 Raft 算法進行通信,Raft 算法保證了微服務(wù)實例或機器集群所訪問的數(shù)據(jù)的可靠一致性。
在分布式系統(tǒng)或者 Kubernetes 集群中,etcd 可以作為服務(wù)注冊與發(fā)現(xiàn)和鍵值對存儲組件。
3. 應(yīng)用場景
etcd 在穩(wěn)定性、可靠性和可伸縮性上表現(xiàn)極佳,同時也為云原生應(yīng)用系統(tǒng)提供了協(xié)調(diào)機制。etcd 經(jīng)常用于服務(wù)注冊與發(fā)現(xiàn)的場景,此外還有鍵值對存儲、消息發(fā)布與訂閱、分布式鎖等場景。
3.1 鍵值對存儲
etcd 是一個用于鍵值存儲的組件,存儲是 etcd 最基本的功能,其他應(yīng)用場景都建立在 etcd 的可靠存儲上。比如 Kubernetes 將一些元數(shù)據(jù)存儲在 etcd 中,將存儲狀態(tài)數(shù)據(jù)的復(fù)雜工作交給 etcd,Kubernetes 自身的功能和架構(gòu)就能更加穩(wěn)定。
3.2 服務(wù)注冊與發(fā)現(xiàn)
etcd 基于 Raft 算法,能夠有力地保證分布式場景中的一致性。各個服務(wù)啟動時注冊到 etcd 上,同時為這些服務(wù)配置鍵的 TTL 時間。注冊到 etcd 上面的各個服務(wù)實例通過心跳的方式定期續(xù)租,實現(xiàn)服務(wù)實例的狀態(tài)監(jiān)控。
3.3 消息發(fā)布與訂閱
在分布式系統(tǒng)中,服務(wù)之間還可以通過消息通信,即消息的發(fā)布與訂閱,如下圖所示:
通過構(gòu)建 etcd 消息中間件,服務(wù)提供者發(fā)布對應(yīng)主題的消息,消費者則訂閱他們關(guān)心的主題,一旦對應(yīng)的主題有消息發(fā)布,就會產(chǎn)生訂閱事件,消息中間件就會通知該主題所有的訂閱者。
3.4 分布式鎖
分布式系統(tǒng)中涉及多個服務(wù)實例,存在跨進程之間資源調(diào)用,對于資源的協(xié)調(diào)分配,單體架構(gòu)中的鎖已經(jīng)無法滿足需要,需要引入分布式鎖的概念。etcd 基于 Raft 算法,實現(xiàn)分布式集群的一致性,存儲到 etcd 集群中的值必然是全局一致的,因此基于 etcd 很容易實現(xiàn)分布式鎖。
4. etcd 的核心架構(gòu)
從上圖可知,etcd 有 etcd Server、gRPC Server、存儲相關(guān)的 MVCC 、Snapshot、WAL,以及 Raft 模塊。
其中:
etcd Server用于對外接收和處理客戶端的請求;gRPC Server則是etcd與其他etcd節(jié)點之間的通信和信息同步;MVCC即多版本控制,etcd的存儲模塊,鍵值對的每一次操作行為都會被記錄存儲,這些數(shù)據(jù)底層存儲在BoltDB數(shù)據(jù)庫中;WAL預(yù)寫式日志,etcd中的數(shù)據(jù)提交前都會記錄到日志;Snapshot快照,以防WAL日志過多,用于存儲某一時刻etcd的所有數(shù)據(jù);Snapshot和WAL相結(jié)合,etcd可以有效地進行數(shù)據(jù)存儲和節(jié)點故障恢復(fù)等操作;
雖然 etcd 內(nèi)部實現(xiàn)機制復(fù)雜,但對外提供了簡單的 API 接口,方便客戶端調(diào)用。我們可以通過 etcdctl 客戶端命令行操作和訪問 etcd 中的數(shù)據(jù),或者通過HTTP API 接口直接訪問 etcd。
etcd 中的數(shù)據(jù)結(jié)構(gòu)很簡單,它的數(shù)據(jù)存儲其實就是鍵值對的有序映射。etcd 還提供了一種鍵值對監(jiān)測機制,即 Watch 機制,客戶端通過訂閱相關(guān)的鍵值對,獲取其更改的事件信息。Watch 機制實時獲取 etcd 中的增量數(shù)據(jù)更新,使數(shù)據(jù)與 etcd 同步。
etcd 目前有 V2.x 和 V3.x 兩個大版本。etcd V2 和 V3 是在底層使用同一套 Raft 算法的兩個獨立應(yīng)用,但相互之間實現(xiàn)原理和使用方法上差別很大,接口不一樣、存儲不一樣,兩個版本的數(shù)據(jù)互相隔離。
至于由 etcd V2 升級到 etcd V3 的情況,原有數(shù)據(jù)只能通過 etcd V2 接口訪問,V3 接口創(chuàng)建的數(shù)據(jù)只能通過新的 V3 的接口訪問。
etcd 架構(gòu)圖:
通常,etcd 會監(jiān)聽兩個端口,默認是 2379 端口和 2380 端口。其中,2380 端口用于集群內(nèi)部通信,主要涉及集群間數(shù)據(jù)同步、心跳、選舉等。2379 端口用于與客戶端通信,比如接收客戶端發(fā)起的讀/寫數(shù)據(jù)請求。
etcd 節(jié)點在部署的時候有兩種運行模式:集群模式和代理模式。
當 etcd 節(jié)點以集群模式運行時,它會加入已有集群中,作為集群的一部分。也就是說,后續(xù)的心跳、數(shù)據(jù)同步、選舉等它都會參與。
集群模式中的節(jié)點數(shù)一般采用奇數(shù)個。為什么呢?因為假如同時有兩個 Candidate 發(fā)起選舉,如果是偶數(shù)節(jié)點的話,可能存在兩個 Candidate 獲得相同票數(shù)。
這會導(dǎo)致什么問題?如果兩個 Candidate 票數(shù)一樣,就需要再次發(fā)起選舉,而再次發(fā)起選舉還是有一定概率出現(xiàn)票數(shù)一樣,這會導(dǎo)致選舉耗時較多,影響穩(wěn)定性。所以,采用奇數(shù)個節(jié)點,能有效降低票數(shù)一樣的概率,提升選舉的效率。另外,使用奇數(shù)節(jié)點來部署,也能讓 etcd 很好地處理分區(qū)容錯問題。
當某個 etcd 節(jié)點以代理模式運行時,該節(jié)點負責(zé)將接收到的請求轉(zhuǎn)發(fā)給 etcd 集群節(jié)點。目前 etcd 接口有 v2 和 v3 兩個版本,其中 v2 是 HTTP 接口,v3 是 gRPC 接口。需要注意的是,代理模式只支持轉(zhuǎn)發(fā) v2 版本的請求,也就是只支持轉(zhuǎn)發(fā) HTTP 請求。
不過,由于 etcd v3 接口在性能、安全、穩(wěn)定性等方面要比 v2 接口優(yōu)秀很多,新項目傾向于使用 v3 接口,老項目也逐漸從 v2 接口遷移到 v3 接口。也就是說,代理模式以后可能逐漸被淘汰掉。
5. 分布式中的 CAP 理論
CAP 原理是描述分布式系統(tǒng)下節(jié)點數(shù)據(jù)同步的基本定理,分別指
Consistency(一致性)
指數(shù)據(jù)一致性,表示一個系統(tǒng)的數(shù)據(jù)信息(包括備份數(shù)據(jù))在同一時刻都是一致的。在分布式系統(tǒng)下,同一份數(shù)據(jù)可能存在于多個不同的實例中,在數(shù)據(jù)強一致性的要求下,修改其中一份數(shù)據(jù)后必須同步到它的所有備份中。在數(shù)據(jù)同步的任何時候,都需要保證所有對該份數(shù)據(jù)的請求將返回同樣的狀態(tài)。
Availability(可用性)
指服務(wù)可用性,要求服務(wù)在接收到客戶端請求后,都能夠給出響應(yīng)。服務(wù)可用性考量的是系統(tǒng)的可用性,要求系統(tǒng)在高并發(fā)情況和部分節(jié)點宕機的情況下,系統(tǒng)整體依然能夠響應(yīng)客戶端的請求。
Partition tolerance(分區(qū)容錯性)
指分區(qū)容忍性。在分布式系統(tǒng)中,不同節(jié)點之間通過網(wǎng)絡(luò)進行通信。由于網(wǎng)絡(luò)的不可靠性,位于不同網(wǎng)絡(luò)分區(qū)的服務(wù)節(jié)點可能會通信失敗,如果系統(tǒng)能夠容忍這種情況,說明它是滿足分區(qū)容忍性的。如果系統(tǒng)不能滿足,將會限制分布式系統(tǒng)的擴展性,即服務(wù)節(jié)點的部署數(shù)量和地區(qū)都會受限,也就違背了分布式系統(tǒng)設(shè)計的初衷,所以一般來說分布式系統(tǒng)都會滿足分區(qū)容忍性。
這三個要素最多只能同時實現(xiàn)兩點,不能三者兼顧。
基于分布式系統(tǒng)的基本特質(zhì),P(分區(qū)容錯性)是必須要滿足的,所以接下來需要考慮滿足 C(一致性)還是 A(可用性)。
但是在滿足了分區(qū)容忍性的前提下,分布式系統(tǒng)并不能同時滿足數(shù)據(jù)一致性和服務(wù)可用性。
假設(shè)服務(wù) A 現(xiàn)在有兩個實例 A1 和 A2,它們之間的網(wǎng)絡(luò)通信出現(xiàn)了異常,基于分區(qū)容忍性,這并不會影響 A1 和 A2 獨立的正常運行。假如此時客戶端請求 A1,請求將數(shù)據(jù) B 從 B1 狀態(tài)修改為 B2,由于網(wǎng)絡(luò)的不可用,數(shù)據(jù) B 的修改并不能通知到實例 A2。
如果此時另一個客戶端向 A2 請求數(shù)據(jù) B,如果 A2 返回數(shù)據(jù) B1,將滿足服務(wù)可用性,但并不能滿足數(shù)據(jù)一致性;如果A2 等待 A1 的通知后才返回數(shù)據(jù) B 的正確狀態(tài),雖然滿足了數(shù)據(jù)一致性,但并不能響應(yīng)客戶端請求,違背了服務(wù)可用性的指標。
在類似銀行之類對金額數(shù)據(jù)要求強一致性的系統(tǒng)中,要優(yōu)先考慮滿足數(shù)據(jù)一致性;而在大眾網(wǎng)頁之類的系統(tǒng)中,用戶對網(wǎng)頁版本的新舊不會有特別的要求,在這種場景下服務(wù)可用性會高于數(shù)據(jù)一致性。
6. 常用術(shù)語
7. 分布式原理
7.1 客戶端
當 RPC 服務(wù)部署在多個節(jié)點上時,客戶端得到的是一個服務(wù)列表,有多個 IP 端口對。客戶端的連接池可以隨機地挑選任意的 RPC 服務(wù)節(jié)點進行連接。
每個服務(wù)節(jié)點應(yīng)該有個權(quán)重值,當所有節(jié)點的權(quán)重值一樣時,它們的流量分配就是均勻的。如果某個節(jié)點的相對權(quán)重值較小,它被客戶端選中的概率也會相對比較小。
class RPCNode {String addr; // 服務(wù)地址int weight; // 節(jié)點權(quán)重
}class RPCCluster {RPCNode[] nodes; // 節(jié)點列表Node random(); // 按權(quán)重隨機挑選節(jié)點
}
7.2 容災(zāi)
當有一個服務(wù)節(jié)點掛掉時,客戶端需要采取一定的策略避免請求失敗。當請求失敗時,客戶端還要進行重試,但是也不可以無限重試,要有一定的重試策略。
比如當節(jié)點掛掉時,將失效節(jié)點摘除,放置到失效節(jié)點列表中。然后每隔一段時間檢查失效節(jié)點是否恢復(fù)了,如果恢復(fù)了,那就從失效節(jié)點中移除,再將節(jié)點地址重新加入到有效節(jié)點列表中。那如何判斷節(jié)點真的掛掉了呢,一般需要設(shè)置一個時間窗口,統(tǒng)計在一定時間窗口里出現(xiàn)的錯誤數(shù)量。如果這個數(shù)量過大,那就意味著失效了。這也是為了防止網(wǎng)絡(luò)偶然抖動導(dǎo)致服務(wù)節(jié)點流量的大幅波動。
7.3 降權(quán)法
上面提到客戶端會為每個節(jié)點賦予一個權(quán)值,改變權(quán)值就可以改變節(jié)點的相對流量。如果某個節(jié)點出現(xiàn)了一次調(diào)用錯誤,可以對該節(jié)點進行降權(quán)。如果錯誤次數(shù)過多,降權(quán)會降的很快,最終達到一個最小值。之所以不應(yīng)該降到零,那是為了給節(jié)點提供一個恢復(fù)的機會。被降權(quán)的節(jié)點后來只要有一次調(diào)用成功,那么 weight 值就應(yīng)該盡快被還原,這樣節(jié)點就可以快速恢復(fù)為正常節(jié)點。
客戶端一次調(diào)用失敗會嘗試重試。如果降權(quán)太慢,會導(dǎo)致重試次數(shù)太多,因為第二次隨機挑選節(jié)點時還是很有可能再次挑選到失效節(jié)點。降權(quán)太快也不好,網(wǎng)絡(luò)抖動會導(dǎo)致節(jié)點流量分配的快速抖動,瞬間從正常降到近零,又可以瞬間從近零恢復(fù)到正常。
一個簡單的策略是權(quán)重減半法。錯誤一次權(quán)重減半,連續(xù)錯誤兩次權(quán)重就降到 1/4,如此直到降到最小值。如果初始權(quán)重值是 1024,那么權(quán)重值就會逐漸衰減1024=>512=>256=>128=>64=>32=>16=>8=>4=>2=>1。如果節(jié)點恢復(fù)了,那么調(diào)用會成功,權(quán)重就可以直接恢復(fù)到正常值,也可以通過加倍法逐漸恢復(fù)到正常值1=>2=>4=>8=>16=>32=>64=>128=>256=>512=>1024。如果希望恢復(fù)的更快一點,可以通過乘 4 法,乘 8 法。
7.4 服務(wù)發(fā)現(xiàn)
健壯的服務(wù)應(yīng)該是可以支持動態(tài)擴容的服務(wù)。比如 RPC 服務(wù)壓力過大,希望通過增加節(jié)點的方式來減小單個 RPC 服務(wù)的壓力。如果使用的是前面的靜態(tài) RPC 服務(wù)地址列表,那么當節(jié)點增加時,我們需要修改客戶端的配置重啟才能生效。
通過服務(wù)發(fā)現(xiàn)技術(shù),當 RPC 服務(wù)節(jié)點增加或減少時,客戶端可以動態(tài)快速收到服務(wù)列表的變更信息,從而可以實時調(diào)整連接配置,這樣無需重啟就可以完成服務(wù)的擴容和縮容。
class ServiceDiscovery(object):def register_service(self, name, addr):passdef get_services(self, name):passdef on_services_changed(self, name):pass
服務(wù)發(fā)現(xiàn)技術(shù)依賴于服務(wù)之間的特殊中間節(jié)點。這個節(jié)點的作用就是接受服務(wù)的注冊,提供服務(wù)的查找,以及服務(wù)列表變更的實時通知功能。它一般使用支持高可用的分布式配置數(shù)據(jù)庫作為解決方案,如 zookeeper/etcd 等。
- 服務(wù)注冊——服務(wù)節(jié)點在啟動時將自己的服務(wù)地址注冊到中間節(jié)點
- 服務(wù)查找——客戶端啟動時去中間節(jié)點查詢服務(wù)地址列表
- 服務(wù)變更通知——客戶端在中間節(jié)點上訂閱依賴服務(wù)列表的變更事件。當依賴的服務(wù)列表變更時,中間節(jié)點負責(zé)將變更信息實時通知給客戶端。
總結(jié)
以上是生活随笔為你收集整理的etcd 笔记(01)— etcd 简介、特点、应用场景、常用术语、分布式 CAP 理论、分布式原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2022-2028年中国氟橡胶预混胶行业
- 下一篇: 2022-2028年中国金属薄膜行业市场