在技術架構體系中非常多的場景會使用到消息隊列,Kafka作為最常用的消息中間件,以高性能低延遲高可用的特性備受程式員和架構師的青睐。了解kafka的原理是使用kafka的入門基礎,要想用的好kafka更需要有一些規範來限制。本文将從kafka叢集配置、生産者、消費者三方面來說一下個人認為應該指向的規範。
叢集配置
CPU、記憶體、磁盤、網絡是影響伺服器性能的主要因素。
CPU
由于生産者會對消息的資料進行壓縮,是以服務端接收消息之後需要解壓縮并設定偏移量後重新壓縮,最後消費者收到資料後再解壓縮。對于CPU而言當然越多的CPU核心約好。但是要注意不要造成浪費。
記憶體
Kafka的Borker收到生産者的消息之後是先寫入作業系統的Page Cache,當Page Cache達到一定大小或者是定時同步PageCache到磁盤檔案。是以Kafka的Borker不能與其他重要通用依賴作業系統PageCache的程式(比如ES)部署在一起,否則将會影響頁緩存互相影響性能。
磁盤
生産者必須等到一個Borker确認消息成功之後送出才結束,如果服務端IO磁盤吞吐跟不上,意味着生産者并發不會高。另外磁盤大小又決定的kafka叢集的資料存儲量。是以如果追求極緻性能建議直接上SSD。如果對叢集的存儲量有要求,建議上大容量磁盤。
多個分區也可位于同一台伺服器上,這樣可以在同一台伺服器上使用不同的分區對應不同的磁盤,實作磁盤間的并行處理
server.properties 檔案的log.dirs = 可以指定多個目錄。
是以一般可以通過增加分區的數量來提高系統的并行吞吐量。
網絡
網絡的吞吐量決定這Kafka的叢集處理和消費資料上限,有條件可以直接上萬兆網卡。
ZK叢集
zk叢集的高可用對于Kafka叢集而言是十分重要的。是以建議zk叢集建議使用5節點叢集,并且最好是實體節點。
叢集分類管理
叢集可以按照使用場景分類,将叢集分為三大類,線上業務,點選流,服務端日志三大類:
線上業務:主要是服務間解耦場景,如:資源池、短信、郵件消息等
點選流:通過采集系統收的日志或者自行上報的使用者行為相關日志,如:移動app日志,各種使用者點選日志等
服務端日志:服務端産生的程式日志,如:IIS日志、nginx日志,容器日志,服務應用自身監控日志等。
叢集權限管理
叢集的的消費管理最好開啟權限通路管理,如果要消費叢集的topic,需要申請相關權限,在消費端配置client.id 來辨別。
叢集調優
Kafka 叢集安裝部署完畢後,可以根據情況對以下配置進行調優:
num.partitions: 預設分區數配置
log.retention.ms: 資料最多保留的時間,根據 業務與資料情況、可用磁盤容量 設定資料最多保留的時間期限
log.segment.bytes: 資料片段的滾動大小,太小将會頻繁寫檔案,太大将會影響日志過期
log.segment.ms: 日志片段的過期時間
message.max.bytes: 單條消息最大的大小,預設1M
生産者
選用合适的Topic
對生産者而言,每一個分區的資料寫入是完全可以并行化的;但是,對消費者而言,kafka隻允許單個分區中的消息被一個消費者線程消費,一個消費組的消費并行度完全依賴于所消費的分區數。
實際情況是随着分區的增長,相應的吞吐量也跟着上漲,一旦分區數超過了某個門檻值後,整體的吞吐量是不升反降的,也就是說,并不是分區數越多,吞吐量就越大。
标準方法:建立一個隻有1個分區的topic,然後測試這個topic的producer吞吐量和consumer吞吐量。假設它們的值分别是Tp和Tc,機關可以是MB/s。然後假設總的目标吞吐量是Tt,那麼分區數 = Tt / max(Tp, Tc)
簡單方法:設定為叢集中伺服器中數量的1倍或者2倍。
1、副本數推薦設定 3 副本,同步複制。主要為了保證分區的高可用,以避免機器故障導緻資料丢失。
2、分區數量與Kafka的消費者的處理能力是強關聯的,是以根據自己系統的量級以及場景選擇合适的分區數,單topic最大分區數建議為10,以下為消息數量以及分區數的推薦設定
消息數量 | 分區數 |
100萬 | 1~3 |
500~700萬 | 3~ 5 |
1000+萬 | 7~8 |
1+億 | 10+ |
* 分區數後期可以申請新增,但是不支援縮減
* 如果對資料的順序性有要求 ,選擇一個分區
3、保留時長:保留的周期,一般填寫168h(7天)。資料量大的情況,可填寫更短的時間(如3天),不建議填寫超過7天。
4、Topic命名規範建議:Topic_業務名/業務表名,使用英文字母統一小寫短橫杠"-"以下劃線代替 " _ "。
正确的程式配置
1、生産或者消費過程中,client包應該與kafka叢集版本保持一緻,避免出現版本相容問題及kafka性能問題。
2、kafkaboostrap.servers配置項需配置多個ip 或者多個域名的連接配接位址(3個為最低标準)。
3、producer保證發送的資料同步複制,避免資料丢失。但是要注意使用ack=all,可也會降低寫入的吞吐量及其他可能的異常情況。
6、producer使用批量寫入方式可以顯著提高寫入吞吐量,并減少與kafka broker的通信次數,具體設定為
buffer.memory: 生産者緩沖區大小
batch.size: 一個批次的資料位元組大小,太大占用緩沖區多,但是不會延遲(有其他觸發機制)而 太小會頻繁送出消息效率低下
linger.ms: 發送批次前等待的時間,時間到會觸發批次資料的送出,太大延遲高但吞吐高,太小延遲低但頻率高開銷大
reties: 送出失敗重試次數
max.in.flight.requests.per.connection: 生産者受到伺服器響應之前還可以發送多少消息,設定為1可以保證消息是順序寫入的(即使失敗重試),太大記憶體使用高但是吞吐高,不會因為服務端而阻塞
compression.type: snappy/gzip/lz4可選,推薦 少CPU,高成本效益的snappy
7、producer的JVM記憶體要足夠,避免記憶體不足導緻發送阻塞
8、producer消息大小,最好不要超過1M,最大不能超過預設10MB。
消費端
1、consumer數量并不是越多越好,超過topic分區數,會有consumer拉取不到消息。如果低于consumer數量,則會有的consumer消費多個分區的消息。
2、消費者可以設定
poll
方法擷取資料的 上限和下限:
上限:設定一次最多可以拿多少條資料,避免用戶端記憶體不夠導緻發送OOM
下限:設定至少有多少資料時才傳回給用戶端,避免幾ms就發一次請求,每次隻擷取少量資料的情況,減少請求量提升效率。
fetch.min.bytes: 消費者從 Broker 最小拉取的位元組數,調大可以降低負載、提高吞吐
fetch.max.wait.ms: 消費者從 Broker 拉取資料時最大的等待機關,太大會提高延遲,拉取資料時要麼滿足 位元組數 要麼滿足 等待時間。
3、auto.offset.reset: 讀取沒有偏移量的分區時如何處理,
lastest:從最新記錄開始(預設)
earliest:從頭
4、使用正确的消費者模式大多數場景下我們需要手工送出偏移量
設定enable.auto.commit=false, 此時需要注意如果程式報異常,消費者将會堵塞。
5、consumer拉取消息處理下遊邏輯,需評估poll與server的心跳時間範圍,避免心跳逾時,導緻consumer頻繁加入和退出,阻塞消費。
session.timeout.ms: 消費者端發送心跳的逾時時間(預設3s)可以設定為30s,調高可以 避免gc等情況下觸發的rebalance,容錯時間長,太低可能導緻容錯時間短,可能會觸發不必要的rebalance
6、Kafka不能保證消費重複的消息,業務側需保證消息處理的幂等性。
最近在整理一份面試資料,覆寫Java核心技術、架構、中間件,架構等。擷取方式:關注公衆号并回複 面試 領取,更多内容陸續奉上。