做者 | RocketMQ社區
來源|阿里巴巴雲原生公衆號git
「童年的雨天最是泥濘,倒是記憶裏最乾淨的曾經。凜冬散盡,星河長明,新的一年,萬事順遂,再見,2020!」github
走過這個歲末,萬衆期待的 Apache RocketMQ 4.8.0 終於發佈了,在這個版本中社區對 RocketMQ 完成大量的優化和問題修復。更重要的是,該版本從性能、穩定性、功能三個方面大幅度提高 DLedger 模式能力。apache
DLedger 是 OpenMessaging 中一個基於 Raft 的 CommitLog 存儲庫實現,從 RocketMQ 4.5.0 版本開始,RocketMQ 引入 DLedger 模式來解決了 Broker 組內自動故障轉移的問題,而在 4.8.0 版本中社區也對 RocketMQ DLedger 模式進行了全面升級。緩存
RocketMQ 4.7.0 從新升級了同步雙寫的架構,利用異步化 pipeline 模式大幅提高了同步雙寫的性能。在 RocketMQ 4.8.0 中,社區將這一改進應用到 DLedger 模式中, 下圖展現了 DLedger 模式下 broker 處理髮送消息的過程。在本來的架構中, SendMessageProcessor 線程對每個消息的處理,都須要等待多數派複製成功確認,纔會返回給客戶端,而在新版本中,利用 CompletableFuture 對線程處理消息的過程進行異步化改造,再也不等待多數派的確認便可對下一個請求進行處理,Ack 操做由其餘線程確認以後再進行結果處理並返回給客戶端。經過對複製過程進行切分並將其流水線化,減小線程的長時間等待,充分利用 CPU,從而大幅提升吞吐量。性能優化
Batch 一直是性能優化的重要方式,在新版本中,能夠經過設置 isEnableBatchPush=true 來開啓 DLedger 模式的批量複製。經過將多條數據聚合在一個包中進行發送,能夠下降收發包的個數,從而下降系統調用和上下文的切換。在數據發送壓力比較大,而且可能達到系統收發包瓶頸的狀況下,批量複製能顯著提升吞吐量。值得注意的是,DLedger 模式下的批量複製並不會對單個包進行延時的攢批處理,所以不會影響單個消息的發送時延。網絡
除了上述的性能優化,社區還對 DLedger 模式下影響性能的鎖、緩存等作了數項性能優化,使 DLedger 模式下的性能提高數倍。架構
爲了驗證和測試 Dledger 模式的可靠性,除了本地對 DLedger 模式進行了各類各樣的測試,社區利用 OpenMessaging-Chaos 框架對 RocketMQ DLedger 模式進行了大量 Chaos 測試。OpenMessaging-Chaos 是一個利用故障注入來驗證各類消息平臺一致性和高可用性的測試框架,在 OpenMessaging-Chaos 的測試中,客戶端併發地向待測試集羣發送和接收消息,中間會間隔性地對集羣進行故障注入,最後給出測試結果,包括是否丟消息,是否有重複消息,集羣平均故障恢復時間等。利用 OpenMessaging-Chaos,咱們驗證了 DLedger 模式在如下故障注入場景下的表現:併發
random-partition(fixed-partition)故障隨機挑選節點進行網絡隔離,模擬常見的對稱網絡分區。框架
random-loss 故障隨機挑選節點並對這些節點接收和發送的網絡包進行按比例丟棄,模擬一些節點網絡較差的狀況。dom
random-kill(minor-kill、major-kill、fixed-kill)故障模擬常見的進程崩潰狀況。
random-suspend(minor-suspend、major-suspend、fixed-suspend)故障模擬一些慢節點的狀況,好比發生 Full GC、OOM 等。
以 minor-kill 故障注入爲例,咱們部署 5 個節點組成一組 DLedger 模式的 RocketMQ broker 進行 Chaos 測試。minor-kill 故障注入會隨機挑選集羣中少數節點進程殺死,因爲殺死少數節點,即便集羣不可用也能在一段時間內恢復,方便測試集羣平均故障恢復時間。
測試過程當中咱們設置四個客戶端併發向 RocketMQ DLedger 集羣發送和接收消息,故障注入時間間隔爲 100s,即 100s 正常運行,100s 故障注入,一直循環,整個階段一共持續 2400s。測試結束後,OpenMessaging-Chaos 會給出測試結果和時延圖。下圖展現了整個測試過程當中入隊操做的時延狀況。
圖中縱座標是是時延,橫座標是測試時間,綠色框表示數據發送成功,紅色框表示數據發送失敗,藍色框表示不肯定是否數據添加成功,灰色部分表示故障注入的時間段。能夠看出一些故障注入時間段形成了集羣短暫的不可用,一些故障時間段則沒有,這是合理的。因爲是隨機網絡分區,因此只有殺死的少數節點包含 leader 節點時纔會形成集羣從新選舉,但即便形成集羣從新選舉, DLedger 模式在一段時間後也會恢復可用性。
下圖是測試結束後 OpenMessaging-Chaos 給出的統計結果,能夠看到一共成功發送了 11W 個數據,沒有數據丟失,這代表即便在故障下,RocketMQ DLedger 模式仍舊知足 At Least Once 的投遞語義。此外,RTOTestResult 代表 12 次故障時間段一共發生了 3 次集羣不可用的狀況(與上述時延圖一致),但每次集羣都能在 30 秒之內恢復,平均故障恢復時間在 22 秒左右。
在 OpenMessaging Chaos 測試過程當中,咱們發現了 DLedger 模式存在的數個隱性問題並進行了修復,提升了 DLedger 模式下對進程異常崩潰、慢節點、對稱/非對稱網絡分區、網絡丟包的容錯能力,也進一步驗證了 DLedger 模式的可靠性。
在舊版本中一組 Broker 中選誰做爲 Leader 徹底是隨機的。可是在新版中咱們能夠經過配置 preferredLeaderId 來指定優先選舉某個節點爲 Leader,以下圖所示,經過在三個機房部署 DLedger 模式的 broker 組,利用 preferred leader 能夠更好的實現機房對齊的功能,圖中 DC1 中服務更好,咱們能夠優先選擇在 DC1 中部署 Master。此外,利用 preferred leader 還能夠更好實現 DLedger 集羣混部,從而充分利用機器資源。
從 RocketMQ 4.8.0 開始,DLedger 模式支持批量消息發送,從而在消息類型的支持上徹底與 Master-Slave 部署形態保持一致。
除了對 DLedger 模式的大量優化,本次 RocketMQ 版本一共包含 Improvement 25 個,Bug Fix 11 個,文檔和代碼格式優化 16 個。據不徹底統計,這些貢獻來自近 40 位 RocketMQ 社區的 Contributor,感謝你們的積極參與。也很是期待有更多的用戶、廠商、開發者參與到 RocketMQ 建設中來,加入 Apache RocketMQ 社區,永遠不會太遲!