1. 程式人生 > >Kafka Cluster優化兩三事

Kafka Cluster優化兩三事

轉自:https://bigdata-ny.github.io/2016/12/05/kafka-cluster-optimize/

寫在之前:本文將講述Kafka Cluster配置和優化。

Kafka Cluster(相對於單個server)最大的優點:可擴充套件性和容錯性。

image

​ Kafka叢集簡圖

Kafka Broker個數

決定Kafka叢集大小的因素有以下幾點:

  • 磁碟容量:首先考慮的是所需儲存的訊息所佔用的總磁碟容量和每個broker所能提供的磁碟空間。如果Kafka叢集需要保留 10 TB資料,單個broker能儲存 2 TB,那麼我們需要的最小Kafka叢集大小 5 個broker。此外,如果啟用副本引數,則對應的儲存空間需至少增加一倍(取決於副本引數)。這意味著對應的Kafka叢集至少需要 10 個broker。
  • 請求量:另外一個要考慮的是Kafka叢集處理請求的能力。這主要取決於對Kafka client請求的網路處理能力,特別是,有多個consumer或者網路流量不穩定。如果,高峰時刻,單個broker的網路流量達到80%,這時是撐不住兩個consumer的,除非有兩個broker。再者,如果啟用了副本引數,則需要考慮副本這個額外的consumer。也可以擴充套件多個broker來減少磁碟的吞吐量和系統記憶體。

Kafka Broker配置

同一個Kafka叢集的所有broker機器必須滿足以下兩個引數:

  • 所有broker機器需配置相同的zookeeper連線引數(.connect)。這決定了Kafka叢集儲存的元資料位置;
  • 所有broker機器需配置唯一的broker id( .id)。如果一個叢集下的兩個broker配置了相同的broker id,則第二個broker啟動時會失敗並報錯。

作業系統優化

大部分Linux釋出版本預設的核心引數配置能讓大部分應用工作的相當好。但對於實際的Kafka broker場景來說,做稍些改變會提升broker效能。主要涉及的配置:虛擬記憶體、網路和磁碟掛載(用來儲存log segment),一般在/etc/sysctl.conf (CentOS系統)。

  • Virtual Memory

一般來說,Linux的虛擬記憶體會根據系統負載自動調整。記憶體頁(page)swap到磁碟會顯著的影響Kafka的效能,並且Kafka重度使用page cache,如果VM系統swap到磁碟,那說明沒有足夠的記憶體來分配page cache。

避免swap的一種方式是設定swap空間為0。但是,swap會在系統崩潰時提供安全機制,或者會在out of memory的情況下阻止作業系統 kill 掉程序。由於這個原因,推薦 vm.swappiness引數設定為一個非常低的值:1 。這個引數表示 VM系統中的多少百分比用來作為swap空間。

另外一種方式是通過核心調節“髒頁”(注:“髒頁”會被刷到磁碟上)。Kafka依賴磁碟I/O效能來提高producer的響應時間。這也是為什麼通常優先把log segment功能放在可以快速響應的磁碟中(比如,SSD)。這樣使得flush程序把“髒資料”寫入磁碟前,“髒頁”數目就減少了,可以設定vm.dirty_background_ratio(表示佔用系統記憶體的百分比)引數的值為 10 以下。大部分應用場景下,vm.dirty_background_ratio設定為 5 就夠用了,要注意了:這個引數值不能設定為 0 ,因為設定為 0 後會引起核心持續刷“髒頁”,使得核心的buffer write功能沒法施展。

“髒頁”的總量可以通過vm.dirty_ratio 來改變,預設值是 20 (此處也是百分比),這個值的設定範圍較大,一般建議設定 60 到 80 為合理的值。但是vm.dirty_ratio 引數也引來了不小的風險,會造成大量unflush的資料在硬刷到磁碟時產生較長的I/O停頓。如果vm.dirty_ratio 值設定的較大時,強烈建議Kafka開啟備份功能,以備系統崩潰。

在設定了這些引數後,需要監控Kafka叢集執行時“髒頁”的數量,當前“髒頁”數量可由如下方式檢視(/proc/vmstat檔案):

 

1

2

3

 

# cat /proc/vmstat | egrep "dirty|writeback" nr_dirty 3875

nr_writeback 29

nr_writeback_temp 0

  • 磁碟

除了考慮磁碟硬體本身和RAID配置外,磁碟的filesystem對Kafka叢集的影響最大。雖然有許多filesystem,但最常用的是EXT4或者XFS。在這裡XFS檔案系統比EXT4稍好,具體原因Google下。

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

  • 網路

Linux釋出版本的網路引數對高網路流量不適用。對於Kafka叢集,推薦更改每個socket傳送和接收buffer的最大記憶體:net.core.wmem_default 和 net.core.rmem_default 為128 kb,net.core.wmem_max 和net.core.rmem_max 為 2 Mb。另外一個socket引數是TCP socket的傳送和接收buffer: net.ipv4.tcp_wmem 和 net.ipv4.tcp_rmem

Kafka叢集穩定

主要涉及到GC、資料中心佈局和ZK使用:

  • GC調優

調GC是門手藝活,幸虧Java 7引進了G1 垃圾回收,使得GC調優變的沒那麼難。G1主要有兩個配置選項來調優:MaxGCPauseMillisInitiatingHeapOccupancyPercent,具體引數設定可以參考Google,這裡不贅述。

Kafka broker能夠有效的利用堆記憶體和物件回收,所以這些值可以調小點。對於 64Gb記憶體,Kafka執行堆記憶體5Gb,MaxGCPauseMillisInitiatingHeapOccupancyPercent 分別設定為 20毫秒和 35。

Kafka的啟動指令碼使用的不是 G1回收,需要在環境變數中加入:

 

1

2

3

 

# export JAVA_HOME=/usr/java/jdk1.8.0_51

# export KAFKA_JVM_PERFORMANCE_OPTS="-server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+DisableExplicitGC -Djava.awt.headless=true"

# /usr/local/kafka/bin/kafka-server-start.sh -daemon /usr/local/kafka/config/server.properties

  • 資料中心佈局

原則上Kafka broker不建議都在一個機架上,為了容災,但現實情況大部分公司做不到,此處略去。

  • Zookeeper

Kafka叢集利用ZK來儲存broker、topic和partition的元資料資訊。

在Kafka 0.9.0之前,consumer利用ZK來直接儲存consumer group的資訊,包括topic的消費情況、每個partition消費的週期性commit。在0.9.0版本,提供新的consumer介面利用Kafka broker來管理。

Consumer可以選擇使用Zk或者Kafka來提交 offset和 提交間隔。如果consumer使用ZK管理offset,那每個consumer在每個partition的每個時間間隔寫入ZK。合理的offset提交間隔是1分鐘,但如果一個Kafka叢集有大量的consumer消費時,這個ZK流量將是巨大的。所以如果ZK不能處理大流量,那隻能把offset提交間隔設大,但同時也帶來丟資料的風險。最保險的建議是使用Kafka來提交offset。

另外,建議Kafka叢集不要和其他應用使用同一組ZK,因為Kafka對於ZK的延遲和超時是相當敏感的,ZK的不通將會導致Kafka的不可預測性。