1. 程式人生 > >kafka叢集基於可用性指標進行效能調優實踐-kafka 商業環境實戰

kafka叢集基於可用性指標進行效能調優實踐-kafka 商業環境實戰

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

1 掉下來一個可用性

  • 可用性反映了kafka叢集應對崩潰的能力,調優可用性就是為了讓Kafka更快的從崩潰中恢復過來。

2 Topic角度看問題

  • Controller就是broker,主要負責副本分配方案和分割槽上線的工作(根據副本的分配方案)。
  • 副本狀態機
  • 分割槽狀態機
  • 注意Topic的分割槽數越多,一旦分割槽的leader副本所在broker發生崩潰,就需要進行leader的選舉,雖然Leader的選舉時間很短,大概幾毫秒,但是Controller處理請求時單執行緒的,controller通過Zookeeper可實時偵測broker狀態。一旦有broker掛掉了,controller可立即感知併為受影響分割槽選舉新的leader,但是在新的分配方案出來後,釋出到各個broker進行元資料更新就要浪費網路I/O了。
  • 建議分割槽不要過大,可能會影響可用性。

3 Producer角度看問題

  • 首推引數是acks,當acks設定為all時,broker端引數min.insync.replicas的效果會影響Producer端的可用性。該引數越大,kafka會強制進行越多的follower副本同步寫入日誌,當出現ISR縮減到min.insync.replicas值時,producer會停止對特定分割槽傳送訊息,從而影響了可用性。
  • 版權宣告:本套技術專欄是作者(秦凱新)平時工作的總結和昇華,通過從真實商業環境抽取案例進行總結和分享,並給出商業應用的調優建議和叢集環境容量規劃等內容,請持續關注本套部落格。期待加入IOT時代最具戰鬥力的團隊。QQ郵箱地址:[email protected],如有任何學術交流,可隨時聯絡。

4 Broker角度看問題

  • Broker端高可用性直接的表現形式就是broker崩潰,崩潰之後leader選舉有兩種:1:從ISR中選擇。2:通過unclean.leader.election.enable值決定是否從ISR中選擇。第二種情況會出現資料丟失的風險。
  • 另一個引數是broker崩潰恢復調優,即num.recovery.threads.per.data.dir。場景是這樣的,當broker從崩潰中重啟恢復後,broker會掃描並載入底層的分割槽資料執行清理和與其他broker保持同步。這一工程被稱為日誌載入和日誌恢復。預設情況下是單執行緒的。假設某個Broker的log.dirs配置了10個日誌目錄,那麼單執行緒可能就吭哧吭哧掃描載入,太慢了。實際使用中,建議配置為日誌的log.dirs磁碟數量。

5 Consumer角度看問題

  • 對於Consumer而言,高可用性主要是基於組管理的consumer group來體現的,當group下某個或某些consumer例項“掛了”,group的coordinator能夠自動檢測出這種崩潰並及時的開啟rebalance,進而將崩潰的消費分割槽分配到其他存活的consumer上。

  • consumer端引數session.timeout.ms就是定義了能檢測出failure的時間間隔。若要實現高可用,必須設定較低的值,比如5-10秒。一旦超過該值,就會開啟新一輪的reblance。

  • 訊息處理時間引數很牛,max.poll.interval.ms,引數設定了consumer例項所需要的訊息處理時間,一旦超過該值,就是高負荷狀態,此時consumer將停止傳送心跳,並告知coordinator要離開group。消費者在建立時會有一個屬性max.poll.interval.ms
    該屬性意思為kafka消費者在每一輪poll()呼叫之間的最大延遲,消費者在獲取更多記錄之前可以空閒的時間量的上限。如果此超時時間期滿之前poll()沒有被再次呼叫,則消費者被視為失敗,並且分組將重新平衡,以便將分割槽重新分配給別的成員

  • hearbeat.interval.ms 當coordinator決定開啟新一輪的reblance時,他會把這個決定以REBALANCE_IN_PROCESS異常的形式塞進consumer心跳的請求響應中,這樣就可以飛快的感知到新的分割槽分配方案。

  • kafka調優經典的獨白,哈哈哈哈:

      上線兩個月都沒有問題,為什麼最近突然出現問題了。我想肯定是業務系統有什麼動作,我就去問了一個下,
      果然頭一天風控系統kafka掛掉了,並進行了資料重推,導致了資料阻塞。但是我又想即使阻塞了也會慢慢消費掉啊,不應
      該報錯呀。後來我看了一下kafka官網上的引數介紹,發現max.poll.records預設是2147483647 
      (0.10.0.1版本),也就是kafka裡面有多少poll多少,如果消費者拿到的這些資料在制定時間內消費不完,就會手動提交
      失敗,資料就會回滾到kafka中,會發生重複消費的情況。如此迴圈,資料就會越堆越多。後來諮詢了公司的kafka大神,他
      說我的kafka版本跟他的叢集版本不一樣讓我升級kafka版本。於是我就升級到了0.10.2.1,查閱官網發現這個版本的max.po
      ll.records預設是500,可能kafka開發團隊也意識到了這個問題。並且這個版本多了一個max.poll.interval.ms這個引數,
      預設是300s。這個引數的大概意思就是kafka消費者在一次poll內,業務處理時間不能超過這個時間。後來升級了kafka版本
      ,把max.poll.records改成了50個之後,上了一次線,準備觀察一下。上完線已經晚上9點了,於是就打卡回家了,明天看
      結果。第二天早起滿心歡喜準備看結果,以為會解決這個問題,誰曾想還是堆積。我的天,思來想去,也想不出哪裡有問題
      。於是就把處理各個業務的程式碼前後執行時間打印出來看一下,新增程式碼,提交上線。然後觀察結果,發現大部分時間都用
      在資料庫IO上了,並且執行時間很慢,大部分都是2s。於是想可能剛上線的時候資料量比較小,查詢比較快,現在資料量大
      了,就比較慢了。當時腦子裡第一想法就是看了一下常用查詢欄位有沒有新增索引,一看沒有,然後馬上新增索引。加完索
      引觀察了一下,處理速度提高了好幾倍。雖然單條業務處理的快樂, 
      但是堆積還存在,後來發現,業務系統大概1s推送3、4條資料,但是我kafka現在是單執行緒消費,速度大概也是這麼多。再
      加上之前的堆積,所以消費還是很慢。於是業務改成多執行緒消費,利用執行緒池,開啟了10個執行緒,上線觀察。幾分鐘就消費
      完了。大功告成,此時此刻,心裡舒坦了好多。不容易呀!
    

6 引數清單

Broker端

  • 避免過多分割槽
  • 設定unclean.leader.election.enable=true(為了可用性,資料丟失不考慮)
  • 設定min.insync.replicas=1(減輕同步壓力)
  • 設定num.recovery.threads.per.data.dir=broker 日誌的log.dirs磁碟數

Producer端

  • 設定acks=1,設定為all時,遵循min.insync.replicas=1

consumer端

  • 設定session.timeout.ms為較低的值,比如100000
  • 設定max.poll.interval.ms訊息平均處理時間,可適當調大。
  • 設定max.poll.records和max.partition.fetch.bytes減少訊息處理總時長,避免頻繁的rebalance。
  • 版權宣告:本套技術專欄是作者(秦凱新)平時工作的總結和昇華,通過從真實商業環境抽取案例進行總結和分享,並給出商業應用的調優建議和叢集環境容量規劃等內容,請持續關注本套部落格。期待加入IOT時代最具戰鬥力的團隊。QQ郵箱地址:[email protected],如有任何學術交流,可隨時聯絡。

7 總結

num.recovery.threads.per.data.dir以及max.partition.fetch.bytes以及max.poll.records重點關注一下,很有意思的選手。

秦凱新 於深圳 201812042237

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