引言
前幾期的評測中,我們對比了Kafka和RocketMQ的吞吐量和穩(wěn)定性,本期我們要引入一個新的評測標準——軟件可靠性。
先看下面這種情況:有A,B兩輛越野汽車,在城市的周邊地區(qū)均能很好應(yīng)對泥濘的路況。當一同開去穿越西藏,A車會因為西藏本地的汽油不達標,導(dǎo)致油路受阻無法點火,而B車順利完成了穿越。因此我們說,B車的可靠性比A車高。
“軟件的可靠性”就是考察軟件在各種異常突發(fā)的情況下的應(yīng)對能力。常見的軟件異常有:磁盤損壞、進程意外退出、宿主機宕機等情況。
對于消息中間件來說,“可靠性”最直接的指標就是——消息數(shù)據(jù)不丟失。此外,消息不重投、服務(wù)一主多備等特性也可以用來評估可靠性。
那么Kafka和RocketMQ(以下簡稱RMQ)在可靠性上孰優(yōu)孰劣呢?和我們走進本期的測試比拼吧!
測試目的
在消息收發(fā)的過程中,分別模擬Broker服務(wù)進程被Kill、物理機器掉電的異常場景,多次實驗,查看極端情況下消息系統(tǒng)的可靠性。
測試場景
以下場景使用多個發(fā)送端向一個Topic發(fā)送消息,發(fā)送方式為同步發(fā)送,分區(qū)數(shù)為8,只啟動一個訂閱者。
場景1. 模擬進程退出
在消息收發(fā)過程中,利用Kill -9 命令使Broker進程終止,然后重新啟動,得到可靠性數(shù)據(jù)如下:

注:以上測試場景中Kafka的異步刷盤間隔為1秒鐘,同步發(fā)送需設(shè)置request.required.acks=1,否則會出現(xiàn)消息丟失。
在Broker進程被終止重啟,Kafka和RMQ都能保證同步發(fā)送的消息不丟,因為進程退出后操作系統(tǒng)能確保將該進程遺留在內(nèi)存的數(shù)據(jù)刷到磁盤上。實驗中,Kafka出現(xiàn)了極少量的消息重復(fù)。再次可以確定此場景中,二者的可靠性都很高。
場景2. 模擬機器掉電
在消息收發(fā)過程中,直接拔掉Broker所在的宿主機電源,然后重啟宿主機和Broker應(yīng)用。因受到機房斷電限制,我們在本場景測試中使用的是普通PC機器。得到可靠性數(shù)據(jù)如下:

測試發(fā)現(xiàn),即使在并發(fā)很低的情況下,Kafka和RMQ都無法保證掉電后不丟消息。這個時候,就需要改變刷盤策略了。我們把刷盤策略由“異步刷盤”變更為“同步刷盤”,就是說,讓每一條消息都完成存儲后才返回,以保證消息不丟失。
注:關(guān)于兩種刷盤模式的詳細區(qū)別可以參照文檔最下方的說明
重新執(zhí)行上面的測試,得到數(shù)據(jù)如下:

首先,設(shè)置同步刷盤時,二者都沒出現(xiàn)消息丟失的情況。限于我們使用的是普通PC機器,兩者吞吐量都不高。此時Kafka的最高TPS僅有500條/秒,RMQ可以達到4000條/秒,已經(jīng)是Kafka的8倍。
為什么Kafka的吞吐量如此低呢?因為Kafka本身是沒有實現(xiàn)任何同步刷盤機制的,就是說在這種場景下測試,Kafka注定是要丟消息的。但要想做到每一條消息都在落盤后才返回,我們可以通過修改異步刷盤的頻率來實現(xiàn)。設(shè)置參數(shù)log.flush.interval.messages=1,即每條消息都刷一次磁盤。這樣的做法,Kafka也不會丟消息了,但是頻繁的磁盤讀寫直接導(dǎo)致性能的下降。
另外,二者在服務(wù)恢復(fù)后,均出現(xiàn)了消息重復(fù)消費的情況,這說明消費位點的提交并不是同步落盤的。不過,幸好Kafka和RMQ都提供了自定義消費位點的接口,來避免大量的重復(fù)消費。
測試結(jié)論
- 在Broker進程被Kill的場景, Kafka和RocketMQ都能在保證吞吐量的情況下,不丟消息,可靠性都比較高。
- 在宿主機掉電的場景,Kafka與RocketMQ均能做到不丟消息,此時Kafka的吞吐量會急劇下跌,幾乎不可用。RocketMQ則仍能保持較高的吞吐量。
- 在單機可靠性方面,RocketMQ綜合表現(xiàn)優(yōu)于Kafka。
附錄:
測試環(huán)境
服務(wù)端為單機部署,機器配置如下:

應(yīng)用版本:

測試腳本

同步刷盤和異步刷盤的區(qū)別

同步刷盤是在每條消息都確認落盤了之后才向發(fā)送者返回響應(yīng);而異步刷盤中,只要消息保存到Broker的內(nèi)存就向發(fā)送者返回響應(yīng),Broker會有專門的線程對內(nèi)存中的消息進行批量存儲。所以異步刷盤的策略下,當機器突然掉電時,Broker內(nèi)存中的消息因無法刷到磁盤導(dǎo)致丟失。
|