課程目標
理解 etcd 性能
etcd 性能優(yōu)化
1. 理解etcd性能
image-20200618174108466.png上圖是一個標準的 etcd 集群架構(gòu)簡圖篙悯。可以將 etcd 集群劃分成幾個核心的部分:例如藍色的 Raft 層、紅色的 Storage 層榛搔,Storage 層內(nèi)部又分為 treeIndex 層和 boltdb 底層持久化存儲 key/value 層吮播。它們的每一層都有可能造成 etcd 的性能損失鹰服。
Raft 病瞳。Raft 需要通過網(wǎng)絡同步數(shù)據(jù),網(wǎng)絡 IO 節(jié)點之間的 RTT 和 / 帶寬會影響 etcd 的性能悲酷。除此之外套菜,WAL 也受到磁盤 IO 寫入速度影響。
Storage 设易。磁盤 IO fdatasync 延遲會影響 etcd 性能逗柴,索引層鎖的 block 也會影響 etcd 的性能。除此之外顿肺,boltdb Tx 的鎖以及 boltdb 本身的性能也將大大影響 etcd 的性能戏溺。
其他方面渣蜗。etcd 所在宿主機的內(nèi)核參數(shù)和 gRPC api 層的延遲,也將影響 etcd 的性能于购。
2. etcd 性能優(yōu)化
2.1. server端性能優(yōu)化
2.1.1. 硬件方面
server 端在硬件上需要足夠的 CPU 和 Memory 來保障 etcd 的運行袍睡。其次知染,作為一個非常依賴于磁盤 IO 的數(shù)據(jù)庫程序肋僧,etcd 需要 IO 延遲和吞吐量非常好的 ssd 硬盤,etcd 是一個分布式的 key/value 存儲系統(tǒng)控淡,網(wǎng)絡條件對它也很重要嫌吠。最后在部署上,需要盡量將它獨立的部署掺炭,以防止宿主機的其他程序會對 etcd 的性能造成干擾辫诅。可以參考官方文檔涧狮。
2.1.2. 軟件方面
etcd 軟件分成很多層炕矮,下面根據(jù)不同層次進行性能優(yōu)化的簡單介紹。因為我對于開發(fā)不是很擅長者冤,想深度了解的同學可以自行訪問下面的 GitHub pr 來獲取具體的修改代碼肤视。
- 首先是針對于 etcd 的內(nèi)存索引層優(yōu)化:優(yōu)化內(nèi)部鎖的使用減少等待時間。 原來的實現(xiàn)方式是遍歷內(nèi)部引 BTree 使用的內(nèi)部鎖粒度比較粗涉枫,這個鎖很大程度上影響了 etcd 的性能,新的優(yōu)化減少了這一部分的影響,降低了延遲翔怎。具體可參照如下鏈接:https://github.com/coreos/etcd/pull/9511
- 針對于 lease 規(guī)模使用的優(yōu)化:優(yōu)化了 lease revoke 和過期失效的算法枕屉,將原來遍歷失效 list 時間復雜度從 O(n) 降為 O(logn),解決了 lease 規(guī)某耐ⅲ化使用的問題摇予。具體可參照如下鏈接:https://github.com/coreos/etcd/pull/9418
- 最后是針對于后端 boltdb 的使用優(yōu)化:將后端的 batch size limit/interval 進行調(diào)整,這樣就能根據(jù)不同的硬件和工作負載進行動態(tài)配置吗跋,這些參數(shù)以前都是固定的保守值侧戴。具體可參照如下鏈接:https://github.com/etcd-io/etcd/commit/3faed211e535729a9dc36198a8aab8799099d0f3
- 還有一點是由谷歌工程師優(yōu)化的完全并發(fā)讀特性:優(yōu)化調(diào)用 boltdb tx 讀寫鎖使用,提升讀性能小腊。具體可參照如下鏈接:https://github.com/etcd-io/etcd/pull/10523
2.1.3. Raft log retention
etcd --snapshot-count
配置壓縮前要保存在內(nèi)存中的應用Raft條目數(shù)救鲤。當---snapshot-count
達到設定的數(shù)值時,服務器會將快照數(shù)據(jù)保存到磁盤上秩冈,然后截斷舊條目本缠。當速度較慢的follower節(jié)點在壓縮索引之前請求日志時,leader會發(fā)送快照入问,強制follower覆蓋其狀態(tài)丹锹。
如果把 --snapshot-count
參數(shù)調(diào)整高一點稀颁,在快照之前會在內(nèi)存中保留更多Raft條目,從而導致經(jīng)常性的更高內(nèi)存使用率楣黍,recurrent higher memory usage匾灶,這是一個issue。由于leader保留最新的Raft條目的時間更長租漂,所以慢的follower在leader快照之前有更多的時間追趕阶女。--snapshot-count
的數(shù)值應該在較高的內(nèi)存使用率和較慢的follower的較高可用性之間進行權(quán)衡。
從v3.2開始哩治,默認值--snapshot count從10000更改為100000秃踩。
在性能方面,--snapshot-count
大于100000可能會影響寫入的吞吐量业筏。內(nèi)存中對象的數(shù)量增加會減慢Go語言GC標記階段的runtime.scanobject
憔杨,這也是一個issue, Go GC mark phase runtime.scanobject
蒜胖。并且不頻繁的內(nèi)存回收會使分配變慢消别。性能因工作負載和系統(tǒng)環(huán)境而異。但是台谢,通常情況下寻狂,過于頻繁的壓縮會影響群集可用性和寫入吞吐量。過于頻繁的壓縮也有害于給垃圾收集器施加過大的壓力对碌。具體的結(jié)果可以看slideshare荆虱。
2.1.4. Auto Compaction自動壓縮
etcd默認會為key保留一個小時,也就是一個小時之后朽们,key的空間就會被自動壓縮
# keep one hour of history
$ etcd --auto-compaction-retention=1
在v3.0.0和v3.1.0版本怀读,
--auto-compaction-retention=10
在v3版本的key-value上運行,每10小時進行一次壓縮骑脱。壓縮功能只支持階段性壓縮菜枷。壓縮器會每五分鐘記錄一次最新的revision,知道達到第一個壓縮點(比如10個小時)叁丧。為了保留上次壓縮時期的鍵值歷史記錄啤誊,他使用壓縮器件之前,從每5分鐘收集的revision記錄中獲取最后的revision拥娄。當--auto-compaction-retention=10
的時候蚊锹,壓縮器使用revision 100作為壓縮的revision,其中revison 100是10小時前回去的最新版本稚瘾。如果壓縮成功或請求的修訂已被壓縮牡昆,則他將重置時段計時器并以新的歷史revision記錄重新開始(例如,重新啟動revision收集并壓縮下一個10小時的時段)摊欠。如果壓縮失敗丢烘,5分鐘后會重試柱宦。在3.2.0版本中,壓縮器每小時運行一次播瞳。壓縮器只支持階段性壓縮掸刊。壓縮器同樣是五分鐘運行一次,來記錄最新一次的revision赢乓。在每個小時內(nèi)忧侧,它使用壓縮期間之前,每5分鐘收集來的revision記錄中獲取的最后一個revision骏全。也就是說苍柏,每小時尼斧,壓縮程序都會丟棄壓縮期間之前創(chuàng)建的歷史數(shù)據(jù)姜贡。壓縮時期的保持期會移到下一小時。例如棺棵,當每小時寫入次數(shù)為100并且
--auto compression retention=10
時楼咳,v3.1每10小時壓縮一次revision 1000、2000和3000次烛恤,而v3.2.x母怜、v3.3.0、v3.3.1和v3.3.2每1小時壓縮revision 1000缚柏、1100和1200次苹熏。如果壓縮成功或請求的revision已被壓縮,它將重置時段計時器币喧,并從歷史revision記錄中刪除已使用的壓縮revision(例如轨域,從以前收集的revision開始下一個revision收集和壓縮)。如果壓縮失敗杀餐,將在5分鐘后重試干发。在v3.3.0、v3.3.1和v3.3.2中史翘,
--auto-compaction-mode=revision --auto-compaction-retention=1000
在"latest revision"上自動壓縮-每5分鐘壓縮1000(當最新revision為30000時枉长,在revision29000上壓縮)。例如琼讽,--auto-compaction-mode=periodic --auto-compaction-retention=72h
在壓縮的時候必峰,每7.2小時有72小時的保持時間窗口。例如钻蹬,--auto-compaction-mode=periodic --auto-compaction-retention=30m
吼蚁,每3分鐘用30分鐘保持時間窗口自動壓實。定期壓縮機繼續(xù)記錄給定壓縮周期的每1/10的最新revision(例如脉让,--auto-compaction-mode=periodic --auto-compaction-retention=10h
為1小時)桂敛。對于給定壓縮周期的每1/10功炮,compactor使用壓縮周期之前獲取的最后一個修訂版來丟棄歷史數(shù)據(jù)。每給定壓實周期的1/10术唬,壓實周期的保留窗口移動一次薪伏。例如,當每小時寫入次數(shù)為100并且--auto-compaction-retention=10
時粗仓,v3.1每10小時壓縮一次revision1000嫁怀、2000和3000,而v3.2.x借浊、v3.3.0塘淑、v3.3.1和v3.3.2每1小時壓縮一次revision1000、1100和1200蚂斤。此外存捺,當每分鐘寫入1000、v3.3.0曙蒸、v3.3.1和v3.3.2時捌治,對于粒度更細的每3分鐘,--auto-compaction-mode=periodic --auto-compaction-retention=30m
壓縮版本30000纽窟、33000和36000肖油。-
當
--auto-compaction-retention=10h
的時候, etcd 會先等待10小時進行第一次壓縮,然后每小時壓縮(1/10個10小時)以此類推0Hr (rev = 1) 1hr (rev = 10) ... 8hr (rev = 80) 9hr (rev = 90) 10hr (rev = 100, Compact(1)) 11hr (rev = 110, Compact(10)) ...
不管壓縮成功與否臂港,這個進程會在給定的1/10個壓縮時間段中不斷的重復森枪。如果壓縮成功,他會把已經(jīng)壓縮的revijsion從歷史revision記錄中移除审孽。
在v3.3.3版本中县袱,
--auto-compaction-mode=revision --auto-compaction-retention=1000
在latest revision
上每5分鐘就自動壓縮(latest revsion為30000時,在29000的revision上壓縮)瓷胧。在以前--auto-compaction-mode=periodic --auto-compaction-retention=72h
每7.2小時自動壓縮显拳,72小時保留窗口一次。現(xiàn)在搓萧,每隔1小時就會發(fā)生一次壓縮杂数,但保留時間仍為72小時。以前瘸洛,--auto-compaction-mode=periodic --auto-compaction-retention=30m
揍移,自動壓縮時,每3分鐘保留30分鐘的保留窗口》蠢撸現(xiàn)在那伐,每30分鐘執(zhí)行一次壓縮,但保留時間仍為30分鐘。當給定周期小于1小時時罕邀,階段性壓縮器會記錄每個壓縮周期的最新revision畅形,如果給定周期大于1小時(比如: 在1小時內(nèi),當--auto-compaction-mode=periodic --auto-compaction-retention=24h
的時候)诉探。對于每個壓實周期或1小時日熬,壓縮器會使用在壓縮周期之前獲取的最新revision來丟棄歷史數(shù)據(jù)。壓縮期的保留窗口會在每個給定的壓實期或小時內(nèi)移動肾胯。例如竖席,當每小時寫入為100并且--auto-compaction-mode=periodic --auto-compaction-retention=24h
的時候,v3.2.x敬肚,v3.3.0毕荐,v3.3.1和v3.3.2每2個小時壓縮revision2400,2640和2880艳馒,而v3.3.3或更高版本每1小時壓縮2400憎亚、2500、2600版本鹰溜。此外虽填,當--auto-compaction-mode=periodic --auto-compaction-retention=30m
且每分鐘寫入量約為1000,v3.3.0曹动,v3.3.1和v3.3.2壓縮30000、33000和36000時牲览, v3.3.3或更高版本每3分鐘壓縮一次revision30000墓陈、60000和90000,每30分鐘壓縮一次第献。
2.1.5. Defragmentation去碎片化
壓縮鍵空間后贡必,后端數(shù)據(jù)庫可能會出現(xiàn)內(nèi)部碎片。 任何內(nèi)部碎片都是后端可以免費使用但仍消耗存儲空間的空間庸毫。 通過在后端數(shù)據(jù)庫中留有空隙仔拟,內(nèi)部壓縮舊修訂會碎片化etcd。 碎片空間可供etcd使用飒赃,但對主機文件系統(tǒng)不可用利花。 換句話說,刪除應用程序數(shù)據(jù)不會回收磁盤上的空間载佳。
碎片整理過程會將此存儲空間釋放回文件系統(tǒng)炒事。 對每個成員進行碎片整理,以便避免群集范圍內(nèi)的延遲峰值蔫慧。
要對etcd成員進行碎片整理挠乳,請使用etcdctl defrag
命令:
$ etcdctl defrag
Finished defragmenting etcd member[127.0.0.1:2379]
請注意,對活動成員進行碎片整理會阻止系統(tǒng)在重建其狀態(tài)時讀取和寫入數(shù)據(jù)。就是說如果有節(jié)點在恢復數(shù)據(jù)睡扬,這個操作會打斷的盟蚣。
如果要對集群做整理,就需要指定--endpoints或者使用--cluster選項
$ etcdctl defrag --cluster
Finished defragmenting etcd member[http://127.0.0.1:2379]
Finished defragmenting etcd member[http://127.0.0.1:22379]
Finished defragmenting etcd member[http://127.0.0.1:32379]
如果etcd沒在運行卖怜,就需要指定etcd的--data-dir
$ etcdctl defrag --data-dir <path-to-etcd-data-dir>
2.1.5. Space quota空間限額
etcd中的空間配額可確保集群以可靠的方式運行刁俭。 如果沒有空間配額,則如果密鑰空間過大韧涨,etcd可能會遭受性能不佳的影響牍戚,或者它可能僅會耗盡存儲空間,從而導致無法預測的集群行為虑粥。 如果任何成員的密鑰空間的后端數(shù)據(jù)庫超出了空間配額如孝,則etcd會發(fā)出一個群集范圍的警報,該警報會將群集置于維護模式娩贷,該模式僅接受密鑰讀取和刪除第晰。 只有在釋放鍵空間中足夠的空間并對后端數(shù)據(jù)庫進行碎片整理以及清除空間配額警報之后,集群才能恢復正常運行彬祖。但是生產(chǎn)系統(tǒng)上幾乎沒有人這么做茁瘦。
默認情況下,etcd設置適合大多數(shù)應用程序的保守的空間配額储笑,但是可以在命令行上以字節(jié)為單位進行配置:
# set a very small 16MB quota
$ etcd --quota-backend-bytes=$((16*1024*1024))
可以使用循環(huán)來觸發(fā)他
# fill keyspace
$ while [ 1 ]; do dd if=/dev/urandom bs=1024 count=1024 | ETCDCTL_API=3 etcdctl put key || break; done
...
Error: rpc error: code = 8 desc = etcdserver: mvcc: database space exceeded
# confirm quota space is exceeded
$ ETCDCTL_API=3 etcdctl --write-out=table endpoint status
+----------------+------------------+-----------+---------+-----------+-----------+------------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | RAFT TERM | RAFT INDEX |
+----------------+------------------+-----------+---------+-----------+-----------+------------+
| 127.0.0.1:2379 | bf9071f4639c75cc | 2.3.0+git | 18 MB | true | 2 | 3332 |
+----------------+------------------+-----------+---------+-----------+-----------+------------+
# confirm alarm is raised
$ ETCDCTL_API=3 etcdctl alarm list
memberID:13803658152347727308 alarm:NOSPACE
刪除過多的鍵空間數(shù)據(jù)并對后端數(shù)據(jù)庫進行碎片整理將使群集重新回到配額限制內(nèi):
# get current revision
$ rev=$(ETCDCTL_API=3 etcdctl --endpoints=:2379 endpoint status --write-out="json" | egrep -o '"revision":[0-9]*' | egrep -o '[0-9].*')
# compact away all old revisions
$ ETCDCTL_API=3 etcdctl compact $rev
compacted revision 1516
# defragment away excessive space
$ ETCDCTL_API=3 etcdctl defrag
Finished defragmenting etcd member[127.0.0.1:2379]
# disarm alarm
$ ETCDCTL_API=3 etcdctl alarm disarm
memberID:13803658152347727308 alarm:NOSPACE
# test puts are allowed again
$ ETCDCTL_API=3 etcdctl put newkey 123
OK
2.2. client端性能優(yōu)化
針對于 Put 操作避免使用大 value甜熔,精簡精簡再精簡,例如 K8s 下的 crd 使用突倍;
其次腔稀,etcd 本身適用及存儲一些不頻繁變動的 key/value 元數(shù)據(jù)信息。因此客戶端在使用上需要避免創(chuàng)建頻繁變化的 key/value羽历。這一點例如 K8s下對于新的 node 節(jié)點的心跳數(shù)據(jù)上傳就遵循了這一實踐焊虏;
最后,我們需要避免創(chuàng)建大量的 lease秕磷,盡量選擇復用诵闭。例如在 K8s下,event 數(shù)據(jù)管理:相同 TTL 失效時間的 event 同樣會選擇類似的 lease 進行復用澎嚣,而不是創(chuàng)建新的 lease疏尿。
為了方便大家學習,請大家加我的微信币叹,我會把大家加到微信群(微信群的二維碼會經(jīng)常變)和qq群821119334润歉,問題答案云原生技術(shù)課堂,有問題可以一起討論-
個人微信
640.jpeg -
騰訊課堂
640-20200506145837072.jpeg -
微信公眾號
640-20200506145842007.jpeg 專題講座
2020 CKA考試視頻 真題講解 https://www.bilibili.com/video/BV167411K7hp
2020 CKA考試指南 https://www.bilibili.com/video/BV1sa4y1479B/
2020年 5月CKA考試真題 https://mp.weixin.qq.com/s/W9V4cpYeBhodol6AYtbxIA