小程序搭建賺錢是真的嗎南京seo報(bào)價(jià)
文章目錄
- MQ的發(fā)展史
- 階段一:追求解耦
- 階段二:追求吞吐量與一致性
- 階段三:追求平臺(tái)化
- MQ的通用架構(gòu)
- 主題topic、生產(chǎn)者producer、消費(fèi)者consumer
- 分區(qū)partition
- MQ 存儲(chǔ)
- Kafka
- Good Design ---> 磁盤順序?qū)懕P
- Poor Impact---> topic 數(shù)量不能過(guò)大
- RocketMQ
- zookeeper vs namesrv
- 局部順序?qū)?#xff08;kafka) 與 完全順序?qū)?#xff08;rocketmq)
- Rocketmq 存儲(chǔ)結(jié)構(gòu)
- Pulsar
- 架構(gòu)圖(分層+分片)
- 服務(wù)層設(shè)計(jì)
- 存儲(chǔ)層設(shè)計(jì)
- 擴(kuò)容
- 容災(zāi)
- 小結(jié)
MQ的發(fā)展史
如上圖我們可以把消息隊(duì)列的發(fā)展切分成了三個(gè)大的階段
階段一:追求解耦
- 2003-2010年,計(jì)算機(jī)軟件行業(yè)興起。
- 系統(tǒng)間強(qiáng)耦合是程序設(shè)計(jì)的難題。
- ActiveMQ和RabbitMQ等消息隊(duì)列出現(xiàn)。
- 消息隊(duì)列致力于解決系統(tǒng)間耦合和異步化操作問(wèn)題。
- 系統(tǒng)間解耦和異步化是消息隊(duì)列最主要的功能和使用場(chǎng)景。
階段二:追求吞吐量與一致性
- 10 -12 年期間,大數(shù)據(jù)時(shí)代實(shí)時(shí)計(jì)算需求增長(zhǎng),數(shù)據(jù)規(guī)模擴(kuò)大,Kafka應(yīng)運(yùn)而生滿足消息隊(duì)列高吞吐量和并發(fā)需求。
- 隨著阿里電商業(yè)務(wù)發(fā)展,Kafka在可靠性、一致性、順序消息等方面無(wú)法滿足需求。
- RocketMQ誕生,吸收Kafka設(shè)計(jì)理念之余,解決其痛點(diǎn)。
- RocketMQ不依賴Zookeeper,增強(qiáng)可靠性、一致性、順序消息能力。
- 阿里將RocketMQ開源,最終成為Apache項(xiàng)目,滿足大數(shù)據(jù) messaging 需求。
階段三:追求平臺(tái)化
- 平臺(tái)化的產(chǎn)品會(huì)取代非平臺(tái)化的產(chǎn)品,這是行業(yè)發(fā)展趨勢(shì)。
- 2012年后,云計(jì)算、容器化興起,公司開始把基礎(chǔ)技術(shù)能力平臺(tái)化。
- 阿里云、騰訊云等云服務(wù)的出現(xiàn)證明了這一趨勢(shì)。
- Pulsar誕生于此背景下,目的是解決雅虎內(nèi)部重復(fù)建設(shè)、消息隊(duì)列隔離不好、數(shù)據(jù)遷移難等問(wèn)題。
- Pulsar通過(guò)提供平臺(tái)化的消息隊(duì)列服務(wù)來(lái)解決這些問(wèn)題。
- 平臺(tái)化是Pulsar產(chǎn)生的核心原因,也是解決上述問(wèn)題的關(guān)鍵所在。
MQ的通用架構(gòu)
主題topic、生產(chǎn)者producer、消費(fèi)者consumer
用吃飯的場(chǎng)景生動(dòng)地詮釋了消息隊(duì)列的幾個(gè)關(guān)鍵概念:
- 飯?zhí)玫牟煌瑱n口(米飯、面、麻辣香鍋)對(duì)應(yīng)消息隊(duì)列的主題(topic)概念。
- 用戶選擇某個(gè)檔口排隊(duì)取餐,這個(gè)過(guò)程相當(dāng)于生產(chǎn)者生產(chǎn)了一條消息到該主題的消息隊(duì)列中。
- 檔口將餐食提供給用戶,則相當(dāng)于消費(fèi)者從消息隊(duì)列中消費(fèi)了一條消息。
- 用戶排隊(duì)等待相當(dāng)于消息在隊(duì)列中的存儲(chǔ)等待被消費(fèi)的過(guò)程。
- 取餐按排隊(duì)順序進(jìn)行,消費(fèi)也是按順序進(jìn)行的。
通過(guò)日常生活的吃飯場(chǎng)景,形象地解釋了消息隊(duì)列的工作原理,包括消息主題、生產(chǎn)者、消費(fèi)者、消息存儲(chǔ)和消費(fèi)等核心概念。這些概念抽象起來(lái)可能較難理解,但結(jié)合具象的例子就很容易理解了
分區(qū)partition
- 分區(qū)是消息隊(duì)列的一種架構(gòu)方式,類似于食堂的多個(gè)檔口。
- 當(dāng)消息數(shù)量增長(zhǎng)時(shí),可以通過(guò)增加分區(qū)數(shù)進(jìn)行擴(kuò)容,如食堂增加檔口數(shù)。
- 增加分區(qū)可以擴(kuò)大消息隊(duì)列的并行處理能力,提高吞吐量,就像增加檔口可以減少等待時(shí)間。
- 生產(chǎn)者可以根據(jù)分區(qū)規(guī)則,將消息發(fā)到不同分區(qū),就像食客可以選擇人少的檔口。
- 消費(fèi)者可以從多個(gè)分區(qū)并行消費(fèi)消息,提高效率。
- Kafka之所以能達(dá)到高吞吐量,是因?yàn)樗峭ㄟ^(guò)分區(qū)實(shí)現(xiàn)消息隊(duì)列并行化和橫向擴(kuò)展的。
總結(jié)為:分區(qū)實(shí)現(xiàn)了消息隊(duì)列的并行化,是提升吞吐量和實(shí)現(xiàn)橫向擴(kuò)展的關(guān)鍵手段。
MQ 存儲(chǔ)
特性和性能是存儲(chǔ)結(jié)構(gòu)的外在表現(xiàn),其實(shí)質(zhì)是存儲(chǔ)設(shè)計(jì)。我們需要了解每種消息傳遞協(xié)議的特性,以便更好地理解它們的架構(gòu)設(shè)計(jì)。
我們將首先介紹 Kafka、RocketMQ 和 Pulsar 的架構(gòu)特點(diǎn),然后比較它們?cè)诩軜?gòu)上的不同之處,以及這些不同之處如何影響它們的功能特性。
Kafka
- Kafka 架構(gòu)中,服務(wù)節(jié)點(diǎn)沒(méi)有主從之分,主從概念是針對(duì)某個(gè) topic 下的分區(qū)。
- 存儲(chǔ)單位為分區(qū),通過(guò)不同方式分散在各個(gè)節(jié)點(diǎn),形成各種架構(gòu)圖。
- 生產(chǎn)者數(shù)量為 1,消費(fèi)者數(shù)量為 1,分區(qū)數(shù)為 2,副本數(shù)為 3,服務(wù)節(jié)點(diǎn)數(shù)為 3。
- 圖中有兩塊綠色圖案,分別為 topic1-partition1 分區(qū)和 topic1-partition2 分區(qū),淺綠色方塊為它們的副本。
- 對(duì)于服務(wù)節(jié)點(diǎn) 1,topic1-partition1 是主節(jié)點(diǎn);對(duì)于服務(wù)節(jié)點(diǎn) 2,topic1-partition2 是主節(jié)點(diǎn)。
消息隊(duì)列的大致工作流程如下:
- 生產(chǎn)者、消費(fèi)者與元數(shù)據(jù)中心建立連接,并保持心跳,獲取服務(wù)的實(shí)況和路由信息。
- 生產(chǎn)者將消息發(fā)送到 topic 下的任一分區(qū)中,通過(guò)算法保證每個(gè) topic 下的分區(qū)盡可能均勻。
- 信息需要落盤才可以給上游返回 ack,以保證宕機(jī)后的信息的完整性。
- 在信息寫成功主分區(qū)后,系統(tǒng)會(huì)根據(jù)策略選擇同步復(fù)制還是異步復(fù)制,以保證單節(jié)點(diǎn)故障時(shí)的信息完整性。
- 消費(fèi)者開始工作,拉取響應(yīng)的信息,并返回 ack。
- 消費(fèi)者在獲取消息時(shí),會(huì)根據(jù)偏移量 (offset) 進(jìn)行拉取,每次拉取后偏移量加 1。
Good Design —> 磁盤順序?qū)懕P
Kafka 在底層設(shè)計(jì)上強(qiáng)依賴于文件系統(tǒng)(一個(gè)分區(qū)對(duì)應(yīng)一個(gè)文件系統(tǒng)),本質(zhì)上是基于磁盤存儲(chǔ)的消息隊(duì)列,在我們固有印象中磁盤的讀寫速度是非常慢的,慢的原因是因?yàn)樵谧x寫的過(guò)程中所有的進(jìn)程都在搶占“磁頭”這把鎖,磁頭在讀寫之前需要將其移動(dòng)到合適的位置,這個(gè)“移動(dòng)”極其耗費(fèi)時(shí)間,這也就是磁盤慢的原因,但是如何不用移動(dòng)磁頭呢,順序?qū)懕P就誕生了。
Kafka 消息存儲(chǔ)在分區(qū)中,每個(gè)分區(qū)對(duì)應(yīng)一組連續(xù)的物理空間。新消息追加到磁盤文件末尾。消費(fèi)者按順序拉取分區(qū)數(shù)據(jù)消費(fèi)。Kafka 的讀寫是順序的,可以高效地利用 PageCache,解決磁盤讀寫的性能問(wèn)題。
這一特性非常重要,很多組件的底層存儲(chǔ)設(shè)計(jì)都會(huì)用到這點(diǎn),理解好這點(diǎn)對(duì)理解消息隊(duì)列尤為重要。
The Pathologies of Big Data
Poor Impact—> topic 數(shù)量不能過(guò)大
kafka 的整體性能收到了 topic 數(shù)量的限制,這和底層的存儲(chǔ)有密不可分的關(guān)系,我們上面講過(guò),當(dāng)消息來(lái)的時(shí)候,底層數(shù)據(jù)使用追加寫入的方式,順序?qū)懕P,使得整體的寫性能大大提高,但這并不能代表所有情況,當(dāng)我們 topic 數(shù)量從幾個(gè)變成上千個(gè)的時(shí)候,情況就有所不同了
- 左圖代表了,隊(duì)列中從頭到尾的信息為:topic1、topic1、topic1、topic2,在這種情況下,很好地運(yùn)用了順序?qū)懕P的特性,磁頭不用去移動(dòng)
- 右邊圖的情況,隊(duì)列中從頭到尾的信息為:topic1、topic2、topic3、topic4,當(dāng)隊(duì)列中的信息變的很分散的時(shí)候,這個(gè)時(shí)候我們會(huì)發(fā)現(xiàn),似乎沒(méi)有辦法利用磁盤的順序?qū)懕P的特性,因?yàn)槊看螌懲暌环N信息,磁頭都需要進(jìn)行移動(dòng)
就很好理解,為什么當(dāng) topic 數(shù)量很大時(shí),kafka 的性能會(huì)急劇下降了。
當(dāng)然沒(méi)有其他辦法了嗎,當(dāng)然有。我們可以把存儲(chǔ)換成速度更快 ssd 或者針對(duì)每一個(gè)分區(qū)都搞一塊磁盤,當(dāng)然這都是錢! 這也是架構(gòu)設(shè)計(jì)中的一種 trade off
RocketMQ
對(duì)比 kafka,rocketmq 有兩點(diǎn)很大的不同:
- 元數(shù)據(jù)管理系統(tǒng),從 zookeeper 變成了輕量級(jí)的獨(dú)立服務(wù)集群。
- 服務(wù)節(jié)點(diǎn)變?yōu)?多主多從架構(gòu)
zookeeper vs namesrv
ookeeper 是 cp 強(qiáng)一致架構(gòu)的一種,其內(nèi)部使用 zab 算法,進(jìn)行信息同步和容災(zāi),在信息量較小的情況下,性能較好,當(dāng)信息交互變多,因?yàn)橥綆?lái)的性能損耗加大,性能和吞吐量降低。如果 zookeeper 宕機(jī),會(huì)導(dǎo)致整個(gè)集群的不可用,對(duì)于一些交易場(chǎng)景,這是不可接受的
- 相比 Zookeeper,RocketMQ 選擇了輕量級(jí)的獨(dú)立服務(wù)器 NameSRV。
- NameSRV 使用簡(jiǎn)單的 K/V 結(jié)構(gòu)保存信息。
- NameSRV 支持集群模式,每個(gè) NameSRV 相互獨(dú)立,不進(jìn)行任何通信。
- Data 都保存在內(nèi)存當(dāng)中,Broker 的注冊(cè)過(guò)程通過(guò)循環(huán)遍歷所有 NameSRV 進(jìn)行注冊(cè)。
局部順序?qū)?#xff08;kafka) 與 完全順序?qū)?#xff08;rocketmq)
- Kafka 將不同分區(qū)寫入對(duì)應(yīng)的文件系統(tǒng)中,保證了優(yōu)秀的水平擴(kuò)容能力。
- RocketMQ 追求極致的消息寫,將所有 topic 消息存儲(chǔ)在同一個(gè)文件中,確保消息發(fā)送時(shí)按順序?qū)懳募?#xff0c;提高可用性和吞吐量。
- RocketMQ 的設(shè)計(jì)使得其不支持刪除指定 topic 功能,因?yàn)?topic 信息在磁盤上是一段非連續(xù)的區(qū)域,不像 Kafka 一個(gè) topic 是一段連續(xù)的區(qū)域。
Rocketmq 存儲(chǔ)結(jié)構(gòu)
RocketMQ 的存儲(chǔ)結(jié)構(gòu)設(shè)計(jì)是為了追求極致的消息寫性能,它采用了混合存儲(chǔ)的方式,將多個(gè) Topic 的消息實(shí)體內(nèi)容都存儲(chǔ)于一個(gè) CommitLog 中。在 RocketMQ 的存儲(chǔ)架構(gòu)中,有三個(gè)重要的存儲(chǔ)文件,分別是 CommitLog、ConsumeQueue 和 IndexFile。
-
CommitLog
CommitLog 是存儲(chǔ)消息的主體。Producer 發(fā)送的消息都會(huì)順序?qū)懭?commitLog 文件,所以隨著寫入的消息增多,文件也會(huì)隨之變大。單個(gè)文件大小默認(rèn) 1G,文件名長(zhǎng)度為 20 位,左邊補(bǔ)零,剩余為起始偏移量。例如,00000000000000000000 代表了第一個(gè)文件,起始偏移量為 0,文件大小為 1G。當(dāng)?shù)谝粋€(gè)文件寫滿了,第二個(gè)文件為 00000000001073741824,起始偏移量為 1073741824,以此類推。存儲(chǔ)路徑為HOME/store/commitLog
。 -
ConsumeQueue
ConsumeQueue(邏輯消費(fèi)隊(duì)列) 可以看成基于 topic 的 commitLog 的索引文件。因?yàn)?CommitLog 是按照順序?qū)懭氲?#xff0c;不同的 topic 消息都會(huì)混淆在一起,而 Consumer 又是按照 topic 來(lái)消費(fèi)消息的,這樣的話勢(shì)必會(huì)去遍歷 commitLog 文件來(lái)過(guò)濾 topic,這樣性能肯定會(huì)非常差,所以 rocketMq 采用 ConsumeQueue 來(lái)提高消費(fèi)性能。即每個(gè) Topic 下的每個(gè) queueId 對(duì)應(yīng)一個(gè) Consumequeue,其中存儲(chǔ)了單條消息對(duì)應(yīng)在 commitLog 文件中的物理偏移量 offset,消息大小 size,消息 Tag 的 hash 值。存儲(chǔ)路徑為HOME/store/consumequeue/topic/queueId/fileName
。 -
IndexFile
IndexFile 提供了一種可以通過(guò) key(topicmsgId) 或時(shí)間區(qū)間來(lái)查詢消息的方法。他的存在主要是針對(duì)在客戶端 (生產(chǎn)者和消費(fèi)者) 和控制臺(tái)接口提供了根據(jù) key 查詢消息的實(shí)現(xiàn)。為了方便用戶查詢具體某條消息。IndexFile 的存儲(chǔ)結(jié)構(gòu)可以認(rèn)為是一個(gè) hashmap。存儲(chǔ)路徑為HOME/store/index/
.HOME/store/index/fileName
文件名 fileName 是以創(chuàng)建時(shí)的時(shí)間戳命名的。
我們?cè)谙胂?kafka 是怎么做的,對(duì)的,kafka 并沒(méi)有類似的煩惱,因?yàn)樗行畔⒍际沁B續(xù)的
總結(jié)起來(lái),RocketMQ 的存儲(chǔ)結(jié)構(gòu)設(shè)計(jì)非常復(fù)雜,但它通過(guò)合理的設(shè)計(jì)實(shí)現(xiàn)了高效的消息寫入和讀取性能。同時(shí),RocketMQ 也支持多種存儲(chǔ)方式,如本地存儲(chǔ)、分布式存儲(chǔ)和云存儲(chǔ)等,可以滿足不同場(chǎng)景下的需求。
Pulsar
架構(gòu)圖(分層+分片)
pulsar 相比與 kafka 與 rocketmq 最大的特點(diǎn)則是使用了分層和分片的架構(gòu),回想一下 kafka 與 rocketmq,一個(gè)服務(wù)節(jié)點(diǎn)即是計(jì)算節(jié)點(diǎn)也是服務(wù)節(jié)點(diǎn),節(jié)點(diǎn)有狀態(tài)使得平臺(tái)化、容器化困難、數(shù)據(jù)遷移、數(shù)據(jù)擴(kuò)縮容等運(yùn)維工作都變的復(fù)雜且困難。
-
分層:Pulsar 分離出了 Broker(服務(wù)層)和 Bookie(存儲(chǔ)層)架構(gòu),Broker 為無(wú)狀態(tài)服務(wù),用于發(fā)布和消費(fèi)消息,而 BookKeeper 專注于存儲(chǔ)。
-
分片 : 這種將存儲(chǔ)從消息服務(wù)中抽離出來(lái),使用更細(xì)粒度的分片(Segment)替代粗粒度的分區(qū)(Partition),為 Pulsar 提供了更高的可用性,更靈活的擴(kuò)展能力
服務(wù)層設(shè)計(jì)
Broker 集群在 Pulsar 中形成無(wú)狀態(tài)服務(wù)層。服務(wù)層是“無(wú)狀態(tài)的”,所有的數(shù)據(jù)信息都存儲(chǔ)在了 BookKeeper 上,所有的元信息都存儲(chǔ)在了 zookeeper 上,這樣使得一個(gè) broker 節(jié)點(diǎn)沒(méi)有任何的負(fù)擔(dān),這里的負(fù)擔(dān)有幾層含義:
- 容器化沒(méi)負(fù)擔(dān),broker 節(jié)點(diǎn)不用考慮任何數(shù)據(jù)狀態(tài)帶來(lái)的麻煩。
- 擴(kuò)容、縮容沒(méi)負(fù)擔(dān),當(dāng)請(qǐng)求量級(jí)突增或者降低的同時(shí),可以隨時(shí)的添加節(jié)點(diǎn)或者減少節(jié)點(diǎn)以動(dòng)態(tài)的調(diào)整資源,使得整體在一種“合適”的狀態(tài)。
- 故障轉(zhuǎn)移沒(méi)負(fù)擔(dān),當(dāng)一個(gè)節(jié)點(diǎn)宕機(jī)、服務(wù)不可用時(shí),可以通快速地轉(zhuǎn)移所負(fù)責(zé)的 topic 信息到別的基節(jié)點(diǎn)上,可以很好做到故障對(duì)外無(wú)感知。
存儲(chǔ)層設(shè)計(jì)
pulsar 使用了類似于 raft 的存儲(chǔ)方案,數(shù)據(jù)會(huì)并發(fā)的寫入多個(gè)存儲(chǔ)節(jié)點(diǎn)上,下圖為四存儲(chǔ)節(jié)點(diǎn)、三副本架構(gòu)。
broker2 節(jié)點(diǎn)當(dāng)前需要寫入 segment1 到 segment4 數(shù)據(jù),流程為: segment1 并發(fā)寫入 b1、b2、b3 數(shù)據(jù)節(jié)點(diǎn)、segment2 并發(fā)寫入 b2、b3、b4 數(shù)據(jù)節(jié)點(diǎn)、segment3 并發(fā)寫入 b3、b4、b1 數(shù)據(jù)節(jié)點(diǎn)、segment4 并發(fā)寫入 b1、b2、b4 數(shù)據(jù)節(jié)點(diǎn)。這種寫入方式稱為條帶化的寫入方式。
這種方式潛在的決定了數(shù)據(jù)的分布方式、通過(guò)路由算法,可以很快的找到對(duì)應(yīng)數(shù)據(jù)的位置信息,在數(shù)據(jù)遷移與恢復(fù)中起到重要的作用。
擴(kuò)容
當(dāng)存儲(chǔ)節(jié)點(diǎn)資源不足的時(shí)候,常規(guī)的運(yùn)維操作就是動(dòng)態(tài)擴(kuò)容,相比 kafka 與 rocketmq、pulsar 不用考慮原數(shù)據(jù)的"人為"搬移工作,而是動(dòng)態(tài)新增一個(gè)或者多個(gè)節(jié)點(diǎn),broker 在寫入數(shù)據(jù)時(shí)通過(guò)路有算法優(yōu)先寫入資源充足的節(jié)點(diǎn),使得整體的資源利用力達(dá)到一個(gè)平衡的狀態(tài),如圖所示。
以下是一張 kafka 分區(qū)和 pulsar 分片的一張對(duì)比圖,左圖是 kafka 的數(shù)據(jù)存儲(chǔ)特點(diǎn),因?yàn)閿?shù)據(jù)和分區(qū)的強(qiáng)綁定,導(dǎo)致了第三艘小船沒(méi)有任何的數(shù)據(jù),而相比 pulsar,數(shù)據(jù)不和任何存儲(chǔ)節(jié)點(diǎn)綁定,而是實(shí)時(shí)的動(dòng)態(tài)寫入,從數(shù)據(jù)分布和資源利用來(lái)說(shuō),要做的更好。
容災(zāi)
當(dāng) bookie4 存儲(chǔ)節(jié)點(diǎn)宕機(jī)不可用時(shí),如何恢復(fù)節(jié)點(diǎn)數(shù)據(jù)?這里只需要增加新的存儲(chǔ)節(jié)點(diǎn),并且拷貝 bookie2 與 bookie3 上的數(shù)據(jù)即可,這個(gè)過(guò)程對(duì)外是無(wú)感知的,實(shí)現(xiàn)了平滑切換,如圖所示
小結(jié)
每種設(shè)計(jì)都有其特定的優(yōu)勢(shì)和局限,適應(yīng)不同場(chǎng)景和需求。因此,在選用產(chǎn)品時(shí),需要根據(jù)實(shí)際業(yè)務(wù)場(chǎng)景和需求,權(quán)衡各種設(shè)計(jì)的優(yōu)缺點(diǎn),作出最合適的選擇。這種選擇過(guò)程正是體現(xiàn)了設(shè)計(jì)與需求之間的平衡。所以,針對(duì)不同場(chǎng)景選擇合適的產(chǎn)品是非常關(guān)鍵的。