這是一篇關於 Kafka 實踐的文章,內容來自 DataWorks Summit/Hadoop Summit(Hadoop Summit)上的一篇分享,裏面講述了很多關於 Kafka 配置、監控、優化的內容,絕對是在實踐中總結出的精華,有很大的借鑑參考意義,本文主要是根據 PPT 的內容進行翻譯及適當補充。
Kafka 的架構這裏就不多做介紹了,直接步入正題。
Kafka 基本配置及性能優化
這裏主要是 Kafka 集羣基本配置的相關內容。
硬件要求
Kafka 集羣基本硬件的保證
OS 調優
OS page cache:應當可以緩存所有活躍的 Segment(Kafka 中最基本的數據存儲單位);
fd 限制:100k+;
禁用 swapping:簡單來說,swap 作用是當內存的使用達到一個臨界值時就會將內存中的數據移動到 swap 交換空間,但是此時,內存可能還有很多空餘資源,swap 走的是磁盤 IO,對於內存讀寫很在意的系統,最好禁止使用 swap 分區;
TCP 調優
JVM 配置
JDK 8 並且使用 G1 垃圾收集器
至少要分配 6-8 GB 的堆內存
Kafka 磁盤存儲
使用多塊磁盤,並配置爲 Kafka 專用的磁盤;
JBOD vs RAID10;
JBOD(Just a Bunch of Disks,簡單來說它表示一個沒有控制軟件提供協調控制的磁盤集合,它將多個物理磁盤串聯起來,提供一個巨大的邏輯磁盤,數據是按序存儲,它的性能與單塊磁盤類似)
JBOD 的一些缺陷:
任何磁盤的損壞都會導致異常關閉,並且需要較長的時間恢復;
數據不保證一致性;
多級目錄;
社區也正在解決這麼問題,可以關注 KIP 112、113:
必要的工具用於管理 JBOD;
自動化的分區管理;
磁盤損壞時,Broker 可以將 replicas 遷移到好的磁盤上;
在同一個 Broker 的磁盤間 reassign replicas;
RAID 10 的特點:
可以允許單磁盤的損壞;
性能和保護;
不同磁盤間的負載均衡;
高命中來減少 space;
單一的 mount point;
文件系統:
使用 EXT 或 XFS;
SSD;
基本的監控
Kafka 集羣需要監控的一些指標,這些指標反應了集羣的健康度。
CPU 負載;
Network Metrics;
File Handle 使用;
磁盤空間;
磁盤 IO 性能;
GC 信息;
ZooKeeper 監控。
Kafka replica 相關配置及監控
Kafka Replication
-
Partition 有兩種副本:Leader,Follower;
-
Leader 負責維護 in-sync-replicas(ISR)
-
replica.lag.time.max.ms
:默認爲10000,如果 follower 落後於 leader 的消息數超過這個數值時,leader 就將 follower 從 isr 列表中移除; -
num.replica.fetchers
,默認爲1,用於從 leader 同步數據的 fetcher 線程數; -
min.insync.replica
:Producer 端使用來用於保證 Durability(持久性);
-
Under Replicated Partitions
當發現 replica 的配置與集羣的不同時,一般情況都是集羣上的 replica 少於配置數時,可以從以下幾個角度來排查問題:
-
JMX 監控項:kafka.server:type=ReplicaManager,name=UnderReplicatedPartitions;
-
可能的原因:
-
Broker 掛了?
-
Controller 的問題?
-
ZooKeeper 的問題?
-
Network 的問題?
-
-
解決辦法:
-
調整 ISR 的設置;
-
Broker 擴容。
-
Controller
-
負責管理 partition 生命週期;
-
避免 Controller’s ZK 會話超時:
-
ISR 抖動;
-
ZK Server 性能問題;
-
Broker 長時間的 GC;
-
網絡 IO 問題;
-
-
監控:
-
kafka.controller:type=KafkaController,name=ActiveControllerCount,應該爲1;
-
LeaderElectionRate。
-
Unclean leader 選舉
允許不在 isr 中 replica 被選舉爲 leader。
-
這是 Availability 和 Correctness 之間選擇,Kafka 默認選擇了可用性;
-
unclean.leader.election.enable
:默認爲 true,即允許不在 isr 中 replica 選爲 leader,這個配置可以全局配置,也可以在 topic 級別配置; -
監控:kafka.controller:type=ControllerStats,name=UncleanLeaderElectionsPerSec。
Broker 配置
Broker 級別有幾個比較重要的配置,一般需要根據實際情況進行相應配置的:
-
log.retention.{ms, minutes, hours}
,log.retention.bytes
:數據保存時間; -
message.max.bytes
,replica.fetch.max.bytes
; -
delete.topic.enable
:默認爲 false,是否允許通過 admin tool 來刪除 topic; -
unclean.leader.election.enable
= false,參見上面; -
min.insync.replicas
= 2:當 Producer 的 acks 設置爲 all 或 -1 時,min.insync.replicas
代表了必須進行確認的最小 replica 數,如果不夠的話 Producer 將會報NotEnoughReplicas
或NotEnoughReplicasAfterAppend
異常; -
replica.lag.time.max.ms
(超過這個時間沒有發送請求的話,follower 將從 isr 中移除), num.replica.fetchers; -
replica.fetch.response.max.bytes
; -
zookeeper.session.timeout.ms
= 30s; -
num.io.threads
:默認爲8,KafkaRequestHandlerPool 的大小。
Kafka 相關資源的評估
集羣評估
-
Broker 評估
-
每個 Broker 的 Partition 數不應該超過2k;
-
控制 partition 大小(不要超過25GB);
-
-
集羣評估(Broker 的數量根據以下條件配置)
-
數據保留時間;
-
集羣的流量大小;
-
-
集羣擴容:
-
磁盤使用率應該在 60% 以下;
-
網絡使用率應該在 75% 以下;
-
-
集羣監控
-
保持負載均衡;
-
確保 topic 的 partition 均勻分佈在所有 Broker 上;
-
確保集羣的階段沒有耗盡磁盤或帶寬。
-
Broker 監控
-
Partition 數:kafka.server:type=ReplicaManager,name=PartitionCount;
-
Leader 副本數:kafka.server:type=ReplicaManager,name=LeaderCount;
-
ISR 擴容/縮容率:kafka.server:type=ReplicaManager,name=IsrExpandsPerSec;
-
讀寫速率:Message in rate/Byte in rate/Byte out rate;
-
網絡請求的平均空閒率:NetworkProcessorAvgIdlePercent;
-
請求處理平均空閒率:RequestHandlerAvgIdlePercent。
Topic 評估
-
partition 數
-
Partition 數應該至少與最大 consumer group 中 consumer 線程數一致;
-
對於使用頻繁的 topic,應該設置更多的 partition;
-
控制 partition 的大小(25GB 左右);
-
考慮應用未來的增長(可以使用一種機制進行自動擴容);
-
-
使用帶 key 的 topic;
-
partition 擴容:當 partition 的數據量超過一個閾值時應該自動擴容(實際上還應該考慮網絡流量)。
合理地設置 partition
-
根據吞吐量的要求設置 partition 數:
-
假設 Producer 單 partition 的吞吐量爲 P;
-
consumer 消費一個 partition 的吞吐量爲 C;
-
而要求的吞吐量爲 T;
-
那麼 partition 數至少應該大於 T/P、T/C 的最大值;
-
-
更多的 partition,意味着:
-
更多的 fd;
-
可能增加 Unavailability(可能會增加不可用的時間);
-
可能增加端到端的延遲;
-
client 端將會使用更多的內存。
-
Partition 的增加將會帶來以下幾個優點和缺點:
-
增加吞吐量:對於 consumer 來說,一個 partition 只能被一個 consumer 線程所消費,適當增加 partition 數,可以增加 consumer 的併發,進而增加系統的吞吐量;
-
需要更多的 fd:對於每一個 segment,在 broker 都會有一個對應的 index 和實際數據文件,而對於 Kafka Broker,它將會對於每個 segment 每個 index 和數據文件都會打開相應的 file handle(可以理解爲 fd),因此,partition 越多,將會帶來更多的 fd;
-
可能會增加數據不可用性(主要是指增加不可用時間):主要是指 broker 宕機的情況,越多的 partition 將會意味着越多的 partition 需要 leader 選舉(leader 在宕機這臺 broker 的 partition 需要重新選舉),特別是如果剛好 controller 宕機,重新選舉的 controller 將會首先讀取所有 partition 的 metadata,然後才進行相應的 leader 選舉,這將會帶來更大不可用時間;
-
可能增加 End-to-end 延遲:一條消息只有其被同步到 isr 的所有 broker 上後,才能被消費,partition 越多,不同節點之間同步就越多,這可能會帶來毫秒級甚至數十毫秒級的延遲;
-
Client 將會需要更多的內存:Producer 和 Consumer 都會按照 partition 去緩存數據,每個 partition 都會帶來數十 KB 的消耗,partition 越多, Client 將會佔用更多的內存。
Producer 的相關配置、性能調優及監控
Quotas
-
避免被惡意 Client 攻擊,保證 SLA;
-
設置 produce 和 fetch 請求的字節速率閾值;
-
可以應用在 user、client-id、或者 user 和 client-id groups;
-
Broker 端的 metrics 監控:throttle-rate、byte-rate;
-
replica.fetch.response.max.bytes
:用於限制 replica 拉取請求的內存使用; -
進行數據遷移時限制貸款的使用,
kafka-reassign-partitions.sh -- -throttle option
。
Kafka Producer
-
使用 Java 版的 Client;
-
使用
kafka-producer-perf-test.sh
測試你的環境; -
設置內存、CPU、batch 壓縮;
-
batch.size:該值設置越大,吞吐越大,但延遲也會越大;
-
linger.ms:表示 batch 的超時時間,該值越大,吞吐越大、但延遲也會越大;
-
max.in.flight.requests.per.connection
:默認爲5,表示 client 在 blocking 之前向單個連接(broker)發送的未確認請求的最大數,超過1時,將會影響數據的順序性; -
compression.type
:壓縮設置,會提高吞吐量; -
acks
:數據 durability 的設置;
-
-
避免大消息
-
會使用更多的內存;
-
降低 Broker 的處理速度;
-
性能調優
-
如果吞吐量小於網絡帶寬
-
增加線程;
-
提高 batch.size;
-
增加更多 producer 實例;
-
增加 partition 數;
-
-
設置 acks=-1 時,如果延遲增大:可以增大
num.replica.fetchers
(follower 同步數據的線程數)來調解; -
跨數據中心的傳輸:增加 socket 緩衝區設置以及 OS tcp 緩衝區設置。
Prodcuer 監控
-
batch-size-avg
-
compression-rate-avg
-
waiting-threads
-
buffer-available-bytes
-
record-queue-time-max
-
record-send-rate
-
records-per-request-avg
Kafka Consumer 配置、性能調優及監控
Kafka Consumer
-
使用
kafka-consumer-perf-test.sh
測試環境; -
吞吐量問題:
-
partition 數太少;
-
OS page cache:分配足夠的內存來緩存數據;
-
應用的處理邏輯;
-
-
offset topic(
__consumer_offsets
)-
offsets.topic.replication.factor
:默認爲3; -
offsets.retention.minutes
:默認爲1440,即 1day;
– MonitorISR,topicsize;
-
-
offset commit較慢:異步 commit 或 手動 commit。
Consumer 配置
-
fetch.min.bytes
、fetch.max.wait.ms
; -
max.poll.interval.ms
:調用poll()
之後延遲的最大時間,超過這個時間沒有調用poll()
的話,就會認爲這個 consumer 掛掉了,將會進行 rebalance; -
max.poll.records
:當調用poll()
之後返回最大的 record 數,默認爲500; -
session.timeout.ms
; -
Consumer Rebalance
– check timeouts
– check processing times/logic
– GC Issues -
網絡配置;
Consumer 監控
Consumer 是否跟得上數據的發送速度。
-
Consumer Lag:consumer offset 與 the end of log(partition 可以消費的最大 offset) 的差值;
-
監控
-
metric 監控:records-lag-max;
-
通過
bin/kafka-consumer-groups.sh
查看; -
用於 consumer 監控的 LinkedIn’s Burrow;
-
-
減少 Lag
-
分析 consumer:是 GC 問題還是 Consumer hang 住了;
-
增加 Consumer 的線程;
-
增加分區數和 consumer 線程;
-
如何保證數據不丟
這個是常用的配置:
-
Producer
-
block.on.buffer.full=true
-
retries=Long.MAX_VALUE
-
acks=all
-
max.in.flinght.requests.per.connection=1
-
close producer
-
-
Broker
-
relication factor >= 3
-
min.insync.replicas=2
-
disable unclean leader election
-
-
Consumer
-
min.insync.replicas=2
-
disable auto.buffer.full=true
-
disable auto.buffer.full=true
-
commit offsets only after the message are processed
-
-
block.on.buffer.full
:默認設置爲 false,當達到內存設置時,可能通過 block 停止接受新的 record 或者拋出一些錯誤,默認情況下,Producer 將不會拋出 BufferExhaustException,而是當達到max.block.ms
這個時間後直接拋出 TimeoutException。設置爲 true 的意義就是將max.block.ms
設置爲 Long.MAX_VALUE,未來版本中這個設置將被遺棄,推薦設置max.block.ms
。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
考慮一千次,不如去做一次;猶豫一萬次,不如實踐一次;華麗的跌倒,勝過無謂的彷徨,將來的你,一定會感謝現在奮鬥的你。歡迎大家加入大數據交流羣:725967421 一起交流,一起進步!!
------------------------------------------------------------------------------------------------------------------------------------------------------------------------