kafka叢集基於吞吐量指標進行效能調優實踐-kafka 商業環境實戰

開心雲技術社群發表於2018-12-03

本套技術專欄是作者(秦凱新)平時工作的總結和昇華,通過從真實商業環境抽取案例進行總結和分享,並給出商業應用的調優建議和叢集環境容量規劃等內容,請持續關注本套部落格。期待加入IOT時代最具戰鬥力的團隊。QQ郵箱地址:1120746959@qq.com,如有任何學術交流,可隨時聯絡。

概要

  • 效能
    • 吞吐量:broker或者clients應用程式每秒能處理多少位元組(或訊息)
    • 延時:通常指Producer傳送到broker端持久化儲存訊息之間的時間間隔。
  • 可用性:系統和元件正常執行的概率或時間比率,業界一般N個9來量化可用性,比如年度4個9表示53分鐘(365* 24 * 60 * 0.01%=53分鐘)
  • 永續性:已提交的訊息需要被持久化到Broker端底層的檔案系統的物理日誌而不能丟失。

1 kafka 基礎設施優化

  • 磁碟容量:首先考慮的是所需儲存的訊息所佔用的總磁碟容量和每個broker所能提供的磁碟空間。如果Kafka叢集需要保留 10TB資料,單個broker能儲存 2TB,那麼我們需要的最小Kafka叢集大小5 個broker。此外,如果啟用副本引數,則對應的儲存空間需至少增加一倍(取決於副本引數)。這意味著對應的Kafka叢集至少需要 10 個broker。

  • 檔案系統在檔案被訪問、建立、修改等的時候會記錄檔案的一些時間戳,比如:檔案建立時間(ctime)、最近一次修改時間(mtime)和最近一次訪問時間(atime)。預設情況下,atime的更新會有一次讀操作,這會產生大量的磁碟讀寫,然而atime對Kafka完全沒用。

      mount -o noatime
    複製程式碼
  • 絕大多數執行在Linux上的軟體都是基於EXT4構建和測試的,因此相容性上EXT4要優於其他檔案系統。

  • 作為高效能的64位日誌檔案系統(journaling file system),XFS表現出高效能,高伸縮性,特別適應於生產伺服器,特別是大檔案(30+GB)操作。很多儲存類的應用都適合選擇XFS作為底層檔案系統。

  • 計算機的記憶體分為虛擬記憶體和實體記憶體。實體記憶體是真實的記憶體,虛擬記憶體是用磁碟來代替記憶體。 並通過swap機制實現磁碟到實體記憶體的載入和替換,這裡面用到的磁碟我們稱為swap磁碟。在寫檔案的時候,Linux首先將資料寫入沒有被使用的記憶體中,這些記憶體被叫做記憶體頁(page cache)。然後讀的時候,Linux會優先從page cache中查詢,如果找不到就會從硬碟中查詢。 當實體記憶體使用達到一定的比例後,Linux就會使用進行swap,使用磁碟作為虛擬記憶體。 通過cat /proc/sys/vm/swappiness可以看到swap引數。這個參數列示虛擬記憶體中swap磁碟佔了多少百分比。0表示最大限度的使用記憶體,100表示儘量使用swap磁碟。系統預設的引數是60,當實體記憶體使用率達到40%,就會頻繁進行swap,影響系統效能,推薦將vm.swappiness 設定為較低的值1。 最終我設定為10,因為我們的機器的記憶體還是比較小的,只有40G,設定的太小,可能會影響到虛擬記憶體的使用吧。

     臨時修改:sudo sysctl vm.swappiness=N
     永久修改(/etc/sysctl.conf):vm.swappiness=N
    複製程式碼

2 kafka JVM設定

  • PermGen space : 全稱是Permanent Generation space,是指記憶體的永久儲存區域,為什麼會發生記憶體溢位?這一部分用於存放Class和Meta的資訊, Class在被 Load的時候被放入PermGen space區域,它和存放Instance的Heap區域不同,所以如果你的APP會LOAD很多CLASS的話,就很可能出現PermGen space錯誤。

  • G1演算法將堆劃分為若干個區域(Region),它仍然屬於分代收集器。不過,這些區域的一部分包含新生代,新生代的垃圾收集依然採用暫停所有應用執行緒的方式,將存活物件拷貝到老年代或者Survivor空間。老年代也分成很多區域,G1收集器通過將物件從一個區域複製到另外一個區域,完成了清理工作。這就意味著,在正常的處理過程中,G1完成了堆的壓縮(至少是部分堆的壓縮),這樣也就不會有cms記憶體碎片問題的存在了。

  • 在G1中,還有一種特殊的區域,叫Humongous區域。 如果一個物件佔用的空間超過了分割槽容量50%以上,G1收集器就認為這是一個巨型物件。這些巨型物件,預設直接會被分配在年老代,但是如果它是一個短期存在的巨型物件,就會對垃圾收集器造成負面影響。為了解決這個問題,G1劃分了一個Humongous區,它用來專門存放巨型物件。如果一個H區裝不下一個巨型物件,那麼G1會尋找連續的H分割槽來儲存。為了能找到連續的H區,有時候不得不啟動Full GC。

    kafka叢集基於吞吐量指標進行效能調優實踐-kafka 商業環境實戰

  • G1採用記憶體分割槽(Region)的思路,將記憶體劃分為一個個相等大小的記憶體分割槽,回收時則以分割槽為單位進行回收,存活的物件複製到另一個空閒分割槽中。由於都是以相等大小的分割槽為單位進行操作,因此G1天然就是一種壓縮方案(區域性壓縮);

  • G1雖然也是分代收集器,但整個記憶體分割槽不存在物理上的年輕代與老年代的區別,也不需要完全獨立的survivor(to space)堆做複製準備。G1只有邏輯上的分代概念,或者說每個分割槽都可能隨G1的執行在不同代之間前後切換;

  • G1的收集都是STW的,但年輕代和老年代的收集界限比較模糊,採用了混合(mixed)收集的方式。即每次收集既可能只收集年輕代分割槽(年輕代收集),也可能在收集年輕代的同時,包含部分老年代分割槽(混合收集),這樣即使堆記憶體很大時,也可以限制收集範圍,從而降低停頓。

  • 堆記憶體中一個Region的大小可以通過-XX:G1HeapRegionSize引數指定,大小區間只能是1M、2M、4M、8M、16M和32M,總之是2的冪次方,如果G1HeapRegionSize為預設值,則在堆初始化時計算Region的實踐大小,預設把堆記憶體按照2048份均分,最後得到一個合理的大小。

  • JVM 8 metaSpace 誕生了: 不過元空間與永久代之間最大的區別在於:元空間並不在虛擬機器中,而是使用本地記憶體。因此,預設情況下,元空間的大小僅受本地記憶體限制,但可以通過以下引數來指定元空間的大小: -XX:MetaspaceSize,初始空間大小,達到該值就會觸發垃圾收集進行型別解除安裝,同時GC會對該值進行調整:如果釋放了大量的空間,就適當降低該值;如果釋放了很少的空間,那麼在不超過MaxMetaspaceSize時,適當提高該值。

  • -XX:MinMetaspaceFreeRatio,在GC之後,最小的Metaspace剩餘空間容量的百分比,減少為分配空間所導致的垃圾收集 -XX:MaxMetaspaceFreeRatio,在GC之後,最大的Metaspace剩餘空間容量的百分比,減少為釋放空間所導致的垃圾收集

  • XX:MaxGCPauseMillis=n : 設定最大GC停頓時間(GC pause time)指標(target). 這是一個軟性指標(soft goal), JVM 會盡量去達成這個目標。

  • InitiatingHeapOccupancyPercent: 整個堆疊使用達到百分之多少的時候,啟動GC週期. 基於整個堆,不僅僅是其中的某個代的佔用情況,G1根據這個值來判斷是否要觸發GC週期, 0表示一直都在GC,預設值是45(即45%慢了,或者說佔用了)

  • -XX:G1NewSizePercent 新生代最小值,預設值5%

  • -XX:G1MaxNewSizePercent 新生代最大值,預設值60%

  • MetaspaceSize: 這個JVM引數是指Metaspace擴容時觸發FullGC的初始化閾值,也是最小的閾值。

      # export JAVA_HOME=/usr/java/jdk1.8.0_51
      # export KAFKA_HEAP_OPTS="
      -Xmx6g -Xms6g -XX:MetaspaceSize=128m 
      -XX:MaxMetaspaceSize=128m -XX:+UseG1GC -XX:MaxGCPauseMillis=20
      -XX:InitiatingHeapOccupancyPercent=35 -XX:+G1HeapRegionSize=16M
      -XX:MinMetaspaceFreeRatio=50 "
    複製程式碼
  • 本套技術專欄是作者(秦凱新)平時工作的總結和昇華,通過從真實商業環境抽取案例進行總結和分享,並給出商業應用的調優建議和叢集環境容量規劃等內容,請持續關注本套部落格。期待加入IOT時代最具戰鬥力的團隊。QQ郵箱地址:1120746959@qq.com,如有任何學術交流,可隨時聯絡。

3 檔案調優

  • 若出現"too many files open"錯誤時,就需要為Broker所在的機器調優最大檔案部署符上限。檔案控制程式碼個數計算方法如下:

      broker上可能最大分割槽數*(每個分割槽平均資料量/平均的日誌段大小+3)其中3 表示索引檔案個數,
      假設20個分割槽,分割分割槽總資料量為100GB,每一個日誌段大小是1GB,那麼這臺機器最大檔案部署符大小應該是:
                  20*(100/1+3)=2060
      因此該引數一定要設定足夠大。比如100000
    複製程式碼
  • 若出現"java.lang.OutOfMemoryError:Map failed的嚴重錯誤,主要原因是大量建立topic將極大消耗作業系統記憶體,使用者可以適當調整vm.max.map.count引數,具體方法如下:

     /sbin/sysctl -w vm.max_map_count = N ,該引數預設值是65535,可以考慮線上環境設定更大的值。
    複製程式碼

4 吞吐量

Broker端;

  • 適當增加num.replica.fetchers,但不要超過CPU核數,該值控制了broker端follower副本從leader副本處獲取訊息的最大執行緒數。預設值是1,表明follower副本只使用一個執行緒實時拉取leader處的最新訊息。對於設定了acks=all的producer而言,主要延時可能耽誤在follower與leader同步過程,所以增加該值可以縮短同步的時間,從而間接的提升Producer端的TPS。
  • 調優GC避免經常性的Full GC。老版本過渡依賴Zookeeper來表徵Consumer還活著,若GC時間過長,會導致Zookeeper會話過期,kafka會立即對group進行rebalance。新版本上已經棄用了對Zookeeper的依賴。

Producer端:

  • 適當增加batch.size,比如100-512KB。
  • 適當增加linger.ms,比如10-100毫秒 Producer端是批量傳送訊息的,更大的batch size可以令更多的訊息封裝進同一個請求,故傳送給broker端的總請求數就會減少,此舉可以減輕Producer的負載,也降低了broker端的CPU請求處理開銷。而更大的linger.ms使producer等待更長的時間才傳送訊息,這樣就能夠快取更多的訊息填滿batch,從而從整體上提升TPS。但是延時肯定增加了。
  • 設定壓縮型別compression.type=lz4,目前支援的壓縮方式有:GZIP,Snappy,LZ4,在CPU資源豐富的情況下compression.type=lz4的效果是最好的。
  • acks=0或1
  • retries=0
  • 若多執行緒共享Produer或分割槽數很多時,增加buffer.memory。因為每一個分割槽都會佔用一個batch.size。

consumer端

  • 採用多Consumer例項,共同消費多分割槽資料,這些例項共享相同的group.id
  • 增加fetch.min.bytes,比如10000,表徵每次leader副本所在的broker所返回的最小資料量來間接影響TPS,通過增加該值,Kafka會為每一個FETCH請求的response填入更多的資料。

5 悖論存在(分割槽數越多,TPS越高)

kafka叢集基於吞吐量指標進行效能調優實踐-kafka 商業環境實戰

  • Kafka基本的並行單元就是分割槽,producer在設計時實現了能夠同時向多個分割槽傳送訊息,從而這些訊息最終寫入到多個broker上,最終可以被多個consumer同時消費。通常來說,分割槽數越多,TPS越高
  • 分割槽數越多,佔用的緩衝區越多,因為緩衝區是以分割槽為粒度的,所以Server/clients端將佔用更多的記憶體。
  • 每一個分割槽在底層檔案系統中都有專屬目錄,除了3個索引檔案外還儲存日誌段檔案,會佔用大量的檔案控制程式碼。
  • 每一個分割槽都有若干個副本儲存在不同的broker上,當broker掛掉後,因為需要Controller進行處理leader變更請求,該處理執行緒是單執行緒,瘋了吧,亞歷山大。
  • 本套技術專欄是作者(秦凱新)平時工作的總結和昇華,通過從真實商業環境抽取案例進行總結和分享,並給出商業應用的調優建議和叢集環境容量規劃等內容,請持續關注本套部落格。期待加入IOT時代最具戰鬥力的團隊。QQ郵箱地址:1120746959@qq.com,如有任何學術交流,可隨時聯絡。

7 總結

num.replica.fetchers倒是一個新穎的選手,可以好好試試,acks重點關注,其他都中規中矩。一片好文得來不易,尊重原創,謝絕轉載,謝謝!

本套技術專欄是作者(秦凱新)平時工作的總結和昇華,通過從真實商業環境抽取案例進行總結和分享,並給出商業應用的調優建議和叢集環境容量規劃等內容,請持續關注本套部落格。期待加入IOT時代最具戰鬥力的團隊。QQ郵箱地址:1120746959@qq.com,如有任何學術交流,可隨時聯絡。

秦凱新 於深圳 201812032355

相關文章