在過去的幾個月中,CoreOS致力于完善etcd3 API的beta版,經過對系統的嚴格測試并且在一些用戶的共同協作下,etcd得到了長足的進步。今天etcd v3.0.0,這個由CoreOS開發的分布式鍵值對存儲引擎,正式發布了。
在工程實踐中,etcd3已經被集成到大型分布式系統Kubernetes之中。并且我們已經實現了分布式協作原語,包括:分布式鎖、選舉和軟件事務內存(software transactional memory),以保證etcd3的API對廣大的應用是足夠靈活的。現在我們可以很驕傲地宣布etcd3已經準備好推廣給大眾了。
“etcd的3.0版本在效率、可靠性和可擴展性等方面都獲得長足的進步。它將幫助Kubernetes管理超過數萬臺機器,甚至更多”,Google產品經理,David Aronchick這樣說:“Google容器引擎(GKE)團隊非常感謝CoreOS團隊能對Kubernetes項目作出持續的貢獻。對于云原生社區來說,這使Kubernetes成為一個產品級的容器管理系統”
etcd 3.0是etcd3 API和其數據模型的第一個穩定版本。升級是非常容易的,因為etcd2的JSON外部協議和集群內部協議在etcd3中同樣支持。但是,etcd3是通過搜集了etcd2用戶的反饋和實際擴展etcd2的經驗基礎上全新設計了API的產品。這篇文章將會點明etcd3在效率,可靠性和并發控制上改進的閃光點。
“見證了etcd在技術和社區的持續進步并成長為Kubernetes項目的一部分是非常讓人激動的。etcd3的正式發布將會使這樣的勢頭得以持續,我們期待將來有更多的功能和特性被引入到Red Hat OpenShift容器應用平臺產品中,”Red Hat首席軟件工程師Timothy St. Clair如是說。
從etcd2到etcd3etcd最早是被設計用來解決CoreOS升級時機器的協調問題的。現在它被用于分布式網絡、服務發現、配置管理、任務調度和負載均衡等服務中。原始設計的部分內容被證明是成功的:etcd已經成長為鍵值對存儲引擎,包括JSON外部協議,持續鍵值更新觀察者和有生存時間的鍵等特性。不幸的是,其他的一些功能被頻繁吐槽,包括客戶端空閑時會把仲裁的壓力釋放到集群中,對于老的鍵存在不可預測的垃圾回收。雖然etcd2可以滿足協調機器的任務,但當今微服務的趨勢使得etcd需要具備數以萬計的客戶端去操作數百萬鍵的能力。
etcd3吸取了etcd2的教訓。基礎服務接口使用gRPC代替了JSON以增加效率。JSON外部協議可以通過gRPC gateway得到支持。有生命周期的鍵的實現被替換為輕型流式租約存活(streaming lease keepalive)模型。觀察者也被重新設計,使用流式多路復用事件替代老式的事件模型。v3的數據模型去除了顯示鍵繼承和不穩定的觀察窗口,取而代之的是扁平二進制鍵空間,并使用多版本并發控制的事務語義。
“etcd在我們的Elastic Services Infrastructure(ESI)中作為生產級中心配置管理存儲器而使用,”NTT創新研究院的首席架構師Ichiro Fukuda這樣介紹道:“我們對etcd v3的發布是非常興奮的,并希望通過擴大使用它來增強我們的服務。”
我們邀請您加入我們一起慶祝etcd在性能和擴展性的長足進步使etcd的生產級v3版本成為云原生,分布式系統的基石。像華為、NTT和PingCAP這樣的公司在它們的產品和項目中是非常依賴這個快速的鍵值對存儲引擎的。
“祝賀CoreOS發布了etcd的v3.0版本。etcd在華為PaaS平臺被作為關鍵組件應用在分布式數據協調和數據改變觀察等架構中。隨著etcd的3.0版本的發布,我們希望它能幫助我們的平臺在擴展性,性能和穩定性這些方面得到顯著的提升。我們很高興過去能與CoreOS團隊和技術社區一起工作,并希望持續與CoreOS協作將這項技術和其子系統推到一個更高的層面”——華為PaaS平臺首席架構師Ying Xiong這樣說。
效率與支持大規模使用遠程調用原生的etcd3客戶端使用gRPC協議進行通信。協議消息使用protobuf進行定義,它簡化了PRC客戶端存根代碼的生成并且使協議易于管理。比較來看,即使etcd2客戶端經過解析優化后與etcd3的消息處理性能仍然有2倍的差距。并且,gRPC在處理鏈接方面優勢明顯,因為gRPC使用單一鏈接的HTTP2多路復用流式RPC調用,而JSON客戶端必須為每個請求建立一個鏈接。
租約etcd2的鍵失效是通過存活時間(TTL)機制實現的。對于每個有存活時間的鍵,客戶端必須周期性的刷新該鍵以保證到期時它不會被自動刪除掉。每個刷新行為都會建立一個新連接并提交一個一致性仲裁給etcd去更新鍵。為了保證所有的TTL鍵存活,一個空閑的集群必須支持保持一個最低限度的TTL的鍵除以平均過期時間的吞吐量。
etcd3中的租約替代了早期TTL的實現。租約減少了保持活動的請求并限制了平穩狀態一致性更新。與一個鍵一個TTL不同,一個租約包含一個TTL,租約被分配給一個鍵。當租約生命到期了,它所關聯的所有鍵全被刪除。這個模型在很多鍵有相同的租約時減少了保持活性的通信量。保持活性的鏈接也不會像在etcd2中那樣被回收,而是使用多路復用的gPRC流的方式來保持活性。同樣的,保持活性現在由領導者來處理,避免了在空閑集群提交一致性協議占用資源過多的情況。
觀察者觀察者在etcd中持續觀測鍵值的變化。與ZooKeeper或Consul等返回觀察事件不同,etcd可以持續觀察從當前版本開始的變化。在etcd2中,這些流式的觀察室通過long polling模式的HTTP請求實現的,它使etcd2的服務器極其浪費的為每個觀察者建立一個TCP鏈接。當應用有數千個客戶端觀察數千個鍵時,這種機制會很快耗盡etcd2服務器的套接字和內存資源。
etcd3的多路復用觀察者使用一個鏈接。與每次都打開一個新連接不同,客戶端會在一個雙向gRPC流中注冊一個觀察者。流會發送一個帶有觀察者注冊ID的事件。多個觀察流甚至可以共享相同的TCP鏈接。多路復用和流式鏈接共享減少了至少一個數量級的etcd3的內存占用。
可靠事件的數據模型跟所有鍵值對存儲引擎相同,etcd的數據模型是鍵映射到值上。etcd2的模型僅僅保持最近的鍵值映射是可用的;老版本是被廢掉的。但是,跟蹤所有鍵變化或者掃描整個鍵空間的應用需要一個可靠的事件流去持續重構過去的鍵狀態。為了避免過早的刪除事件以保證這些應用在短暫掉線后仍能正常工作,etcd2維護一個短小的全局滑動事件窗口。但是,如果一個觀察者從一個窗口劃過的修訂開始觀察,那么觀察者將錯過廢棄的事件。
etcd3去掉了這個不可預計的窗口,取而代之的是通過新的多版本并發控制模型去維護鍵的歷史版本。歷史版本保留策略可以為了細粒度存儲管理的需要由集群管理員進行配置。通常etcd3通過一個定時器作廢老版本的鍵更改。一個典型的etcd3集群會保存幾個小時的作廢鍵。為了穩定處理客戶端過長時間離線,不僅僅是透明的網絡中斷,觀察者可以從最后一次觀察的歷史修訂中恢復過來。為了從存儲中讀取特定時間的數據,鍵讀取請求需要使用一個修訂版來標記,這樣就會返回鍵在這個特定版本的值。
另外為了保存歷史數據,etcd3用扁平二進制鍵空間替代了etcd2的繼承鍵結構。事件上,應用更傾向于獲取單獨的鍵或者迭代獲取一個目錄下所有的鍵。使用繼承模式的場景并不常見。etcd3額外提供了在一個區間中鍵按范圍搜索的功能。這個區間模型支持前綴匹配查詢和一個鍵命名習慣模式,這種模式像從一個目錄里來列出鍵一樣。
并發控制當多個客戶端并發讀取或修改一個或一組鍵時,為了阻止損害應用狀態的數據競爭,同步原子操作變得格外重要。為了這個目的,etcd2提供了load-link/store-conditional和compare-and-swap操作;一個客戶端確定一個先前的版本索引或者值去做匹配,看是否可以更新鍵。雖然對于簡單的信號量和有限的原子更新這些操作是足夠的,但是對于一個像分布式鎖和事務級內存這種更加要求成熟度的序列化數據訪問方案來說,這就明顯不適合了。
etcd3可以序列化多個操作為一個條件性的迷你事務。每個事務包含一組條件守護的組合(例如,對于鍵版本,鍵值,已經修改的版本和創建版本的檢查),當所有提交滿足時一組操作被執行(例如,Get、Put、Delete操作),并且任何條件不滿足時另外一組操作被執行。事務可以保證分布式鎖的安全。在etcd3中,因為訪問是否被條件性取決于是否客戶端持有它的鎖。這意味著如果一個客戶端因為時鐘傾斜或者錯過失效事件而失去它獲得的鎖,那么etcd3會毫不留情的拒絕客戶端失效的請求。
展望未來etcd3相對于etcd模型有了質的飛躍。新的etcd3的API是更加有效率和可擴展的。它不僅滿足了當今使用etcd的應用的需求,同時滿足未來的超大規模的集群。
“我們在我們的大規模分布式存儲產品——TiKV中廣泛使用etcd。我們將etcd的raft庫嵌入到我們存儲層去支持一致性復制,并且我們在TiKV集群中使用etcd去協調存儲節點,”PingCAP的CEO劉琦介紹說。“我們非常高興與etcd團隊合作,并樂于見到他們新版本的發布!”
有了etcd3,通過多版本歷史鍵數據技術,數據傳播會更加可靠。同時etcd3的事務原語使原子性更新多個鍵變得容易,同步多個進程變的安全。
etcd目前還在活躍開發中去繼續在集群同步軟件中成為最好的。項目遵循穩定發布模式,這樣可以快速開發新功能而不用擔心犧牲穩定性。未來,etcd項目計劃增加支持更好擴容性的智能代理,自定義etcd個性化協議網關,和更多的測試,更好的保證整個系統。