本文梳理筆者 MQ 知識(shí),從消息中間件的基礎(chǔ)知識(shí)講起,在有了基礎(chǔ)知識(shí)后,對(duì)市面上各主流的消息中間件進(jìn)行詳細(xì)的解析,包括 RabbitMQ、RocketMQ、Kafka、Pulsar,最后再橫向?qū)Ρ冗@幾款主流的消息中間件。本篇是系列文章第二篇。?第一篇:關(guān)于MQ,你了解多少
RocketMQ
基礎(chǔ)概念
Tag
Tag(標(biāo)簽)可以看作子主題,它是消息的第二級(jí)類型,用于為用戶提供額外的靈活性。使用標(biāo)簽,同一業(yè)務(wù)模塊不同目的的消息就可以用相同 Topic 而不同的 Tag 來(lái)標(biāo)識(shí)。比如交易消息又可以分為:交易創(chuàng)建消息、交易完成消息等,一條消息可以沒(méi)有 Tag 。標(biāo)簽有助于保持你的代碼干凈和連貫,并且還可以為 RocketMQ 提供的查詢系統(tǒng)提供幫助。
Group
RocketMQ 中,訂閱者的概念是通過(guò)消費(fèi)組(Consumer Group)來(lái)體現(xiàn)的。每個(gè)消費(fèi)組都消費(fèi)主題中一份完整的消息,不同消費(fèi)組之間消費(fèi)進(jìn)度彼此不受影響,也就是說(shuō),一條消息被 Consumer Group1 消費(fèi)過(guò),也會(huì)再給 Consumer Group2 消費(fèi)。消費(fèi)組中包含多個(gè)消費(fèi)者,同一個(gè)組內(nèi)的消費(fèi)者是競(jìng)爭(zhēng)消費(fèi)的關(guān)系,每個(gè)消費(fèi)者負(fù)責(zé)消費(fèi)組內(nèi)的一部分消息。默認(rèn)情況,如果一條消息被消費(fèi)者 Consumer1 消費(fèi)了,那同組的其他消費(fèi)者就不會(huì)再收到這條消息。
Offset
在 Topic 的消費(fèi)過(guò)程中,由于消息需要被不同的組進(jìn)行多次消費(fèi),所以消費(fèi)完的消息并不會(huì)立即被刪除,這就需要? RocketMQ 為每個(gè)消費(fèi)組在每個(gè)隊(duì)列上維護(hù)一個(gè)消費(fèi)位置(Consumer Offset),這個(gè)位置之前的消息都被消費(fèi)過(guò),之后的消息都沒(méi)有被消費(fèi)過(guò),每成功消費(fèi)一條消息,消費(fèi)位置就加一。也可以這么說(shuō),Queue 是一個(gè)長(zhǎng)度無(wú)限的數(shù)組,Offset 就是下標(biāo)。
RocketMQ 架構(gòu)
RabbitMQ 類似有生產(chǎn)階段、存儲(chǔ)階段、消費(fèi)階段,相較 RabbitMQ 的架構(gòu),增加了 NameServer 集群,橫向拓展能力較好。參考的 Kafka 做的設(shè)計(jì),故也同樣擁有 NIO、PageCache、順序讀寫(xiě)、零拷貝的技能,單機(jī)的吞吐量在十萬(wàn)級(jí),橫向拓展能力較強(qiáng),官方聲明集群下能承載萬(wàn)億級(jí)吞吐。??
存儲(chǔ)階段,可以通過(guò)配置可靠性優(yōu)先的 Broker 參數(shù)來(lái)避免因?yàn)殄礄C(jī)丟消息,簡(jiǎn)單說(shuō)就是可靠性優(yōu)先的場(chǎng)景都應(yīng)該使用同步。??
1、消息只要持久化到 CommitLog(日志文件)中,即使 Broker 宕機(jī),未消費(fèi)的消息也能重新恢復(fù)再消費(fèi)。?
2、Broker 的刷盤機(jī)制:同步刷盤和異步刷盤,不管哪種刷盤都可以保證消息一定存儲(chǔ)在 Pagecache 中(內(nèi)存中),但是同步刷盤更可靠,它是 Producer 發(fā)送消息后等數(shù)據(jù)持久化到磁盤之后再返回響應(yīng)給 Producer。?
Broker 通過(guò)主從模式來(lái)保證高可用,Broker 支持 Master 和 Slave 同步復(fù)制、Master 和 Slave 異步復(fù)制模式,生產(chǎn)者的消息都是發(fā)送給 Master,但是消費(fèi)既可以從 Master 消費(fèi),也可以從 Slave 消費(fèi)。同步復(fù)制模式可以保證即使 Master 宕機(jī),消息肯定在 Slave 中有備份,保證了消息不會(huì)丟失。??
Consumer 的配置文件中,并不需要設(shè)置是從 Master 讀還是從 Slave 讀,當(dāng) Master 不可用或者繁忙的時(shí)候, Consumer 的讀請(qǐng)求會(huì)被自動(dòng)切換到從 Slave。有了自動(dòng)切換 Consumer 這種機(jī)制,當(dāng)一個(gè) Master 角色的機(jī)器出現(xiàn)故障后,Consumer 仍然可以從 Slave 讀取消息,不影響 Consumer 讀取消息,這就實(shí)現(xiàn)了讀的高可用。? ??
如何達(dá)到發(fā)送端寫(xiě)的高可用性呢?在創(chuàng)建 Topic 的時(shí)候,把 Topic 的多個(gè) Message Queue 創(chuàng)建在多個(gè) Broker 組上(相同 Broker 名稱,不同 BrokerId 機(jī)器組成 Broker 組),這樣當(dāng) Broker 組的 Master 不可用后,其他組Master 仍然可用, Producer 仍然可以發(fā)送消息。
此架構(gòu)下的 RocketMQ 不支持把 Slave 自動(dòng)轉(zhuǎn)成 Master ,如果機(jī)器資源不足,需要把 Slave 轉(zhuǎn)成 Master ,則要手動(dòng)停止 Slave 色的 Broker ,更改配置文件,用新的配置文件啟動(dòng) Broker。由此,在高可用場(chǎng)景下此問(wèn)題變得棘手,故需要引入分布式算法的實(shí)現(xiàn),追求 CAP,但實(shí)踐情況是不能同事滿足 CA的,在互聯(lián)網(wǎng)場(chǎng)景下較多是在時(shí)間 BASE 理論,優(yōu)先滿足 AP,盡可能去滿足 C。RocketMQ 引入的是實(shí)現(xiàn) Raft 算法的 Dledger,擁有了選舉能力,主從切換,架構(gòu)拓?fù)鋱D是這樣的:
分布式算法中比較常常聽(tīng)到的是 Paxos 算法,但是由于 Paxos 算法難于理解,且實(shí)現(xiàn)比較困難,所以不太受業(yè)界歡迎。然后出現(xiàn)新的分布式算法 Raft,其比 Paxos 更容易懂與實(shí)現(xiàn),到如今在實(shí)際中運(yùn)用的也已經(jīng)很成熟,不同的語(yǔ)言都有對(duì)其的實(shí)現(xiàn)。Dledger 就是其中一個(gè) Java 語(yǔ)言的實(shí)現(xiàn),其將算法方面的內(nèi)容全部抽象掉,這樣開(kāi)發(fā)人員只需要關(guān)系業(yè)務(wù)即可,大大降低使用難度。
事務(wù)消息
生產(chǎn)者將消息發(fā)送至 Apache RocketMQ 服務(wù)端。
Apache RocketMQ 服務(wù)端將消息持久化成功之后,向生產(chǎn)者返回 Ack 確認(rèn)消息已經(jīng)發(fā)送成功,此時(shí)消息被標(biāo)記為"暫不能投遞",這種狀態(tài)下的消息即為半事務(wù)消息。
生產(chǎn)者開(kāi)始執(zhí)行本地事務(wù)邏輯。
生產(chǎn)者根據(jù)本地事務(wù)執(zhí)行結(jié)果向服務(wù)端提交二次確認(rèn)結(jié)果(Commit 或是 Rollback),服務(wù)端收到確認(rèn)結(jié)果后處理邏輯如下:
二次確認(rèn)結(jié)果為 Commit:服務(wù)端將半事務(wù)消息標(biāo)記為可投遞,并投遞給消費(fèi)者。
二次確認(rèn)結(jié)果為 Rollback:服務(wù)端將回滾事務(wù),不會(huì)將半事務(wù)消息投遞給消費(fèi)者。
在斷網(wǎng)或者是生產(chǎn)者應(yīng)用重啟的特殊情況下,若服務(wù)端未收到發(fā)送者提交的二次確認(rèn)結(jié)果,或服務(wù)端收到的二次確認(rèn)結(jié)果為 Unknown 未知狀態(tài),經(jīng)過(guò)固定時(shí)間后,服務(wù)端將對(duì)消息生產(chǎn)者即生產(chǎn)者集群中任一生產(chǎn)者實(shí)例發(fā)起消息回查。說(shuō)明 服務(wù)端回查的間隔時(shí)間和最大回查次數(shù),請(qǐng)參見(jiàn)[參數(shù)限制](https://rocketmq.apache.org/zh/docs/introduction/03limits/)。
生產(chǎn)者收到消息回查后,需要檢查對(duì)應(yīng)消息的本地事務(wù)執(zhí)行的最終結(jié)果。
生產(chǎn)者根據(jù)檢查到的本地事務(wù)的最終狀態(tài)再次提交二次確認(rèn),服務(wù)端仍按照步驟4對(duì)半事務(wù)消息進(jìn)行處理。
事務(wù)消息生命周期
初始化:半事務(wù)消息被生產(chǎn)者構(gòu)建并完成初始化,待發(fā)送到服務(wù)端的狀態(tài)。
事務(wù)待提交:半事務(wù)消息被發(fā)送到服務(wù)端,和普通消息不同,并不會(huì)直接被服務(wù)端持久化,而是會(huì)被單獨(dú)存儲(chǔ)到事務(wù)存儲(chǔ)系統(tǒng)中,等待第二階段本地事務(wù)返回執(zhí)行結(jié)果后再提交。此時(shí)消息對(duì)下游消費(fèi)者不可見(jiàn)。
消息回滾:第二階段如果事務(wù)執(zhí)行結(jié)果明確為回滾,服務(wù)端會(huì)將半事務(wù)消息回滾,該事務(wù)消息流程終止。
提交待消費(fèi):第二階段如果事務(wù)執(zhí)行結(jié)果明確為提交,服務(wù)端會(huì)將半事務(wù)消息重新存儲(chǔ)到普通存儲(chǔ)系統(tǒng)中,此時(shí)消息對(duì)下游消費(fèi)者可見(jiàn),等待被消費(fèi)者獲取并消費(fèi)。
消費(fèi)中:消息被消費(fèi)者獲取,并按照消費(fèi)者本地的業(yè)務(wù)邏輯進(jìn)行處理的過(guò)程。此時(shí)服務(wù)端會(huì)等待消費(fèi)者完成消費(fèi)并提交消費(fèi)結(jié)果,如果一定時(shí)間后沒(méi)有收到消費(fèi)者的響應(yīng),Apache RocketMQ 會(huì)對(duì)消息進(jìn)行重試處理。具體信息,請(qǐng)參見(jiàn)消費(fèi)重試。
消費(fèi)提交:消費(fèi)者完成消費(fèi)處理,并向服務(wù)端提交消費(fèi)結(jié)果,服務(wù)端標(biāo)記當(dāng)前消息已經(jīng)被處理(包括消費(fèi)成功和失敗)。Apache RocketMQ 默認(rèn)支持保留所有消息,此時(shí)消息數(shù)據(jù)并不會(huì)立即被刪除,只是邏輯標(biāo)記已消費(fèi)。消息在保存時(shí)間到期或存儲(chǔ)空間不足被刪除前,消費(fèi)者仍然可以回溯消息重新消費(fèi)。
消息刪除:Apache RocketMQ 按照消息保存機(jī)制滾動(dòng)清理最早的消息數(shù)據(jù),將消息從物理文件中刪除。更多信息,請(qǐng)參見(jiàn)消息存儲(chǔ)和[清理機(jī)制](https://rocketmq.apache.org/zh/docs/featureBehavior/11messagestorepolicy/)。
RocketMQ 新發(fā)展
在過(guò)去“分”往往是技術(shù)實(shí)現(xiàn)的妥協(xié),而現(xiàn)在“合”才是用戶的真正需求。RocketMQ 5.0 基于統(tǒng)一 Commitlog 擴(kuò)展多元化索引,包括時(shí)間索引、百萬(wàn)隊(duì)列索引、事務(wù)索引、KV索引、批量索引、邏輯隊(duì)列等技術(shù)。在場(chǎng)景上同時(shí)支撐了 RabbitMQ、Kafka、MQTT、邊緣輕量計(jì)算等產(chǎn)品能力,努力實(shí)現(xiàn)“消息、事件、流”的擴(kuò)展支持,云原生是主流。
更多信息可查看官網(wǎng) [Apache RocketMQ](https://rocketmq.apache.org/zh/)。
Kafka
Kafka 是一個(gè)分布式系統(tǒng),由通過(guò)高性能 TCP 網(wǎng)絡(luò)協(xié)議進(jìn)行通信的服務(wù)器和客戶端組成。它可以部署在本地和云環(huán)境中的裸機(jī)硬件、虛擬機(jī)和容器上。
服務(wù)器:Kafka 作為一個(gè)或多個(gè)服務(wù)器集群運(yùn)行,可以跨越多個(gè)數(shù)據(jù)中心或云區(qū)域。其中一些服務(wù)器形成存儲(chǔ)層,稱為代理。其他服務(wù)器運(yùn)行 Kafka Connect 以事件流的形式持續(xù)導(dǎo)入和導(dǎo)出數(shù)據(jù),以將 Kafka 與您現(xiàn)有的系統(tǒng)(例如關(guān)系數(shù)據(jù)庫(kù)以及其他 Kafka 集群)集成。為了讓您實(shí)現(xiàn)關(guān)鍵任務(wù)用例,Kafka 集群具有高度可擴(kuò)展性和容錯(cuò)性:如果其中任何一臺(tái)服務(wù)器發(fā)生故障,其他服務(wù)器將接管它們的工作以確保連續(xù)運(yùn)行而不會(huì)丟失任何數(shù)據(jù)。
客戶端:它們?cè)试S您編寫(xiě)分布式應(yīng)用程序和微服務(wù),即使在出現(xiàn)網(wǎng)絡(luò)問(wèn)題或機(jī)器故障的情況下,也能以容錯(cuò)的方式并行、大規(guī)模地讀取、寫(xiě)入和處理事件流。Kafka 附帶了一些這樣的客戶端,這些客戶端由 Kafka 社區(qū)提供的 數(shù)十個(gè)客戶端進(jìn)行了擴(kuò)充:客戶端可用于 Java 和 Scala,包括更高級(jí)別的 Kafka Streams 庫(kù),用于 Go、Python、C/C++ 和許多其他編程語(yǔ)言以及 REST API。
架構(gòu)
與前面兩個(gè) MQ 類似有生產(chǎn)階段、存儲(chǔ)階段、消費(fèi)階段,相比 RocketMQ 這里的注冊(cè)中心是用的 Zookeeper,Kafka 的諸多事件都依賴于 ZK,元數(shù)據(jù)管理、各個(gè)角色的注冊(cè)、心跳、選舉、狀態(tài)維護(hù),這里的角色包括 Boker、 Topic、 Partition、 消費(fèi)者組等。??
所以這里也會(huì)帶來(lái) ZK Watch 事件壓力過(guò)大的問(wèn)題,大量的 ZK 節(jié)點(diǎn)事件阻塞在隊(duì)列中, 導(dǎo)致自旋鎖, 導(dǎo)致 CPU 上升, 由于大量數(shù)量事件對(duì)象導(dǎo)致占用了大量的內(nèi)存。
圖中的 Controller 是 Kakfa 服務(wù)端 Broker 的概念,Broker 集群有多臺(tái),但只有一臺(tái) Broker 可以扮演控制器的角色;某臺(tái) Broker 一旦成為 Controller,它用于以下權(quán)力:完成對(duì)集群成員管理、主題維護(hù)和分區(qū)的管理,如集群 Broker 信息、Topic 維護(hù)、Partition 維護(hù)、分區(qū)選舉 ISR、同步元信息給其他 Broker 等。
存儲(chǔ)
Topic 是邏輯上的概念,而 Partition 是物理上的概念,即一個(gè) Topic 劃分為多個(gè) Partition,每個(gè) Partition 對(duì)應(yīng)一個(gè)Log文件。?
.log文件:存儲(chǔ)消息數(shù)據(jù)的文件。? ??
.index文件:索引文件,記錄一條消息在log文件中的位置。??
.snapshot文件:記載著生產(chǎn)者最新的offset。??
.timeindex時(shí)間索引文件:當(dāng)前日志分段文件中建立索引的消息的時(shí)間戳,是在 0.10.0 版本后增加的,用于根據(jù)時(shí)間戳快速查找特定消息的位移值,優(yōu)化 Kafka 讀取歷史消息緩慢的問(wèn)題。為了保證時(shí)間戳的單調(diào)遞增,可以將log.message.timestamp.type 設(shè)置成 logApendTime,而 CreateTime 不能保證是消息寫(xiě)入時(shí)間。??
上圖是三個(gè) Broker、兩個(gè) Topic、兩個(gè) Partition 的 Broker ?的存儲(chǔ)情況,可以延伸想象一下百萬(wàn)級(jí) Topic 的存儲(chǔ)情況會(huì)很復(fù)雜。
Rebalnce 問(wèn)題
為了解決強(qiáng)依賴 Zookeeper 進(jìn)行 Rebalance 帶來(lái)的問(wèn)題,Kafka 引入了 Coordinator 機(jī)制。??
首先,觸發(fā) Rebalance (再均衡)操作的場(chǎng)景目前分為以下幾種:消費(fèi)者組內(nèi)消費(fèi)者數(shù)量發(fā)生變化,包括:?
有新消費(fèi)者加入
有消費(fèi)者宕機(jī)下線,包括真正宕機(jī),或者長(zhǎng)時(shí)間 GC、網(wǎng)絡(luò)延遲導(dǎo)致消費(fèi)者未在超時(shí)時(shí)間內(nèi)向 GroupCoordinator 發(fā)送心跳,也會(huì)被認(rèn)為下線。??
有消費(fèi)者主動(dòng)退出消費(fèi)者組(發(fā)送 LeaveGroupRequest 請(qǐng)求) 比如客戶端調(diào)用了 unsubscrible() 方法取消對(duì)某些主題的訂閱
消費(fèi)者組對(duì)應(yīng)的 GroupCoordinator 節(jié)點(diǎn)發(fā)生了變化。??
消費(fèi)者組訂閱的主題發(fā)生變化(增減)或者主題分區(qū)數(shù)量發(fā)生了變化。??
節(jié)點(diǎn)擴(kuò)容?
更多信息可查看 Kafka 官網(wǎng) [Apache Kafka](https://kafka.apache.org/)
Pulsar
在最高層,一個(gè) Pulsar 實(shí)例由一個(gè)或多個(gè) Pulsar 集群組成。一個(gè)實(shí)例中的集群可以在它們之間復(fù)制數(shù)據(jù)。
在 Pulsar 集群中:
一個(gè)或多個(gè) Broker 處理和負(fù)載平衡來(lái)自生產(chǎn)者的傳入消息,將消息分派給消費(fèi)者,與 Pulsar 配置存儲(chǔ)通信以處理各種協(xié)調(diào)任務(wù),將消息存儲(chǔ)在 BookKeeper 實(shí)例(又名 bookies)中,依賴于特定集群的 ZooKeeper 集群用于某些任務(wù)等等。
由一個(gè)或多個(gè) Bookie 組成的 BookKeeper 集群處理消息的持久存儲(chǔ)。
特定于該集群的 ZooKeeper 集群處理 Pulsar 集群之間的協(xié)調(diào)任務(wù)。
下圖展示了一個(gè) Pulsar 集群:
?
Pulsar 用 Apache BookKeeper 作為持久化存儲(chǔ),Broker 持有 BookKeeper client,把未確認(rèn)的消息發(fā)送到 BookKeeper 進(jìn)行保存。
BookKeeper 是一個(gè)分布式的 WAL(Write Ahead Log)系統(tǒng),Pulsar 使用 BookKeeper 有下面幾個(gè)便利:
可以為 Topic 創(chuàng)建多個(gè) Ledgers:Ledger 是一個(gè)只追加的數(shù)據(jù)結(jié)構(gòu),并且只有一個(gè) Writer,這個(gè) Writer 負(fù)責(zé)多個(gè) BookKeeper 存儲(chǔ)節(jié)點(diǎn)(就是 Bookies)的寫(xiě)入。Ledger 的條目會(huì)被復(fù)制到多個(gè) Bookies;
Broker 可以創(chuàng)建、關(guān)閉和刪除 Ledger,也可以追加內(nèi)容到 Ledger;
Ledger 被關(guān)閉后,只能以只讀狀態(tài)打開(kāi),除非要明確地寫(xiě)數(shù)據(jù)或者是因?yàn)?Writer 掛掉導(dǎo)致的關(guān)閉;
Ledger 只能有 Writer 這一個(gè)進(jìn)程寫(xiě)入,這樣寫(xiě)入不會(huì)有沖突,所以寫(xiě)入效率很高。如果 Writer 掛了,Ledger 會(huì)啟動(dòng)恢復(fù)進(jìn)程來(lái)確定 Ledger 最終狀態(tài)和最后提交的日志,保證之后所有 Ledger 進(jìn)程讀取到相同的內(nèi)容;??
除了保存消息數(shù)據(jù)外,還會(huì)保存 Cursors,也就是消費(fèi)端訂閱消費(fèi)的位置。這樣所有 Cursors 消費(fèi)完一個(gè) Ledger 的消息后這個(gè) Ledger 就可以被刪除,這樣可以實(shí)現(xiàn) Ledgers 的定期翻滾從頭寫(xiě)。
節(jié)點(diǎn)對(duì)等
從架構(gòu)圖可以看出,Broker 節(jié)點(diǎn)不保存數(shù)據(jù),所有 Broker 節(jié)點(diǎn)都是對(duì)等的。如果一個(gè) Broker 宕機(jī)了,不會(huì)丟失任何數(shù)據(jù),只需要把它服務(wù)的 Topic 遷移到一個(gè)新的 Broker 上就行。??
Broker 的 Topic 擁有多個(gè)邏輯分區(qū),同時(shí)每個(gè)分區(qū)又有多個(gè) Segment。??
Writer 寫(xiě)數(shù)據(jù)時(shí),首先會(huì)選擇 Bookies,比如圖中的 Segment1。選擇了 Bookie1、Bookie2、Bookie4,然后并發(fā)地寫(xiě)下去。這樣這 3 個(gè)節(jié)點(diǎn)并沒(méi)有主從關(guān)系,協(xié)調(diào)完全依賴于 Writer,因此它們也是對(duì)等的。
擴(kuò)展和擴(kuò)容
在遇到雙十一等大流量的場(chǎng)景時(shí),必須增加 Consumer。
這時(shí)因?yàn)?Broker 不存儲(chǔ)任何數(shù)據(jù),可以方便的增加 Broker。Broker 集群會(huì)有一個(gè)或多個(gè) Broker 做消息負(fù)載均衡。當(dāng)新的 Broker 加入后,流量會(huì)自動(dòng)從壓力大的 Broker 上遷移過(guò)來(lái)。??
對(duì)于 BookKeeper,如果對(duì)存儲(chǔ)要求變高,比如之前存儲(chǔ) 2 個(gè)副本現(xiàn)在需要存儲(chǔ) 4 個(gè)副本,這時(shí)可以單獨(dú)擴(kuò)展 Bookies 而不用考慮 Broker。因?yàn)楣?jié)點(diǎn)對(duì)等,之前節(jié)點(diǎn)的 Segment 又堆放整齊,加入新節(jié)點(diǎn)并不用搬移數(shù)據(jù)。Writer 會(huì)感知新的節(jié)點(diǎn)并優(yōu)先選擇使用。
容錯(cuò)機(jī)制
對(duì)于 Broker,因?yàn)椴槐4嫒魏螖?shù)據(jù),如果節(jié)點(diǎn)宕機(jī)了就相當(dāng)于客戶端斷開(kāi),重新連接其他的 Broker 就可以了。
對(duì)于 BookKeeper,保存了多份副本并且這些副本都是對(duì)等的。因?yàn)闆](méi)有主從關(guān)系,所以當(dāng)一個(gè)節(jié)點(diǎn)宕機(jī)后,不用立即恢復(fù)。后臺(tái)有一個(gè)線程會(huì)檢查宕機(jī)節(jié)點(diǎn)的數(shù)據(jù)備份進(jìn)行恢復(fù)。
在遇到雙十一等大流量的場(chǎng)景時(shí),必須增加 Consumer。
這時(shí)因?yàn)?Broker 不存儲(chǔ)任何數(shù)據(jù),可以方便的增加 Broker。Broker 集群會(huì)有一個(gè)或多個(gè) Broker 做消息負(fù)載均衡。當(dāng)新的 Broker 加入后,流量會(huì)自動(dòng)從壓力大的 Broker 上遷移過(guò)來(lái)。??
對(duì)于 BookKeeper,如果對(duì)存儲(chǔ)要求變高,比如之前存儲(chǔ) 2 個(gè)副本現(xiàn)在需要存儲(chǔ) 4 個(gè)副本,這時(shí)可以單獨(dú)擴(kuò)展 Bookies 而不用考慮 Broker。因?yàn)楣?jié)點(diǎn)對(duì)等,之前節(jié)點(diǎn)的 Segment 又堆放整齊,加入新節(jié)點(diǎn)并不用搬移數(shù)據(jù)。Writer 會(huì)感知新的節(jié)點(diǎn)并優(yōu)先選擇使用。
Pulsar 可以使用多租戶來(lái)管理大集群。Pulsar 的租戶可以跨集群分布,每個(gè)租戶都可以有單獨(dú)的認(rèn)證和授權(quán)機(jī)制。租戶也是存儲(chǔ)配額、消息 TTL 和隔離策略的管理單元。
在和其他組件或者生態(tài)對(duì)接方面,Pulsar 可以支持很多種消息協(xié)議,對(duì)于存量系統(tǒng)的MQ首次接入、切換MQ都很方便。
更多信息可查看 Pulsar 官網(wǎng)?[Apache Pulsar](https://pulsar.apache.org/)
對(duì)比
此圖摘抄自《面渣逆襲:RocketMQ二十三問(wèn)》
這個(gè)圖沒(méi)有 Pulsar 的信息,從網(wǎng)上看到的壓測(cè)報(bào)告來(lái)看,Pulsar 吞吐量大概是 Kafka 的兩倍左右,延遲表現(xiàn)比 Kafka 低不少,Pulsar 的 I/O 隔離顯著優(yōu)于 Kafka。比較詳實(shí)的 Pulsar 和 Kafka 的比對(duì)可以查閱 StreamNative 的文章《Pulsar和Kafka基準(zhǔn)測(cè)試:Pulsar 性能精準(zhǔn)解析(完整版)》,StreamNative 作為 Apache Pulsar 的商業(yè)化公司,數(shù)據(jù)和結(jié)果還是比較可靠的。
進(jìn)階
常言道,最好的學(xué)習(xí)方法是帶著問(wèn)題去尋找答案,在路上撿拾更多果實(shí),增加經(jīng)驗(yàn)值,快速升級(jí)。很多人推薦費(fèi)曼學(xué)習(xí)法,以教代學(xué),按可以教別人的標(biāo)準(zhǔn)來(lái)學(xué)習(xí),最終產(chǎn)出教學(xué)內(nèi)容為目的來(lái)學(xué)習(xí)一個(gè)知識(shí),能讓自己高效學(xué)習(xí)。在我看來(lái)這很像績(jī)效考核用的 OKR 工具,為項(xiàng)目設(shè)定關(guān)鍵成果,實(shí)現(xiàn)成功應(yīng)該做什么?怎么做?而我寫(xiě)這篇文章是在實(shí)踐費(fèi)曼學(xué)習(xí)法。??
所以,在這里我給出幾個(gè)問(wèn)題,讀者可以根據(jù)自己的興趣愛(ài)好帶著問(wèn)題去尋找答案吧。??
如何保證消息的可用性/可靠性/不丟失呢?
如何處理消息重復(fù)的問(wèn)題呢?
順序消息如何實(shí)現(xiàn)?
怎么處理消息積壓?
怎么實(shí)現(xiàn)分布式消息事務(wù)的?半消息?
如何實(shí)現(xiàn)消息過(guò)濾?
如果自己平時(shí)想到的問(wèn)題太多,不知道先看哪一個(gè),那么自己想清楚為什么要學(xué)這些知識(shí)點(diǎn),哪個(gè)問(wèn)題對(duì)于當(dāng)前的自己收益最大。
編輯:黃飛
?
評(píng)論
查看更多