分布式系統需要依賴分布式一致性來協調工作。通常情況下,提供分布式一致性擔保信息的系統會接收到按順序投遞過來的消息,這樣就不會產生腦裂沖突(split-brain conflicts,譯者注:本來一個大腦的兩個半球是互相配合的,但是現在分裂變成了兩個獨立的大腦,并且都認為對方已死。此時,雙方都會去嘗試接管集群資源,這樣就可能會造成沖突,產生嚴重的后果)。這類系統的用途是顯而易見的。像chubby、ZooKeeper、etcd、consul這些項目,盡管它們的原理和協議各不相同,但它們都側重于為分布式一致性提供類似的基本鍵值原語。為了讓etcd成為分布式系統中具吸引力的項目,etcd團隊開發了一款新的代理服務器程序:zetcd,使用這款軟件,etcd集群無需修改即可處理ZooKeeper客戶端的請求。
ZooKeeper是這方面個流行起來的開源軟件,它是很多分布式系統的首選后端軟件。這些系統理論上也可以搭配etcd一起運行,但是由于歷史原因,實際上根本實現不了。etcd集群不支持ZooKeeper,因為etcd的數據模型和客戶端協議與ZooKeeper應用程序不兼容。ZooKeeper應用程序也不是原生的支持etcd;如果系統已經在穩定運行了,那么沒有必要去為了適應新的后端軟件而讓系統更加復雜。幸運的是,etcd的第三版API相當的牛逼,它可以通過一個普通的代理來模擬ZooKeeper客戶端的數據模型,這就是zetcd,一個由etcd團隊開發的新的開源項目。今天,zetcd發布了個測試版,v0.0.1版,這為在生產系統中管理和部署zetcd打下了基礎。
zetcd代理位于etcd集群的前端,它提供了一個模擬ZooKeeper客戶端的端口,讓原版的ZooKeeper應用程序可以運行在etcd上。其基本原理是,zetcd將ZooKeeper客戶端的請求轉換為適合于etcd數據模型和API要求的消息,將發送給etcd,然后將etcd的響應消息轉換后返回給客戶端。該代理的性能可以與ZooKeeper相媲美,利用etcd的特性和工具可以簡化ZooKeeper集群管理。下文將展示zetcd的使用方法和工作原理,并分享一些性能評測數據。
讓zetcd運行起來需要三樣東西:一個go編譯器、一個能夠獲取源代碼的互聯網連接,以及一個可以運行etcd的系統。下面的示例展示了如何用源代碼編譯生成zetcd,并對它運行ZooKeeper命令。當我們需要部署正式環境的時候,我們并不建議從開發分支來獲取源代碼并編譯etcd和zetcd,但是如果只是試用一下的話,這是簡單的方法。
首先,獲取源代碼并編譯etcd和zetcd的二進制文件:
go get github.com/coreos/etcd/cmd/etcd
go get github.com/coreos/zetcd/cmd/zetcd
接下來,運行etcd,并將zetcd連接到etcd的客戶端接入點:
# etcd uses localhost:2379 by default
etcd &
zetcd -zkaddr localhost:2181 -endpoints localhost:2379 &
試用zetcd,啟動查看并創建一個key:
go install github.com/coreos/zetcd/cmd/zkctl
zkctl watch / &
zkctl create /abc "foo"
這個例子展示了在一個獨立的etcd實例上部署了一個zetcd代理層:
那么這個zetcd代理層是做什么的呢?
在底層,zetcd將ZooKeeper的數據模型轉換為適合的etcd API的數據。對于key的查找,zetcd將ZooKeeper的分級目錄轉換為etcd的普通二進制keyspace。對于元數據的管理,zetcd利用事務內存安全地和原子地將ZooKeeper znode信息更新到etcd后端。
ZooKeeper是按目錄列出所有的key(getChildren),而etcd是按區間(Range)列出所有的key。下圖說明了zetcd是如何在etcd中對key進行編碼以便可以快速地列出目錄中的key。所有zetcd的key都有一個包括目錄深度的前綴(例如,“/”和“/abc/”分別具有0和1的深度)。要列出一個目錄,zetcd會給出前綴范圍,這個前綴以目錄的深度和路徑來匹配相應的key(例如,前綴范圍[“/zk/key/002/abc/”,“/zk/key/002/abc0”]用于列出/abc/)。這里的目錄深度是為了限制目錄本身被當作key。如果zetcd將路徑當作是沒有深度的前綴,那么目錄下的所有key,而不是只有其直接子節點,會由etcd返回并被代理拋棄。
每個ZooKeeper的key都在ZNode中攜帶了包含其修改記錄、版本、權限的元數據。雖然etcd也包含了每個key的元數據,但卻比ZNode中的簡單:沒有子版本,因為沒有目錄;沒有ACL,因為etcd使用基于角色的身份驗證方式;沒有時間戳,因為實時時鐘在etcd的作用范圍之外。這個額外的元數據映射到一組描述了完整的ZNode的key上(見上圖)。如果要調整元數據,zetcd會利用軟件事務內存原子地更新key的子集,這樣就能保持ZNodes的一致性,而不需要昂貴的加鎖解鎖開銷。
此外,zetcd可以對真實的ZooKeeper服務器動態驗證它的行為。作為比較,zetcd同時連接到etcd和外部ZooKeeper服務器。當客戶端在此模式下向zetcd發出請求時,請求會同時分發到zetcd和ZooKeeper服務器。如果兩個服務器的響應在語義上不一致,那么zetcd會通過交叉檢查警告對響應進行標記。
因為數據轉換和網絡上的損耗,很有可能就把zetcd的仿真當作是不切實際的做法。盡管單純的ZooKeeper或etcd集群都有一些額外的成本,但是當etcd已安裝并且可以使用,而一些應用程序只支持ZooKeeper調度的時候,zetcd的優勢就體現出來了。例如,早期的用戶報告聲稱,在zetcd中使用etcd的TLS加密流量比加密一個類似的經典的ZooKeeper配置來得更簡單。在這種情況下,相對于簡單地擁有一個可靠的使用ZooKeeper協議的集群來說,性能反而顯得不那么重要了。
使用zetcd的命令行工具zkboom進行評測可以用來判斷zetcd的性能是否達標。它的評測界面和報告與etcd的評測工具類似。其他的ZooKeeper評測工具也可以用于zetcd;為方便起見,zetcd提供了zkboom這個工具。我們來試一下運行zkboom來測試key的創建:
go get github.com/coreos/zetcd/cmd/zkboom
zkboom --conns=50 --total=10000 --endpoints=localhost:2181 create
zetcd可以為小型的工作負載提供足夠的性能。延遲評測表明,使用簡單的雙節點配置,zetcd的仿真可用于中等的請求速率。該配置包含兩臺通過千兆交換機連接的現代Linux機器,其中一臺機器使用機械磁盤RAID運行代理服務器軟件,另一臺機器用于生成客戶端請求。使用zkboom來測量在一開始為空的key存儲空間中創建和讀取128個字節的鍵值對的延遲,客戶端請求速率限制為每秒2500個請求,并逐步增加并發客戶端的數量。我們拿ZooKeeper 3.4.10版和etcd的開發分支作比較。
下圖展示了隨著并發客戶端數量的增加,zetcd的平均key創建延遲的變化情況。在本次評測中,由于etcd在延遲上相對于ZooKeeper有5ms到35ms左右的優勢,因此zetcd就有了一些可用于適應網絡損耗和數據處理的余量。zetcd代理比ZooKeeper遜色了大概20ms左右,但從吞吐量來看,并沒有產生積壓,因為它仍然保持了每秒2500個請求的速率。zetcd寫入速度慢的一種解釋是,它從etcd讀取key的同時,由于數據模型的差異,要為每個新的ZooKeeper的key同時往etcd寫入多個key。
下圖顯示了隨著并發客戶端數量的增加,平均key獲取延遲的變化情況。ZooKeeper的獲取延遲比etcd稍低,差距大約為2ms左右,所以zetcd需要進一步的優化才有可能比ZooKeeper更快。為了模擬ZooKeeper znode元數據,盡管需要從etcd獲取額外的key,但是zetcd延遲命中只比etcd獲取key增加了大約1.5ms左右。這是因為zetcd獲取key的操作只需要一次往返,所有的讀取請求都被加入到單個etcd事務中。
到目前為止,zetcd的前途是光明的。它的性能是合格的,可以輕松支撐每秒超過一千次的操作,并且延遲也是在可接受的范圍之內。它的仿真已經足夠接近ZooKeeper,可以替代Mesos,Kafka和Drill。但是在性能調優方面仍有一定的提升空間。同時,使用更多的ZooKeeper應用程序進行測試能夠加快zetcd對ZooKeeper服務器的替代。
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。