自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Etcd 架構(gòu)與實現(xiàn)解析

開發(fā) 開發(fā)工具
本文通過分析 Etcd 的架構(gòu)與實現(xiàn),了解其優(yōu)缺點以及瓶頸點,最后介紹 Etcd 周邊的工具和一些使用注意事項。

前一段時間的項目里用到了 Etcd, 所以研究了一下它的源碼以及實現(xiàn)。網(wǎng)上關(guān)于 Etcd 的使用介紹的文章不少,但分析具體架構(gòu)實現(xiàn)的文章不多,同時 Etcd v3的文檔也非常稀缺。本文通過分析 Etcd 的架構(gòu)與實現(xiàn),了解其優(yōu)缺點以及瓶頸點,一方面可以學(xué)習(xí)分布式系統(tǒng)的架構(gòu),另外一方面也可以保證在業(yè)務(wù)中正確使用 Etcd,知其然同時知其所以然,避免誤用。***介紹 Etcd 周邊的工具和一些使用注意事項。

架構(gòu)

閱讀對象:分布式系統(tǒng)愛好者,正在或者打算在項目中使用Etcd的開發(fā)人員。

Etcd 按照官方介紹

Etcd is a distributed, consistent key-value store for shared configuration and service discovery

是一個分布式的,一致的 key-value 存儲,主要用途是共享配置和服務(wù)發(fā)現(xiàn)。Etcd 已經(jīng)在很多分布式系統(tǒng)中得到廣泛的使用,本文的架構(gòu)與實現(xiàn)部分主要解答以下問題:

  1. Etcd是如何實現(xiàn)一致性的?
  2. Etcd的存儲是如何實現(xiàn)的?
  3. Etcd的watch機制是如何實現(xiàn)的?
  4. Etcd的key過期機制是如何實現(xiàn)的?

一、為什么需要 Etcd ?

所有的分布式系統(tǒng),都面臨的一個問題是多個節(jié)點之間的數(shù)據(jù)共享問題,這個和團隊協(xié)作的道理是一樣的,成員可以分頭干活,但總是需要共享一些必須的信息,比如誰是 leader, 都有哪些成員,依賴任務(wù)之間的順序協(xié)調(diào)等。所以分布式系統(tǒng)要么自己實現(xiàn)一個可靠的共享存儲來同步信息(比如 Elasticsearch ),要么依賴一個可靠的共享存儲服務(wù),而 Etcd 就是這樣一個服務(wù)。

二、Etcd 提供什么能力?

Etcd 主要提供以下能力,已經(jīng)熟悉 Etcd 的讀者可以略過本段。

  1. 提供存儲以及獲取數(shù)據(jù)的接口,它通過協(xié)議保證 Etcd 集群中的多個節(jié)點數(shù)據(jù)的強一致性。用于存儲元信息以及共享配置。
  2. 提供監(jiān)聽機制,客戶端可以監(jiān)聽某個key或者某些key的變更(v2和v3的機制不同,參看后面文章)。用于監(jiān)聽和推送變更。
  3. 提供key的過期以及續(xù)約機制,客戶端通過定時刷新來實現(xiàn)續(xù)約(v2和v3的實現(xiàn)機制也不一樣)。用于集群監(jiān)控以及服務(wù)注冊發(fā)現(xiàn)。
  4. 提供原子的CAS(Compare-and-Swap)和 CAD(Compare-and-Delete)支持(v2通過接口參數(shù)實現(xiàn),v3通過批量事務(wù)實現(xiàn))。用于分布式鎖以及l(fā)eader選舉。

更詳細的使用場景不在這里描述,有興趣的可以參看文末infoq的一篇文章。

三、Etcd 如何實現(xiàn)一致性的?

說到這個就不得不說起raft協(xié)議。但這篇文章不是專門分析raft的,篇幅所限,不能詳細分析,有興趣的建議看文末原始論文地址以及raft協(xié)議的一個動畫。便于看后面的文章,我這里簡單做個總結(jié):

  1. raft通過對不同的場景(選主,日志復(fù)制)設(shè)計不同的機制,雖然降低了通用性(相對paxos),但同時也降低了復(fù)雜度,便于理解和實現(xiàn)。
  2. raft內(nèi)置的選主協(xié)議是給自己用的,用于選出主節(jié)點,理解raft的選主機制的關(guān)鍵在于理解raft的時鐘周期以及超時機制。
  3. 理解 Etcd 的數(shù)據(jù)同步的關(guān)鍵在于理解raft的日志同步機制。

Etcd 實現(xiàn)raft的時候,充分利用了go語言CSP并發(fā)模型和chan的魔法,想更進行一步了解的可以去看源碼,這里只簡單分析下它的wal日志。

Etcd 實現(xiàn)raft

wal日志是二進制的,解析出來后是以上數(shù)據(jù)結(jié)構(gòu)LogEntry。其中***個字段type,只有兩種,一種是0表示Normal,1表示ConfChange(ConfChange表示 Etcd 本身的配置變更同步,比如有新的節(jié)點加入等)。第二個字段是term,每個term代表一個主節(jié)點的任期,每次主節(jié)點變更term就會變化。第三個字段是index,這個序號是嚴(yán)格有序遞增的,代表變更序號。第四個字段是二進制的data,將raft request對象的pb結(jié)構(gòu)整個保存下。Etcd 源碼下有個tools/etcd-dump-logs,可以將wal日志dump成文本查看,可以協(xié)助分析raft協(xié)議。

raft協(xié)議本身不關(guān)心應(yīng)用數(shù)據(jù),也就是data中的部分,一致性都通過同步wal日志來實現(xiàn),每個節(jié)點將從主節(jié)點收到的data apply到本地的存儲,raft只關(guān)心日志的同步狀態(tài),如果本地存儲實現(xiàn)的有bug,比如沒有正確的將data apply到本地,也可能會導(dǎo)致數(shù)據(jù)不一致。

四、Etcd v2 與 v3

Etcd v2 和 v3 本質(zhì)上是共享同一套 raft 協(xié)議代碼的兩個獨立的應(yīng)用,接口不一樣,存儲不一樣,數(shù)據(jù)互相隔離。也就是說如果從 Etcd v2 升級到 Etcd v3,原來v2 的數(shù)據(jù)還是只能用 v2 的接口訪問,v3 的接口創(chuàng)建的數(shù)據(jù)也只能訪問通過 v3 的接口訪問。所以我們按照 v2 和 v3 分別分析。

五、Etcd v2 Watch,以及過期機制

以下數(shù)據(jù)存儲到 Etcd 中的結(jié)構(gòu)就如圖所示

Etcd v2 是個純內(nèi)存的實現(xiàn),并未實時將數(shù)據(jù)寫入到磁盤,持久化機制很簡單,就是將store整合序列化成json寫入文件。數(shù)據(jù)在內(nèi)存中是一個簡單的樹結(jié)構(gòu)。比如以下數(shù)據(jù)存儲到 Etcd 中的結(jié)構(gòu)就如圖所示。

  1. /nodes/1/name  node1   
  2. /nodes/1/ip    192.168.1.1  

store中有一個全局的currentIndex,每次變更,index會加1.然后每個event都會關(guān)聯(lián)到currentIndex.

當(dāng)客戶端調(diào)用watch接口(參數(shù)中增加 wait參數(shù))時,如果請求參數(shù)中有waitIndex,并且waitIndex 小于 currentIndex,則從 EventHistroy 表中查詢index小于等于waitIndex,并且和watch key 匹配的 event,如果有數(shù)據(jù),則直接返回。如果歷史表中沒有或者請求沒有帶 waitIndex,則放入WatchHub中,每個key會關(guān)聯(lián)一個watcher列表。 當(dāng)有變更操作時,變更生成的event會放入EventHistroy表中,同時通知和該key相關(guān)的watcher。

這里有幾個影響使用的細節(jié)問題:

  1. EventHistroy 是有長度限制的,最長1000。也就是說,如果你的客戶端停了許久,然后重新watch的時候,可能和該waitIndex相關(guān)的event已經(jīng)被淘汰了,這種情況下會丟失變更。
  2. 如果通知watch的時候,出現(xiàn)了阻塞(每個watch的channel有100個緩沖空間),Etcd 會直接把watcher刪除,也就是會導(dǎo)致wait請求的連接中斷,客戶端需要重新連接。
  3. Etcd store的每個node中都保存了過期時間,通過定時機制進行清理。

從而可以看出,Etcd v2 的一些限制:

  1. 過期時間只能設(shè)置到每個key上,如果多個key要保證生命周期一致則比較困難。
  2. watch只能watch某一個key以及其子節(jié)點(通過參數(shù) recursive),不能進行多個watch。
  3. 很難通過watch機制來實現(xiàn)完整的數(shù)據(jù)同步(有丟失變更的風(fēng)險),所以當(dāng)前的大多數(shù)使用方式是通過watch得知變更,然后通過get重新獲取數(shù)據(jù),并不完全依賴于watch的變更event。

六、Etcd v3 存儲,Watch,以及過期機制

Etcd v3 存儲,Watch,以及過期機制

Etcd v3 將watch和store拆開實現(xiàn),我們先分析下store的實現(xiàn)。

Etcd v3 store 分為兩部分,一部分是內(nèi)存中的索引,kvindex,是基于google開源的一個golang的btree實現(xiàn)的,另外一部分是后端存儲。按照它的設(shè)計,backend可以對接多種存儲,當(dāng)前使用的boltdb。boltdb是一個單機的支持事務(wù)的kv存儲,Etcd 的事務(wù)是基于boltdb的事務(wù)實現(xiàn)的。Etcd 在boltdb中存儲的key是reversion,value是 Etcd 自己的key-value組合,也就是說 Etcd 會在boltdb中把每個版本都保存下,從而實現(xiàn)了多版本機制。

舉個例子: 用etcdctl通過批量接口寫入兩條記錄:

  1. etcdctl txn <<<'  
  2. put key1 "v1"  
  3. put key2 "v2"  
  4.  
  5. '  

再通過批量接口更新這兩條記錄:

  1. etcdctl txn <<<'  
  2. put key1 "v12"  
  3. put key2 "v22"  
  4.  
  5. '  

boltdb中其實有了4條數(shù)據(jù):

  1. rev={3 0}, key=key1value="v1"  
  2. rev={3 1}, key=key2value="v2"  
  3. rev={4 0}, key=key1value="v12"  
  4. rev={4 1}, key=key2value="v22"  

reversion主要由兩部分組成,***部分main rev,每次事務(wù)進行加一,第二部分sub rev,同一個事務(wù)中的每次操作加一。如上示例,***次操作的main rev是3,第二次是4。當(dāng)然這種機制大家想到的***個問題就是空間問題,所以 Etcd 提供了命令和設(shè)置選項來控制compact,同時支持put操作的參數(shù)來精確控制某個key的歷史版本數(shù)。

了解了 Etcd 的磁盤存儲,可以看出如果要從boltdb中查詢數(shù)據(jù),必須通過reversion,但客戶端都是通過key來查詢value,所以 Etcd 的內(nèi)存kvindex保存的就是key和reversion之前的映射關(guān)系,用來加速查詢。

然后我們再分析下watch機制的實現(xiàn)。Etcd v3 的watch機制支持watch某個固定的key,也支持watch一個范圍(可以用于模擬目錄的結(jié)構(gòu)的watch),所以 watchGroup 包含兩種watcher,一種是 key watchers,數(shù)據(jù)結(jié)構(gòu)是每個key對應(yīng)一組watcher,另外一種是 range watchers, 數(shù)據(jù)結(jié)構(gòu)是一個 IntervalTree(不熟悉的參看文文末鏈接),方便通過區(qū)間查找到對應(yīng)的watcher。

同時,每個 WatchableStore 包含兩種 watcherGroup,一種是synced,一種是unsynced,前者表示該group的watcher數(shù)據(jù)都已經(jīng)同步完畢,在等待新的變更,后者表示該group的watcher數(shù)據(jù)同步落后于當(dāng)前***變更,還在追趕。

當(dāng) Etcd 收到客戶端的watch請求,如果請求攜帶了revision參數(shù),則比較請求的revision和store當(dāng)前的revision,如果大于當(dāng)前revision,則放入synced組中,否則放入unsynced組。同時 Etcd 會啟動一個后臺的goroutine持續(xù)同步unsynced的watcher,然后將其遷移到synced組。也就是這種機制下,Etcd v3 支持從任意版本開始watch,沒有v2的1000條歷史event表限制的問題(當(dāng)然這是指沒有compact的情況下)。

另外我們前面提到的,Etcd v2在通知客戶端時,如果網(wǎng)絡(luò)不好或者客戶端讀取比較慢,發(fā)生了阻塞,則會直接關(guān)閉當(dāng)前連接,客戶端需要重新發(fā)起請求。Etcd v3為了解決這個問題,專門維護了一個推送時阻塞的watcher隊列,在另外的goroutine里進行重試。

Etcd v3 對過期機制也做了改進,過期時間設(shè)置在lease上,然后key和lease關(guān)聯(lián)。這樣可以實現(xiàn)多個key關(guān)聯(lián)同一個lease id,方便設(shè)置統(tǒng)一的過期時間,以及實現(xiàn)批量續(xù)約。

相比Etcd v2, Etcd v3的一些主要變化:

  1. 接口通過grpc提供rpc接口,放棄了v2的http接口。優(yōu)勢是長連接效率提升明顯,缺點是使用不如以前方便,尤其對不方便維護長連接的場景。
  2. 廢棄了原來的目錄結(jié)構(gòu),變成了純粹的kv,用戶可以通過前綴匹配模式模擬目錄。
  3. 內(nèi)存中不再保存value,同樣的內(nèi)存可以支持存儲更多的key。
  4. watch機制更穩(wěn)定,基本上可以通過watch機制實現(xiàn)數(shù)據(jù)的完全同步。
  5. 提供了批量操作以及事務(wù)機制,用戶可以通過批量事務(wù)請求來實現(xiàn)Etcd v2的CAS機制(批量事務(wù)支持if條件判斷)。

七、Etcd,Zookeeper,Consul 比較

這三個產(chǎn)品是經(jīng)常被人拿來做選型比較的。 Etcd 和 Zookeeper 提供的能力非常相似,都是通用的一致性元信息存儲,都提供watch機制用于變更通知和分發(fā),也都被分布式系統(tǒng)用來作為共享信息存儲,在軟件生態(tài)中所處的位置也幾乎是一樣的,可以互相替代的。二者除了實現(xiàn)細節(jié),語言,一致性協(xié)議上的區(qū)別,***的區(qū)別在周邊生態(tài)圈。Zookeeper 是apache下的,用java寫的,提供rpc接口,最早從hadoop項目中孵化出來,在分布式系統(tǒng)中得到廣泛使用(hadoop, solr, kafka, mesos 等)。Etcd 是coreos公司旗下的開源產(chǎn)品,比較新,以其簡單好用的rest接口以及活躍的社區(qū)俘獲了一批用戶,在新的一些集群中得到使用(比如kubernetes)。雖然v3為了性能也改成二進制rpc接口了,但其易用性上比 Zookeeper 還是好一些。 而 Consul 的目標(biāo)則更為具體一些,Etcd 和 Zookeeper 提供的是分布式一致性存儲能力,具體的業(yè)務(wù)場景需要用戶自己實現(xiàn),比如服務(wù)發(fā)現(xiàn),比如配置變更。而Consul 則以服務(wù)發(fā)現(xiàn)和配置變更為主要目標(biāo),同時附帶了kv存儲。 在軟件生態(tài)中,越抽象的組件適用范圍越廣,但同時對具體業(yè)務(wù)場景需求的滿足上肯定有不足之處。

八、Etcd 的周邊工具

1. Confd

在分布式系統(tǒng)中,理想情況下是應(yīng)用程序直接和 Etcd 這樣的服務(wù)發(fā)現(xiàn)/配置中心交互,通過監(jiān)聽 Etcd 進行服務(wù)發(fā)現(xiàn)以及配置變更。但我們還有許多歷史遺留的程序,服務(wù)發(fā)現(xiàn)以及配置大多都是通過變更配置文件進行的。Etcd 自己的定位是通用的kv存儲,所以并沒有像 Consul 那樣提供實現(xiàn)配置變更的機制和工具,而 Confd 就是用來實現(xiàn)這個目標(biāo)的工具。

Confd 通過watch機制監(jiān)聽 Etcd 的變更,然后將數(shù)據(jù)同步到自己的一個本地存儲。用戶可以通過配置定義自己關(guān)注那些key的變更,同時提供一個配置文件模板。Confd 一旦發(fā)現(xiàn)數(shù)據(jù)變更就使用***數(shù)據(jù)渲染模板生成配置文件,如果新舊配置文件有變化,則進行替換,同時觸發(fā)用戶提供的reload腳本,讓應(yīng)用程序重新加載配置。

Confd 相當(dāng)于實現(xiàn)了部分 Consul 的agent以及consul-template的功能,作者是kubernetes的Kelsey Hightower,但大神貌似很忙,沒太多時間關(guān)注這個項目了,很久沒有發(fā)布版本,我們著急用,所以fork了一份自己更新維護,主要增加了一些新的模板函數(shù)以及對metad后端的支持。

2. Metad

服務(wù)注冊的實現(xiàn)模式一般分為兩種,一種是調(diào)度系統(tǒng)代為注冊,一種是應(yīng)用程序自己注冊。調(diào)度系統(tǒng)代為注冊的情況下,應(yīng)用程序啟動后需要有一種機制讓應(yīng)用程序知道『我是誰』,然后發(fā)現(xiàn)自己所在的集群以及自己的配置。Metad 提供這樣一種機制,客戶端請求 Metad 的一個固定的接口 /self,由 Metad 告知應(yīng)用程序其所屬的元信息,簡化了客戶端的服務(wù)發(fā)現(xiàn)和配置變更邏輯。

Metad 通過保存一個ip到元信息路徑的映射關(guān)系來做到這一點,當(dāng)前后端支持Etcd v3,提供簡單好用的 http rest 接口。 它會把 Etcd 的數(shù)據(jù)通過watch機制同步到本地內(nèi)存中,相當(dāng)于 Etcd 的一個代理。所以也可以把它當(dāng)做Etcd 的代理來使用,適用于不方便使用 Etcd v3的rpc接口或者想降低 Etcd 壓力的場景。

3. Etcd 集群一鍵搭建腳本

Etcd 官方那個一鍵搭建腳本有bug,我自己整理了一個腳本,通過docker的network功能,一鍵搭建一個本地的 Etcd 集群便于測試和試驗。一鍵搭建腳本

九、Etcd 使用注意事項

1. Etcd cluster 初始化的問題

如果集群***次初始化啟動的時候,有一臺節(jié)點未啟動,通過v3的接口訪問的時候,會報告Error: Etcdserver: not capable 錯誤。這是為兼容性考慮,集群啟動時默認(rèn)的API版本是2.3,只有當(dāng)集群中的所有節(jié)點都加入了,確認(rèn)所有節(jié)點都支持v3接口時,才提升集群版本到v3。這個只有***次初始化集群的時候會遇到,如果集群已經(jīng)初始化完畢,再掛掉節(jié)點,或者集群關(guān)閉重啟(關(guān)閉重啟的時候會從持久化數(shù)據(jù)中加載集群API版本),都不會有影響。

2. Etcd 讀請求的機制

v2 quorum=true 的時候,讀取是通過raft進行的,通過cli請求,該參數(shù)默認(rèn)為true。 v3 –consistency=“l” 的時候(默認(rèn))通過raft讀取,否則讀取本地數(shù)據(jù)。sdk 代碼里則是通過是否打開:WithSerializable option 來控制。

一致性讀取的情況下,每次讀取也需要走一次raft協(xié)議,能保證一致性,但性能有損失,如果出現(xiàn)網(wǎng)絡(luò)分區(qū),集群的少數(shù)節(jié)點是不能提供一致性讀取的。但如果不設(shè)置該參數(shù),則是直接從本地的store里讀取,這樣就損失了一致性。使用的時候需要注意根據(jù)應(yīng)用場景設(shè)置這個參數(shù),在一致性和可用性之間進行取舍。

3. Etcd 的compact機制

Etcd 默認(rèn)不會自動compact,需要設(shè)置啟動參數(shù),或者通過命令進行compcat,如果變更頻繁建議設(shè)置,否則會導(dǎo)致空間和內(nèi)存的浪費。

十、腦洞時間

自動上次 Elasticsearch 的文章之后,給自己安排了一個作業(yè),每次分析源碼后需要提出幾個發(fā)散思維的想法,開個腦洞。

1. 并發(fā)代碼調(diào)用分析追蹤工具

當(dāng)前IDE的代碼調(diào)用分析追蹤都是通過靜態(tài)的代碼分析來追蹤方法調(diào)用鏈實現(xiàn)的,對閱讀分析代碼非常有用。但程序如果充分使用CSP或者Actor模型后,都通過消息進行調(diào)用,沒有了明確的方法調(diào)用鏈,給閱讀和理解代碼帶來了困難。如果語言或者IDE能支持這樣的消息投遞追蹤分析,那應(yīng)該非常有用。當(dāng)然我這個只是腦洞,不考慮實現(xiàn)的可能性和復(fù)雜度。

2. 實現(xiàn)一個通用的 multiple group raft庫

當(dāng)前 Etcd 的raft實現(xiàn)保證了多個節(jié)點數(shù)據(jù)之間的同步,但明顯的一個問題就是擴充節(jié)點不能解決容量問題。要想解決容量問題,只能進行分片,但分片后如何使用raft同步數(shù)據(jù)?只能實現(xiàn)一個 multiple group raft,每個分片的多個副本組成一個虛擬的raft group,通過raft實現(xiàn)數(shù)據(jù)同步。當(dāng)前實現(xiàn)了multiple group raft的有 TiKV 和 Cockroachdb,但尚未一個獨立通用的。理論上來說,如果有了這套 multiple group raft,后面掛個持久化的kv就是一個分布式kv存儲,掛個內(nèi)存kv就是分布式緩存,掛個lucene就是分布式搜索引擎。當(dāng)然這只是理論上,要真實現(xiàn)復(fù)雜度還是不小。

十一、Etcd 的開源產(chǎn)品啟示

Etcd在Zookeeper已經(jīng)奠定江湖地位的情況下,硬是重新造了一個輪子,并且在生態(tài)圈中取得了一席之地。一方面可以看出是社區(qū)的形態(tài)在變化,溝通機制和對用戶反饋的響應(yīng)越來越重要,另外一方面也可以看出一個項目的易用的重要性有時候甚至高于穩(wěn)定性和功能。新的算法,新的語言都會給重新制造輪子帶來了機會。

十二、gitchat交流群的問答

1. 問:業(yè)務(wù)使用的etcd v2 升級到 v3 會有什么問題呢,如何平滑過渡?


答:v2的大多數(shù)功能,用v3都能實現(xiàn),比如用prefix模擬原來的目錄結(jié)構(gòu),用txn模擬CAS,一般不會有什么問題。但因為v2和v3的數(shù)據(jù)是互相隔離的,所以遷移起來略麻煩。建議先在業(yè)務(wù)中封裝一層,將etcd v2,v3的差異封裝起來,然后通過開關(guān)切換。

2. 問:metad的watch是怎么實現(xiàn)的?

答:metad的watch實現(xiàn)的比較簡單,因為metad的watch返回的不是變更事件,而是***的結(jié)果。所以metad只維護了一個全局版本號,只要發(fā)現(xiàn)客戶端watch的版本小于等于全局版本號,就直接返回***結(jié)果。

3. 問:etcd和zk都是作為分布式配置管理的組件。均提供了watch功能,選主。作為初使用者,這兩個之間的選取該如何?

etcd和zk二者大多數(shù)情況下可以互相替代,都是通用的分布式一致性kv存儲。二者之間選擇建議選擇自己的開發(fā)棧比較接近并且團隊成員比較熟悉的,比如一種是按語言選擇,go語言的項目用etcd,java的用zk,出問題要看源碼也容易些。如果是新項目,糾結(jié)于二者,那可以分裝一層lib,類似于docker/libkv,同時支持兩種,有需要可以切換。

4. 問:etcd和eureka、consul 的異同,以及各自的適用場景,以及選型原則。這個問題其實可以把zk也包括進來,這些都有相同之處。

答:etcd和zk的選型前面講到了,二者的定位都是通用的一致性kv存儲,而eureka和consul的定位則是專做服務(wù)注冊和發(fā)現(xiàn)。前二者的優(yōu)勢當(dāng)然是通用性,應(yīng)用廣泛,部署運維的時候容易和已有的服務(wù)一起共用,而同時缺點也是太通用了,每個應(yīng)用的服務(wù)注冊都有自己的一套元數(shù)據(jù)格式,互相整合起來就比較麻煩了,比如想做個通用的api gateway就會遇到元數(shù)據(jù)格式兼容問題。這也成為后二者的優(yōu)勢。同時因為后二者的目標(biāo)比較具體,所以可以做一些更高級的功能,比如consul的DNS支持,consul-template工具,eureka的事件訂閱過濾機制。Eureka本身的實現(xiàn)是一個AP系統(tǒng),也就是說犧牲了一致性,它認(rèn)為在服務(wù)發(fā)現(xiàn)和配置中心這個場景下,可用性和分區(qū)容錯比一致性更重要。 我個人其實更期待后二者的這種專門的解決方案,要是能形成服務(wù)注冊標(biāo)準(zhǔn),那以后應(yīng)用之間互相交互就容易了。但也有個可能是這種標(biāo)準(zhǔn)由集群調(diào)度系統(tǒng)來形成事實標(biāo)準(zhǔn)。

后二者我了解的也不深入,感覺可以另起一篇文章了。

5. 問:接上面,etcd和zk各自都有哪些坑可能會被踩到,都有多坑。掉進去了如何爬起來?

答:這個坑的概念比較太廣泛了,更詳細的可以翻bug列表。但使用中的大多數(shù)坑一般有幾種:

誤用導(dǎo)致的坑。要先認(rèn)識清楚etcd,zk的定位,它需要保存的是整個集群共享的信息,不能當(dāng)存儲用。比如有人在某個zk的某個數(shù)據(jù)節(jié)點下創(chuàng)建了大量的子節(jié)點,然后獲取,導(dǎo)致zk報錯,zk的buffer有個4mb的限制,超過就會報錯。

運維方面的坑。etcd,zk這種服務(wù),一般都比較穩(wěn)定,搭建好后都不用管,但萬一某些節(jié)點出問題了,要增加節(jié)點恢復(fù)系統(tǒng)的時候,可能沒有預(yù)案或者操作經(jīng)驗,導(dǎo)致弄壞集群。

網(wǎng)絡(luò)分區(qū)以及可用性設(shè)計的坑。設(shè)計系統(tǒng)的時候,要想清楚如果etcd或zk整個掛了,或者出現(xiàn)網(wǎng)絡(luò)分區(qū),應(yīng)用的一部分節(jié)點只能連接到少數(shù)派的etcd/zk(少數(shù)派不可用)的時候,應(yīng)用會有什么表現(xiàn)。這種情況下,應(yīng)用的正確表現(xiàn)應(yīng)該是服務(wù)正常運作,但不支持變更,等etcd/zk集群恢復(fù)后就自動恢復(fù)了。但如果設(shè)計不當(dāng),有自動化的一些行為,可能帶來的故障就大了。

想要少踩坑,一個辦法就是我文中提到的,研究原理知其然同時知其所以然,另外一個問題就是多試驗,出了問題有預(yù)案。

6. 問:一個實驗性質(zhì)的硬件集群項目的幾個問題

我們實現(xiàn)了基于Arm的分布式互聯(lián)的硬件集群(方法參考的是https://edcashin.wordpress.com/2013/12/29/trying-etcd-on-android-mac-and-raspberry-pi/comment-page-1/ 將etcd跑在Arm開發(fā)板上),將Etcd當(dāng)作一個分布式的數(shù)據(jù)庫使用(但是Etcd本身運行在這些硬件之上),然后參考go-rpiohttps://github.com/stianeikeland/go-rpio 實現(xiàn)基于etcd的key-value同步硬件的信息,控制某些GPIO。

問題1:目前已知Etcd可以為別的服務(wù)提供服務(wù)發(fā)現(xiàn),在這個場景下假設(shè)已經(jīng)存在5個運行Etcd節(jié)點的硬件,當(dāng)一個新的Etcd硬件節(jié)點被安裝時,Etcd能否為自己提供服務(wù)發(fā)現(xiàn)服務(wù),實現(xiàn)Etcd節(jié)點的自動發(fā)現(xiàn)與加入?

問題2:隨著硬件安裝規(guī)模的增加,Etcd的極限是多少,raft是否會因為節(jié)點的變多,心跳包的往返而導(dǎo)致同步一次的等待時間變長?

問題3:當(dāng)規(guī)模足夠大,發(fā)生網(wǎng)絡(luò)分區(qū)時,是否分區(qū)較小的一批硬件之間的數(shù)據(jù)是無法完成同步的?

答:這個案例挺有意思,我一個一個回答。

etcd本來是做服務(wù)發(fā)現(xiàn)的,如果etcd集群也需要服務(wù)發(fā)現(xiàn),那就再來一個etcd集群 :)。你可以自己搭建一個etcd cluster或者用etcd官方提供的 discovery.etcd.io。詳細參看:etcd 官方的 op-guide/clustering

etcd的機制是多節(jié)點一致的,所以它的極限有兩部分,一是單機的容量限制,內(nèi)存和磁盤。二是網(wǎng)絡(luò)開銷,每次raft操作需要所有節(jié)點參與,節(jié)點越多性能越低。所以擴展很多etcd節(jié)點是沒有意義的,一般是 3,5,7,9。再多感覺就沒意義了。如果你們不太在意一致性,建議讀請求可以不通過一致性協(xié)議,直接讀取節(jié)點本地數(shù)據(jù)。具體方式文中有說明。

etcd網(wǎng)絡(luò)分區(qū)時,少數(shù)派是不可用狀態(tài),不支持raft請求,但支持非一致性讀請求。

7. 問:如果跨機房部署服務(wù),是部署兩套ETCD嗎?如果跨機房部署,如何部署及配置?

答:這個要看跨機房的場景。如果是完全無關(guān)聯(lián)需要公網(wǎng)連接的兩個機房,服務(wù)之間一般也不需要共享數(shù)據(jù)吧?部署兩套互不相干的etcd,各用各的比較合適。但如果是類似于aws的可用區(qū)的概念,兩個機房內(nèi)網(wǎng)互通,搭建兩套集群為了避免機房故障,可以隨時切換。這個etcd當(dāng)前沒有太好的解決辦法,建議的辦法是跨可用區(qū)部署一個etcd cluster,調(diào)整心跳以及選舉超時時間,這個辦法如果有3個可用區(qū)機房,每個機房3個節(jié)點,掛任何一個機房都不影響整個集群,但兩個機房就比較尷尬。還有個辦法是兩個集群之間同步,這個etcdv3提供了一個mirror的工具,但還是不太完善,不過感覺用etcd的watch機制做一個同步工具也不難。這個機制consul倒是提供了,多數(shù)據(jù)中心的集群數(shù)據(jù)同步,互相不影響可用性。

【本文是51CTO專欄作者“王淵命”的原創(chuàng)文章,轉(zhuǎn)載請聯(lián)系作者本人獲取授權(quán)】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2020-05-19 21:40:35

Tomcat架構(gòu)Connector

2013-04-07 17:57:16

SDN網(wǎng)絡(luò)架構(gòu)

2024-08-15 08:03:52

2025-03-27 04:10:00

2019-01-16 16:46:49

Go存儲etcd

2019-12-16 15:39:48

Etcd存儲Go

2023-08-21 08:31:40

LinuxNFSD架構(gòu)

2024-09-29 08:00:00

動態(tài)代理RPC架構(gòu)微服務(wù)架構(gòu)

2017-01-13 10:51:13

RPC模型解析

2023-12-22 13:58:00

C++鏈表開發(fā)

2009-03-03 09:13:36

工作流BPM業(yè)務(wù)流程

2021-07-01 11:56:04

etcd-wal模塊解析數(shù)據(jù)庫

2018-11-09 10:09:38

RAC硬件軟件

2023-11-26 13:36:20

協(xié)議Raft

2023-07-06 12:39:14

RedisLRULFU

2011-06-13 16:20:25

網(wǎng)站信息架構(gòu)收錄流量

2023-08-08 09:52:13

系統(tǒng)端架構(gòu)NFS

2017-07-07 14:30:27

Flink架構(gòu)拓撲

2022-03-25 10:48:40

NBF架構(gòu)設(shè)計

2019-09-09 09:53:52

K8s集群架構(gòu)
點贊
收藏

51CTO技術(shù)棧公眾號