etcd、Zookeeper和Consul一致鍵值數據存儲的性能對比

這篇博文是探索三個分佈式、一致性鍵值數據存儲軟件性能的系列文章中的第一篇:etcd、Zookeeper和Consul,由etcd團隊所寫,可讓咱們全面地瞭解如何評估三個分佈式一致存儲軟件的性能。翻譯過程當中不免有偏差,還請你們諒解html

一致性鍵值存儲的用處

許多現代分佈式應用程序都創建在分佈式一致鍵值存儲之上。Hadoop生態系統中的應用程序和「Netflix棧」的許多部分都使用ZookeeperConsul公開了服務發現和運行情況檢查API,並支持Nomad等集羣工具。Kubernetes容器編排系統,MySQLVitess水平擴展,Google Key Transparency項目以及許多其餘系統都是基於etcd構建的。有了這麼多關鍵任務集羣,服務發現和基於這些一致鍵值存儲的數據庫應用程序,測量可靠性和性能是相當重要的。java

知足寫性能須要的條件

理想的鍵值存儲每秒攝取許多鍵,快速持久並確認每次寫入,並保存大量數據。若是存儲沒法跟上寫入,那麼請求將超時,可能會觸發故障轉移和停機。若是寫入速度很慢,那麼應用程序看起來很慢。若是數據過多,存儲系統可能會爬行甚至沒法運行。git

咱們使用dbtester來模擬寫入,並發現etcd在這些基準測試中優於相似的一致分佈式鍵值存儲軟件。在較低的層面上,背後的架構決策能夠更加統一和有效地利用資源,這些決策轉化爲在合理的工做負載和規模下可靠的良好吞吐量、延遲和總容量。這反過來又有助於使用etd的應用程序,如Kubernetes,可靠、易於監控和高效。github

性能有不少方面,本文將深刻介紹鍵的建立,鍵值的填充和存儲,來講明底層的機制。數據庫

資源利用

在跳到高級性能以前,首先經過資源利用率和併發性突出鍵值存儲行爲的差別是有幫助的,寫操做爲驗證這個問題提供了一個很好的例子。寫操做必須和磁盤關聯起來,由於寫操做會持久鍵值到媒體。而後,這些數據必須跨服務器進行復制(replicate across machines),從而致使集羣間大量網絡流量。這些流量構成了處理寫的所有開銷的一部分,這會消耗CPU。最後,將鍵放入存儲區直接利用內存獲取鍵用戶數據,並間接用於簿記(book-keeping)。apache

根據最近的一項用戶調查,大多數etcd部署都使用虛擬機。爲了遵照最多見的平臺配置,全部的測試都在谷歌雲平臺計算引擎虛擬機(Google Cloud Platform Compute Engine virtual machines)上運行,而且使用Linux OS(全部虛擬機都有Ubuntu 16.10, Linux內核4.8.0-37-genericext4文件系統。咱們選擇Ubuntu做爲一箇中立的Linux操做系統,而不是像Container Linux那樣的CoreOS項目,以說明這些結果應該適用於任何類型的Linux發行版。可是,在容器Linux上收集這些基準測試將獲得很是類似的結果)。每一個集羣使用三個VM,足以容忍單個節點故障。每一個VM都有16個專用的vcpu30GB內存和300GB SSD,能夠達到150 MB/s的持續寫操做。這個配置足夠強大,能夠模擬來自1000個客戶機的流量,這對於etcd的用例和如下資源度量所選擇的目標來講是最小的。全部的測試都進行了屢次試驗,在運行之間的誤差相對較小,不影響任何通常結論。etcd的使用以下圖所示:後端

鍵值存儲基準測試設置緩存

全部基準測試都使用如下軟件配置:服務器

軟件名稱 版本 編譯語言版本
etcd v3.1.0 Go 1.7.5
Zookeeper r3.4.9 Java 8 (JRE build 1.8.0_121-b13)
Consul v0.7.4 Go 1.7.5

每一個資源利用率測試都會建立一百萬個具備1024字節值的惟一256字節鍵(one million unique 256-byte keys with 1024-byte values)。選擇鍵長度以使用共同的最大路徑長度對存儲軟件施加壓力,選擇值長度是由於它是protobuf編碼的Kubernetes值的預期平均大小。雖然精確的平均鍵長度和值長度是與工做負載相關的,但長度表明極端之間的權衡。更精確的敏感性研究將爲每一個存儲軟件提供更多關於最佳案例表現特徵的看法,但風險更大。網絡

磁盤帶寬

寫操做必須持久化到磁盤,他們記錄共識提案(consensus proposals),壓縮舊數據,並保存存儲快照。在大多數狀況下,寫入應該以記錄共識提案爲主。etcd的日誌(log)將protobuf編碼的提議流轉換爲一系列預分配文件,在頁面邊界處同步,每一個條目都有滾動的CRC32校驗和。 Zookeeper的事務日誌(transaction log)相似,可是使用Adler32進行jute編碼和校驗和。Consul採用不一樣的方法,而是記錄到boltdb/bolt後端,raft-boltdb

下圖顯示了擴展客戶端併發性如何影響磁盤寫入。正如預期的那樣,當併發性增長時,ext4文件系統上/proc/diskstats上的磁盤帶寬會增長,以應對請求壓力的增長。etcd的磁盤帶寬穩定增加,它寫的數據比Zookeeper還多,由於除了日誌外,它還必須寫boltDB。另外一方面,Zookeeper會由於寫入完整的狀態快照而丟失數據速率,這些完整的快照與etcd的增量和併發提交相反,後者只寫入更新,而不會中止全部正在進行的操做(stopping the world)。Consul的數據率最初大於etcd,這多是因爲在B+樹中刪除了提交的raft協議(raft proposals)而致使的寫放大,而後因爲花了幾秒鐘寫快照而出現波動。

建立一百萬個鍵時的平均服務器磁盤寫入吞吐量

網絡

網絡是分佈式鍵值存儲的中心。客戶端與鍵值存儲集羣的服務器進行通訊,集羣中的服務器相互通訊。每一個鍵值存儲都有本身的客戶端協議,etcd客戶端使用創建在HTTP/2之上的Protocol Buffer v3 gRPC協議,Zookeeper客戶端使用自定義的流式TCP協議JuteConsul使用JSON。一樣,每一個協議都有本身的TCP服務器協議。etcd peer stream protobuf編碼的raft RPC提議,Zookeeper將TCP流用於有序的雙向jute編碼ZAB通道,Consul發佈用MsgPack編碼的raft RPC。

下表顯示了全部服務器和客戶端的總網絡利用率。在大多數狀況下,etcd具備最低的網絡使用率,除了Consul客戶端接收的數據略少。這能夠經過etcdPut響應來解釋,其中包含帶有修訂數據的標題,而Consul只是以明文true響應。ZookeeperConsul的服務器間流量多是因爲傳輸大型快照和節省空間的協議編碼較少。

使用1,000個客戶端建立一百萬個鍵時傳輸的總數據量

CPU

即便存儲和網絡速度很快,集羣也必須當心處理開銷。浪費CPU的機會比比皆是:許多消息必須被編碼和解碼,糟糕的併發控制能夠對抗鎖定,系統調用能夠以驚人的頻率進行,而且內存堆能夠捶打。 因爲etcdZookeeperConsul都但願leader服務器節點處理寫入,所以較差的CPU利用率能夠輕鬆下降性能。

下圖顯示了在擴展客戶端時使用top -b -d 1測量的服務器CPU利用率。etcd CPU利用率按預期平均和最大負載進行擴展,隨着更多鏈接的增長,CPU負載依次增長。最引人注目的是Zookeeper的平均跌幅爲700,但客戶端數量增長了1000,日誌報告太忙以捕捉,跳過其SyncRequestProcessor,而後建立新的日誌文件,從1,073%利用率到230%。 這種降低也發生在1,000個客戶端,但從平均值來看不太明顯,利用率從894%上升到321%。一樣,處理快照時Consul CPU利用率降低10秒,從389% CPU降至16%

用於在客戶端擴展時建立一百萬個鍵的服務器CPU使用

內存

當鍵值存儲設計爲僅管理元數據大小的數據時,大多數數據能夠緩存在內存中。維護內存數據庫能夠提升速度,但代價是過多的內存佔用可能會致使頻繁的垃圾回收和磁盤交換,從而下降總體性能。當ZookeeperConsul在內存中加載全部鍵值數據時,etcd只保留一個小的駐留內存索引,直接經過boltdb中的內存映射文件支持其大部分數據,僅將數據保存在boltDB中會因請求分頁而致使磁盤訪問,但整體而言,etcd更好地考慮操做系統設施。

下圖顯示了在集羣總內存佔用量中向集羣添加更多鍵的效果。最值得注意的是,一旦存儲系統中有大量的鍵,etcd使用的內存量不到ZookeeperConsul的一半。Zookeeper位居第二,佔據了四倍的內存,這符合仔細調整JVM堆設置的建議(recommendation)。最後,儘管Consul使用了etcd所用的boltDB,但它的內存存儲(in-memory store)否認了etcd中的佔用空間優點,消耗了三者中最大的內存。

建立一百萬個鍵時的服務器內存佔用

存儲爆炸

隨着物理資源的肯定,重點能夠迴歸到聚合基準測試。首先,爲了找到最大鍵提取率,系統併發性可擴展到一千個客戶端。這些最佳攝取率爲測量負載下的延遲提供了基礎,從而衡量總的等待時間。一樣,每一個系統客戶端以最佳攝取速率計數,當密鑰從一百萬個鍵擴展到三百萬個鍵時,能夠經過測量吞吐量的降低來強調總容量。

吞吐量變化

隨着愈來愈多的客戶端同時寫入集羣,理想狀況下,在提高以前,提取率應該穩定上升。可是,下圖顯示在寫出一百萬個鍵時縮放客戶端數量時不是這種狀況。 相反,Zookeeper(最大速率爲43,458 req/sec)波動很大,這並不奇怪,由於它必須明確配置爲容許大量鏈接。Consul的吞吐量(最大速率16,486 req/sec)能夠很好地擴展,但在併發壓力下會下降到低速率。etcd的吞吐量(最大速率34,747 req/sec)整體穩定,隨着併發性而緩慢上升。最後,儘管ConsulZookeeper使用了更多的CPU,但最大吞吐量仍然落後於etcd

隨客戶端規模建立一百萬個鍵的平均吞吐量

延遲分佈

鑑於存儲系統的最佳吞吐量,延遲應該是局部最小且穩定,排隊效應將延遲其餘併發操做。一樣,理想狀況下,隨着鍵總數的增長,延遲會保持低且穩定,若是請求變得不可預測,則可能存在級聯超時,抖動監視警報或故障。然而,經過下面顯示的延遲測量來判斷,只有etcd具備最低的平均等待時間和規模上的緊密、穩定的界限。

etcd,Zookeeper和Consul鍵建立延遲位數和範圍

Zookeeper努力爲併發客戶提供最佳吞吐量,一旦它觸發快照,客戶端請求就會開始失敗。服務器記錄列表錯誤,例如Too busy to snap, skipping, fsync-ing the write ahead logfsync-ing the write ahead log in SyncThread: 1 took 1,038 ms which will adversely effect operation latency,最終致使leader節點丟失,Exception when following the leader。客戶端請求偶爾會失敗,包括zk等錯誤,例如zk: could not connect to a serverzk: connection closed錯誤。Consul報告沒有錯誤,儘管可能應該,它經歷了普遍的差別降級性能,多是因爲其大量寫入放大。

鍵總數

憑藉最佳平均吞吐量達到100萬個鍵的最大併發性,能夠在容量擴展時測試吞吐量。下圖顯示了時間序列延遲,以及延遲峯值的對數標度,由於鍵被添加到存儲中,最多可達300萬個鍵。在大約50萬個鍵以後,ZookeeperConsul延遲峯值都會增加。因爲高效的併發快照,etcd沒有出現尖峯,可是在一百萬個鍵以前略有延遲。

特別值得注意的是,就在兩百萬個鍵以前,Zookeeper徹底失敗了。其追隨者落後,未能及時收到快照,這代表領導者選舉須要長達20秒才能鎖定集羣。

建立300萬個鍵時的延遲

下一步是什麼

在建立一百萬個或更多鍵時,etcd能夠比ZookeeperConsul穩定地提供更好的吞吐量和延遲。此外,它實現了這一目標,只有一半的內存,顯示出更高的效率。可是,還有一些改進的餘地,Zookeeper設法經過etcd提供更好的最小延遲,代價是不可預測的平均延遲。

全部基準測試都是使用etcd的開源dbtester生成的。任何但願重現結果的人均可以得到上述測試的測試用例參數。對於更簡單,僅限etcd的基準測試,請嘗試使用etcd3基準測試工具

編譯自:Exploring Performance of etcd, Zookeeper and Consul Consistent Key-value Datastores

相關文章
相關標籤/搜索