准備工作
硬件:筆記本,windows10系統4核8G內存
軟件:接口測試工具,以及kafka自帶測試工具
影響測試結果配置分析
Borker
- num.network.thread=3
用於接收並處理網絡請求的線程數,默認為3。其內部實現是采用Selector模型。啟動一個線程作為Acceptor來負責建立連接,再配合啟動num.network.threads個線程來輪流負責從Sockets里讀取請求,一般無需改動,除非上下游並發請求量過大。
- num.partiton=1
Partition的數量選取也會直接影響到Kafka集群的吞吐性能。例如我們接口如果開了多個線程去消費kafka的數據,每個Partition對應一個Mapper去消費數據,如果Partition數量太少,則任務會因為Mapper數不足而非常慢。此外,當Partition數量相對於流入流出的數據量顯得較少,或由於業務邏輯和Partition數量沒有匹配好造成個別Partition讀寫數據量大,大量的讀寫請求集中落在一台或幾台機器上時就會很影響效率。
- Replica.lag.time.max.ms=10000
- Replica.lag.message=4000
- Num.replica.fetchers=1
對於任意(Broker, Leader)元組,都會有replication.factor-1個Broker作為Replica,在Replica上會啟動若干Fetch線程把對應的數據同步到本地,而num.replica.fetchers這個參數是用來控制Fetch線程的數量。
- Default.replication.factor=1
默認創建topic的時候創建replication-factor的數量。(這個相當於備份數據,每次producer發送消息會發送replication-factor的數目的消息,很影響效率,一般設置2-3個性能最好)同樣解決這個問題的辦法可以設置producer的屬性acks(0是生產不會等服務器返回結果,而會一直發送,會丟數據,但速度賊快;1是會等leader的partition返回結果值,有一定延遲但能保證數據不丟,all或者-1是會等所有副本都返回值,再繼續生產,延遲大,但保障性最好)
- Batch.size=16384
kafka會默認將發送到一個partiton的數據進行整合,這個大小是處理請求數據大小batch發送的,如果太小,可能就只能單獨請求發送消息給kafka。
Producer
使用新版本jar包(producer.client)下的producer進行發送數據(0.8版本上,我們現在使用的0.10版本)
Consumer
- num.consumer.fetchers=1
啟動consumer的個數,適度增加可以提高並發量
測試屬性之間關系
-
BrokerList和Replication和Partition之間的關系
BrokerList配置一個7000,partition為3,replication為1,開啟了7000,發送一條信息,得到的結果:在7000的生成3個partition文件夾,數據在其中一個partition文件夾中。
BrokerList配置多個7000、7001、7002,partition為3,replication為1,開啟7000,發送一條信息,得到的結果:在7000的生成3個partition文件夾,數據在其中一個partition文件夾中。
BrokerList配置多個7000、7001、7002,partition為3,replication為1,開啟7000、7001、7002,發送一條信息,得到結果:在7000上面生成1個文件夾,7001生成一個文件夾,7002生成一個文件夾,數據在7001文件夾中。
結論:當我們不配置replication-factor的時候,那么你向brokerList發送數據,kafka會自動根據你的partition生成不同的文件夾目錄,並且不會進行備份;同理我們配置了replication為3,開啟三個7000,7001,7002那么數據會自動備份,且只會在每個broker中生成三個partition文件夾。(我們配置spring文件的時候,brokerList只需要設置一個就可以,replication會自動幫我匹配已經開啟的節點作為follower進行備份,與配置中brokerList個數沒有關系,如果你配置了三個broker,那么還是其中一個作為leader進行寫入數據,其余兩個broker作為follower進行備份,而不會出現上面紅色字體情況)
-
Replication和acks之間的關系
100000條數據速度,replication-factor數據為3表示有兩個備份(時間單位毫秒)
| replication-factor=1 | repilication-factor=3 | Offset | |
| Acks=All/-1 | 29529 | 29524 | 具體值 |
| Acks=1 | 29498 | 27123 | 具體值 |
| Acks=0 | 9092 | 10468 | -1 |
結論:100000數據並沒有丟失,但是從時間上看,如果acks=0速度是最快的,但是不安全,我們寫回調監聽的時候返回的offset的數據為-1,表示我們並不知道它是否已經寫入kafka的文件夾中;如果設置acks為1,速度有一些慢,但是很安全,回調監聽函數會返回插入數據的offset對應具體值,表示我們已經知道他已經插入成功了;如果Acks=All(或者為-1)速度是最慢的,監聽器也會返回我們offset具體值,為什么它最慢效率最低,原因是這個參數設置為all表示kafka當配置了replication-factor的時候會follower會從leader中拉取數據作為備份,並告訴leader備份成功了,然后leader在告訴kafka我已經完成了kafka的寫入數據操作。與acks=1的差別,就是相差備份數據的完成過程。
-
BatchSize和發送數據之間的關系
發送100條數據,默認分區數為3(Partition為3)
當我們配置batchSize為默認值的時候(16384),監聽器返回的結果數據為:
- 先發送Partiton 0的數據(0,3,6,9....)
- 在發送Partition1的數據(1,4,7,10...)
- 最后發送Partition2的數據(2,5,8,11....)
修改batchSize配置為10,監聽器返回的數據結果為:
0,1,2,3,4.....(分別對應不同的partition)
結論:當我們設置batchSize數據適當的時候,kakfa-producer提交數據請求的時候會根據partiton進行數據整合,然后統一發送一個producer請求,如果設置的batchsize很小,那么每個寫入的都不滿足進行整合大小的條件,那么producer每次都會重新提交一個請求進行數據寫入。
-
Consumer數量和Partition之間的關系
我們開啟線程作為consumer,配置了三個了partiton0,partition1,partition2,發送了10個數據,看看數據分布:
Partition0:0,3,6,9 partition1:1,4,7 partition2:2,5,8
Consumer只有一個:Consumer的消費順序:0,3,6,9,2,5,8,1,4,7
結論,如果使用分區,不能保證數據順序,但是會保證每個partition的數據的順序
Consumer有兩個:Consumer-1消費:0,3,6,9,1;Consumer-2消費:2,5,8,4,7
結論:兩個會消費kafka分配給自己分區的數據,多於分區的數據會后消費,且共同消費剩余分區的。注:誰消費多誰消費少完全由消費者消費能力決定的。
Consumer有三個:Consumer-1 消費:0,3,6,9;Consumer-2 消費:1,4,7;Consumer-3 消費:2,5,8
結論:三個消費者分別消費不同分區的數據,並且不進行交互消費。
Consumer有四個:Consumer-1 消費:0,3,6,9;Consumer-2 消費:1,4,7;Consumer-3 消費:2,5,8;Consumer-4 消費:空
結論:消費者數量大於partition數量的時候,多余的consumer會作為空閑等待,除非有consumer掛掉。
定義消費者組group.id:當我們設置了消費者為消費者組group.id相同的時候,消費者組中多余的消費者會空閑等待,如果不是這個組的消費者掛掉,不會啟動這個消費者組中的消費者進行補充
結論:topic下的一個分區下的消息只能被同一個消費者組的中的一個消費者消費
所以綜上所述,consumer設置的個數要小於partition分區數,如果想要保證順序,那么不要使用分區,如果要保證並發數量並且使用分區,那么最好設置consumer的消費者數量和分區數量相等。
分區數確定算法:分區數=Tt/Max(Tp,Tc)
Tp:producer吞吐量 Tc:consumer吞吐量 Tt目標的吞吐量
-
Consumer和Rebalance之間的關系
如果topic1有0,1,2共三個Partition,當group1只有一個Consumer(名為consumer1)時,該 Consumer可消費這3個Partition的所有數據。如圖:

增加一個Consumer(consumer2)后,其中一個Consumer(consumer1)可消費2個Partition的數據(Partition 0和Partition 1),另外一個Consumer(consumer2)可消費另外一個Partition(Partition 2)的數據。

再增加一個Consumer(consumer3)后,每個Consumer可消費一個Partition的數據。consumer1消費partition0,consumer2消費partition1,consumer3消費partition2。

再增加一個Consumer(consumer4)后,其中3個Consumer可分別消費一個Partition的數據,另外一個Consumer(consumer4)不能消費topic1的任何數據。

此時關閉consumer1,其余3個Consumer可分別消費一個Partition的數據。

接着關閉consumer2,consumer3可消費2個Partition,consumer4可消費1個Partition。

再關閉consumer3,僅存的consumer4可同時消費topic1的3個Partition。

Consumer Rebalance的算法如下:
- 將目標Topic下的所有Partirtion排序,存於PT
- 對某Consumer Group下所有Consumer排序,存於CG,第i個Consumer記為Ci
- N=size(PT)/size(CG),向上取整
- 解除Ci對原來分配的Partition的消費權(i從0開始)
- 將第i∗N到(i+1)∗N−1個Partition分配給Ci
測試性能之間關系
-
Producer吞吐量
1.線程數
創建一個6個分區,沒有備份的topic,設置不同的線程數(server.properties中的配置num.network.thread)生產相同量的數據,查看性能變化。
執行命令:
(1)創建topic
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partition 6 --topic test-ref-1
(2)生產數據
kafka-producer-perf-test.bat --num-records 1000000 --topic test-ref-1 --record-size 200 --throughput 100000 --producer-props bootstrap.servers=localhost:7000
運行結果如下表所示:
| 操作 |
Topic |
線程數 |
Partition |
Replication |
Records/second |
MB/second |
| 1 |
test-ref-1 |
1 |
6 |
1 |
98286.5 |
18.746 |
| 2 |
test-ref-1 |
3 |
6 |
1 |
99946 |
19.06 |
| 3 |
test-ref-1 |
6 |
6 |
1 |
99946 |
19.06 |
初步結論:新版本測試工具可以設置吞吐量大小,所以效果不明顯,根據老版本測試是在分區一定的情況下,線程數小於分區數基礎上提高吞吐量。
2.分區數
創建兩個topic,一個分區數為3,一個分區數6,線程數相同然后生產相同數量的數據。
執行命令:
(1)創建topic
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partition 3 --topic test-ref-2
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partition 12 --topic test-ref-3
(2)生產數據
kafka-producer-perf-test.bat --num-records 1000000 --topic test-ref-2 --record-size 200 --throughput 100000 --producer-props bootstrap.servers=localhost:7000
kafka-producer-perf-test.bat --num-records 1000000 --topic test-ref-3 --record-size 200 --throughput 100000 --producer-props bootstrap.servers=localhost:7000
運行結果如下表所示:
| 操作 |
Topic |
線程數 |
Partition |
Replication |
Records/second |
MB/second |
| 1 |
test-ref-2 |
3 |
3 |
1 |
90903.3 |
17.34 |
| 2 |
test-ref-3 |
3 |
12 |
1 |
99297.9 |
18.94 |
初步結論:partition越多,吞吐量越大(但是根據網上結論,這個是有一定峰值,當達到峰值的時候,數量趨於平緩)如下圖:

3.備份數
創建兩個topic,一個備份數1,一個備份數3,單線程生產相同數量的數據。
執行命令:
(1)創建topic
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 2 --partition 3 --topic test-ref-4
(2)生產數據
kafka-producer-perf-test.bat --num-records 1000000 --topic test-ref-4 --record-size 200 --throughput 100000 --producer-props bootstrap.servers=localhost:7000
運行結果如下表所示:
| 操作 |
Topic |
線程數 |
Partition |
Replication |
Records/second |
MB/second |
| 1 |
test-ref-2 |
3 |
3 |
1 |
90903.3 |
17.34 |
| 2 |
test-ref-4 |
3 |
3 |
2 |
48962.2 |
9.34 |
初步結論:備份數越大,吞吐量越低。
4.Broker數
分兩次創建分區數大於1的topic:第一次開啟一個broker創建topic,並且發送數據,第二次開啟兩個broker創建topic,並發送數據。
執行命令:
(1)創建topic
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partition 3 --topic test-ref-5
(2)生產數據
kafka-producer-perf-test.bat --num-records 1000000 --topic test-ref-5 --record-size 200 --throughput 100000 --producer-props bootstrap.servers=localhost:7000
運行結果如下表所示:
| 操作 |
Topic |
線程數 |
Partition |
Replication |
Records/second |
MB/second |
| 1 |
test-ref-2 |
3 |
3 |
1 |
90903.3 |
17.34 |
| 2 |
test-ref-5 |
3 |
3 |
1 |
92539.5 |
17.65 |
初步結論:broke越多,吞吐量越大(但是效果不明顯-測試了broker為3和4的情況,並未截圖)
5.批處理大小
批處理大小引用他人測試,並未進行實測。
通過如下圖表查看測試結果:
| 操作 |
Bacth-size |
線程數 |
Partition |
Replication |
Records/second |
MB/second |
| 1 |
200 |
2 |
6 |
2 |
86491.7227 |
8.2485 |
| 2 |
1000 |
2 |
6 |
2 |
187594.7353 |
17.8904 |
| 3 |
2000 |
2 |
6 |
2 |
244479.6495 |
23.3154 |
| 4 |
3000 |
2 |
6 |
2 |
248172.2117 |
23.6675 |
| 5 |
4000 |
2 |
6 |
2 |
242217.5501 |
23.0997 |
| 6 |
5000 |
2 |
6 |
2 |
172405.4701 |
16.4419 |
關系折線圖如下:


初步結論:批處理在適當范圍內會使吞吐量增高,一定范圍內趨於平穩,大於峰值之后會減小吞吐量。
6.消息長度
消息大小引用他人測試,並未進行實測。
通過如下圖表查看測試結果:
| 操作 |
Bytes |
線程數 |
Records/second |
MB/second |
| 1 |
100 |
2 |
248172.2117 |
23.6675 |
| 2 |
200 |
2 |
132873.0610 |
25.3435 |
| 3 |
500 |
2 |
79277.1195 |
37.8023 |
| 4 |
1000 |
2 |
39015.5290 |
37.2081 |
關系折線圖如下:

初步結論:上面的所有測試都基於短消息(payload100字節),而正如上文所說,短消息對Kafka來說是更難處理的使用方式,可以預期,隨着消息長度的增大,records/second會減小,但MB/second會有所提高。下圖是records/second與消息長度的關系圖。(我們消息長度大約:650~800字節/每條訂單)
-
Consumer吞吐量
1.consumer數
創建Topic,分區數為6,線程數1,設置不同的consumer數量。
執行命令:
(1)創建topic
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partition 6 --topic test-ref-6
(2)生產數據
kafka-producer-perf-test.bat --num-records 1000000 --topic test-ref-6 --record-size 200 --throughput 100000 --producer-props bootstrap.servers=localhost:7000
(3)消費數據
kafka-consumer-perf-test.bat --messages 1000000 --threads 1 --zookeeper localhost:2181 --num-fetch-threads 1 --topic test-ref-6
kafka-consumer-perf-test.bat --messages 1000000 --threads 1 --zookeeper localhost:2181 --num-fetch-threads 3 --topic test-ref-6
kafka-consumer-perf-test.bat --messages 1000000 --threads 1 --zookeeper localhost:2181 --num-fetch-threads 6 --topic test-ref-6
kafka-consumer-perf-test.bat --messages 1000000 --threads 1 --zookeeper localhost:2181 --num-fetch-threads 12 --topic test-ref-6
運行結果如下表所示:
| 操作 |
Topic |
線程數 |
Partition |
Consumer |
Message/second |
MB/second |
| 1 |
test-ref-6 |
1 |
6 |
1 |
370644.9222 |
70.6949 |
| 2 |
test-ref-6 |
1 |
6 |
3 |
432900.4329 |
86.5692 |
| 2 |
test-ref-6 |
1 |
6 |
6 |
407664.0848 |
77.7558 |
| 2 |
test-ref-6 |
1 |
6 |
12 |
430663.2214 |
82.1425 |
初步結論:在partition一樣的時候,一個consumer-group中的consumer越多消費吞吐量越大,但是consumer數量到達和partition數量相同的時候那么消費者吞吐量不會增加。
2.consumer分區數
創建Topic,線程數1,consumer數量為3,設置不同的分區數量。
執行命令:
(1)創建topic
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partition 1 --topic test-ref-7
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partition 3 --topic test-ref-8
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partition 6 --topic test-ref-9
kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partition 12 --topic test-ref-10
(2)生產數據
kafka-producer-perf-test.bat --num-records 1000000 --topic test-ref-7 --record-size 200 --throughput 100000 --producer-props bootstrap.servers=localhost:7000
kafka-producer-perf-test.bat --num-records 1000000 --topic test-ref-8 --record-size 200 --throughput 100000 --producer-props bootstrap.servers=localhost:7000
kafka-producer-perf-test.bat --num-records 1000000 --topic test-ref-9 --record-size 200 --throughput 100000 --producer-props bootstrap.servers=localhost:7000
kafka-producer-perf-test.bat --num-records 1000000 --topic test-ref-10 --record-size 200 --throughput 100000 --producer-props bootstrap.servers=localhost:7000
(3)消費數據
kafka-consumer-perf-test.bat --messages 1000000 --threads 1 --zookeeper localhost:2181 --num-fetch-threads 3 --topic test-ref-7
kafka-consumer-perf-test.bat --messages 1000000 --threads 1 --zookeeper localhost:2181 --num-fetch-threads 3 --topic test-ref-8
kafka-consumer-perf-test.bat --messages 1000000 --threads 1 --zookeeper localhost:2181 --num-fetch-threads 3 --topic test-ref-9
kafka-consumer-perf-test.bat --messages 1000000 --threads 1 --zookeeper localhost:2181 --num-fetch-threads 3 --topic test-ref-10
運行結果如下表所示:
| 操作 |
Topic |
線程數 |
Partition |
Consumer |
Message/second |
MB/second |
| 1 |
test-ref-7 |
1 |
1 |
3 |
320410.1250 |
61.1134 |
| 2 |
test-ref-8 |
1 |
3 |
3 |
423908.4358 |
80.8541 |
| 3 |
test-ref-9 |
1 |
6 |
3 |
440528.6344 |
84.0242 |
| 4 |
test-ref-10 |
1 |
12 |
3 |
458505.2728 |
87.4529 |
初步結論:在consumer數量相同的時候,partition數量越大,吞吐量越高。但是partition數量大於255的時候producer發送速度和consumer消費速度慢的要死。(前提是consumer數量小於partition數,如果大於,有consumer閑置)
3.consumer數與分區數(消費接口)
Consumer-group下的consumer數越多消費效率越快,但是當大於topic分區數的時候有些consumer是休息狀態,具體看上面Consumer的數量和Partition之間的關系;由於本地只有一台機器無法模擬多個consumer消費的情況。
