kafka商業環境實戰系列
本套系列部落格從真實商業環境抽取案例進行總結和分享,並給出kafka商業應用的調優建議和叢集環境容量規劃等內容,請持續關注本套部落格。版權宣告:本套kafka調優系列版權歸作者(秦凱新)所有,禁止轉載,歡迎學習。
作者:秦凱新 地址:於深圳
1. Producer核心工作流程
- Producer首先使用使用者主執行緒將待傳送的訊息封裝進一個ProducerRecord類例項中。
- 進行序列化後,傳送給Partioner,由Partioner確定目標分割槽後,傳送到Producer程式中的一塊記憶體緩衝區中。
- Producer的另一個工作執行緒(即Sender執行緒),則負責實時地從該緩衝區中提取出準備好的訊息封裝到一個批次的內,統一傳送給對應的broker中。
2. producer 主要引數設定
2.1 producer 引數acks 設定(無資料丟失)
在訊息被認為是“已提交”之前,producer需要leader確認的produce請求的應答數。該引數用於控制訊息的永續性,目前提供了3個取值:
acks = 0: 表示produce請求立即返回,不需要等待leader的任何確認。這種方案有最高的吞吐率,但是不保證訊息是否真的傳送成功。
acks = -1: 表示分割槽leader必須等待訊息被成功寫入到所有的ISR副本(同步副本)中才認為produce請求成功。這種方案提供最高的訊息永續性保證,但是理論上吞吐率也是最差的。
acks = 1: 表示leader副本必須應答此produce請求並寫入訊息到本地日誌,之後produce請求被認為成功。如果此時leader副本應答請求之後掛掉了,訊息會丟失。這是個這種的方案,提供了不錯的永續性保證和吞吐。
商業環境推薦:
如果要較高的永續性要求以及無資料丟失的需求,設定acks = -1。其他情況下設定acks = 1
2.2 producer引數 buffer.memory 設定(吞吐量)
該引數用於指定Producer端用於快取訊息的緩衝區大小,單位為位元組,預設值為:33554432合計為32M。kafka採用的是非同步傳送的訊息架構,prducer啟動時會首先建立一塊記憶體緩衝區用於儲存待傳送的訊息,然後由一個專屬執行緒負責從緩衝區讀取訊息進行真正的傳送。
商業環境推薦:
- 訊息持續傳送過程中,當緩衝區被填滿後,producer立即進入阻塞狀態直到空閒記憶體被釋放出來,這段時間不能超過max.blocks.ms設定的值,一旦超過,producer則會丟擲TimeoutException 異常,因為Producer是執行緒安全的,若一直報TimeoutException,需要考慮調高buffer.memory 了。
- 使用者在使用多個執行緒共享kafka producer時,很容易把 buffer.memory 打滿。
2.3 producer引數 compression.type 設定(lZ4)
producer壓縮器,目前支援none(不壓縮),gzip,snappy和lz4。
商業環境推薦:
基於公司物聯網平臺,試驗過目前lz4的效果最好。當然2016年8月,FaceBook開源了Ztandard。官網測試: Ztandard壓縮率為2。8,snappy為2.091,LZ4 為2.101 。
2.4 producer引數 retries設定(注意訊息亂序,EOS)
producer重試的次數設定。重試時producer會重新傳送之前由於瞬時原因出現失敗的訊息。瞬時失敗的原因可能包括:後設資料資訊失效、副本數量不足、超時、位移越界或未知分割槽等。倘若設定了retries > 0,那麼這些情況下producer會嘗試重試。
商業環境推薦:
- producer還有個引數:max.in.flight.requests.per.connection。如果設定該引數大約1,那麼設定retries就有可能造成傳送訊息的亂序。
- 版本為0.11.1.0的kafka已經支援"精確到一次的語義”,因此訊息的重試不會造成訊息的重複傳送。
2.5 producer引數batch.size設定(吞吐量和延時效能)
producer都是按照batch進行傳送的,因此batch大小的選擇對於producer效能至關重要。producer會把發往同一分割槽的多條訊息封裝進一個batch中,當batch滿了後,producer才會把訊息傳送出去。但是也不一定等到滿了,這和另外一個引數linger.ms有關。預設值為16K,合計為16384.
商業環境推薦:
- batch 越小,producer的吞吐量越低,越大,吞吐量越大。
2.6 producer引數linger.ms設定(吞吐量和延時效能)
producer是按照batch進行傳送的,但是還要看linger.ms的值,預設是0,表示不做停留。這種情況下,可能有的batch中沒有包含足夠多的produce請求就被髮送出去了,造成了大量的小batch,給網路IO帶來的極大的壓力。
商業環境推薦:
- 為了減少了網路IO,提升了整體的TPS。假設設定linger.ms=5,表示producer請求可能會延時5ms才會被髮送。
2.7 producer引數max.in.flight.requests.per.connection設定(吞吐量和延時效能)
producer的IO執行緒在單個Socket連線上能夠傳送未應答produce請求的最大數量。增加此值應該可以增加IO執行緒的吞吐量,從而整體上提升producer的效能。不過就像之前說的如果開啟了重試機制,那麼設定該引數大於1的話有可能造成訊息的亂序。
商業環境推薦:
- 預設值5是一個比較好的起始點,如果發現producer的瓶頸在IO執行緒,同時各個broker端負載不高,那麼可以嘗試適當增加該值.
- 過大增加該引數會造成producer的整體記憶體負擔,同時還可能造成不必要的鎖競爭反而會降低TPS
結語
秦凱新 於深圳 2018-10-27