前面我們一起學(xué)習(xí)了分布式通信中的遠(yuǎn)程調(diào)用(分布式通信技術(shù)之遠(yuǎn)程調(diào)用:RPC)抡医。遠(yuǎn)程調(diào)用的核心是在網(wǎng)絡(luò)服務(wù)層封裝了通信協(xié)議、序列化早敬、傳輸?shù)炔僮骷缮担層脩粽{(diào)用遠(yuǎn)程服務(wù)如同進(jìn)行本地調(diào)用一樣。
其實(shí)搞监,這種方式就是通過網(wǎng)絡(luò)服務(wù)層的封裝實(shí)現(xiàn)了不同機(jī)器上不同進(jìn)程之間的直接通信水孩,因?yàn)槭侵苯油ㄐ牛酝ㄟ^線程阻塞的方式實(shí)現(xiàn)同步調(diào)用比較容易琐驴,因此通常被用于同步調(diào)用俘种。比如,機(jī)器 1 上的進(jìn)程 A 調(diào)用機(jī)器 2 上的進(jìn)程 B绝淡,進(jìn)程 A 被掛起宙刘,進(jìn)程 B 開始執(zhí)行,當(dāng)進(jìn)程 B 將值返回給 A 時(shí)牢酵,A 繼續(xù)執(zhí)行悬包。
雖然這種方式也可以用于異步通信,但因?yàn)檫M(jìn)程之間是直接交互的馍乙,所以當(dāng)進(jìn)程比較多時(shí)布近,會(huì)導(dǎo)致進(jìn)程維護(hù)通信的復(fù)雜度非常高,且一個(gè)進(jìn)程通信接口改變丝格,與其通信的進(jìn)程都會(huì)受到影響撑瞧。
隨著業(yè)務(wù)和分布式計(jì)算規(guī)模的逐漸增大和復(fù)雜化,遠(yuǎn)程調(diào)用模型有點(diǎn)心有余力而不足了显蝌,為此出現(xiàn)了專門的異步通信模式预伺,也就是消息發(fā)布訂閱模式和消息隊(duì)列模式。在接下來的兩篇文章中,我將與你詳細(xì)講述這兩種通信模式扭屁。
什么是發(fā)布訂閱算谈?
其實(shí),發(fā)布訂閱的思想在我們的生活中隨處可見料滥。
比如然眼,學(xué)術(shù)屆電子論文的訂閱方式。通常葵腹,各個(gè)會(huì)議方或出版社會(huì)將學(xué)術(shù)論文發(fā)布到論文網(wǎng)站(或平臺(tái)上高每,比如 ACM、知網(wǎng)等)践宴,然后學(xué)生或老師向論文網(wǎng)站訂閱自己感興趣的論文鲸匿,比如分布式相關(guān)的、AI 相關(guān)的等阻肩。
當(dāng)會(huì)議方或出版社將論文發(fā)布到論文網(wǎng)站后带欢,論文網(wǎng)站會(huì)根據(jù)訂閱信息,將相應(yīng)的論文推送給訂閱者(比如通過郵件的方式)烤惊。這里的會(huì)議方或出版社就相當(dāng)于生產(chǎn)者乔煞,負(fù)責(zé)發(fā)布論文,學(xué)生或老師就相當(dāng)于消費(fèi)者柒室,而論文網(wǎng)站就相當(dāng)于一個(gè)消息中心渡贾。
?
由此可以看出,發(fā)布訂閱的三要素是生產(chǎn)者雄右、消費(fèi)者和消息中心空骚,生產(chǎn)者負(fù)責(zé)產(chǎn)生數(shù)據(jù)放到消息中心,消費(fèi)者向消息中心訂閱自己感興趣的消息擂仍,當(dāng)發(fā)布者推送數(shù)據(jù)到消息中心后囤屹,消息中心根據(jù)消費(fèi)者訂閱情況將相關(guān)數(shù)據(jù)推送給對(duì)應(yīng)的訂閱者。這種將數(shù)據(jù)送到消費(fèi)者手里的行為防楷,是不是和我們現(xiàn)在常說的“送貨上門”一樣呢牺丙?
發(fā)布訂閱的原理及應(yīng)用
這個(gè)論文訂閱的例子,充分體現(xiàn)了發(fā)布訂閱的思想复局。接下來冲簿,我就與你進(jìn)一步分析下發(fā)布訂閱的原理吧。
發(fā)布訂閱的基本工作原理
在分布式通信領(lǐng)域中亿昏,消息系統(tǒng)一般有兩種典型的模式峦剔。一種是點(diǎn)對(duì)點(diǎn)模式(P2P,Point to Point)角钩,另一種是發(fā)布訂閱模式(Pub/Sub吝沫,Publish/Subscribe)呻澜。接下來,我們就一起看看這兩種模式惨险,以幫助你深入理解發(fā)布訂閱模式的原理羹幸。
首先,我們一起看一下什么是點(diǎn)對(duì)點(diǎn)模式辫愉。
生產(chǎn)者將消息發(fā)送到消息中心栅受,然后消費(fèi)者從消息中心取出對(duì)應(yīng)的消息進(jìn)行消費(fèi)。消息被消費(fèi)后恭朗,消息中心不再存儲(chǔ)該消息屏镊,因此其他消費(fèi)者無法再消費(fèi)該消息。也就是說痰腮,點(diǎn)對(duì)點(diǎn)模式雖然支持多個(gè)消費(fèi)者而芥,但一個(gè)消息只能被一個(gè)消費(fèi)者消費(fèi),不允許重復(fù)消費(fèi)膀值。
這種模式就好比棍丐,限定了每篇論文只能被一個(gè)用戶消費(fèi),比如現(xiàn)在有一篇分布式相關(guān)的論文虫腋,這篇論文推送給學(xué)生 A 之后骄酗,論文網(wǎng)站就必須將其刪除或下架稀余,也就是說其他用戶無法再獲取或閱讀該論文了悦冀。(當(dāng)然實(shí)際情況并不是這樣的,這里只是為了方便你理解睛琳,我做了相應(yīng)的假設(shè)盒蟆。)
?
接下來,我們看一下發(fā)布訂閱模式师骗。
生產(chǎn)者可以發(fā)送消息到消息中心历等,而消息中心通常以主題(Topic)進(jìn)行劃分,每條消息都會(huì)有相應(yīng)的主題辟癌,消息會(huì)被存儲(chǔ)到自己所屬的主題中寒屯,訂閱該主題的所有消費(fèi)者均可獲得該消息進(jìn)行消費(fèi)。
?
比如圖中假設(shè)生產(chǎn)者 1 發(fā)布一個(gè) Topic 相關(guān)數(shù)據(jù)或消息黍少,消費(fèi)者 1~3 均訂閱了該 Topic 消息寡夹,則該消息會(huì)推送消費(fèi)者 1~3,也就是說同一個(gè)消息被 3 個(gè)消費(fèi)者消費(fèi)了厂置。
這種模式就好比菩掏,不同的方向代表不同的主題,比如分布式領(lǐng)域代表一個(gè)主題昵济,當(dāng)會(huì)議方或出版社發(fā)布分布式相關(guān)的論文時(shí)智绸,該論文會(huì)被存儲(chǔ)到論文網(wǎng)站的分布式主題下野揪,同時(shí)學(xué)生或老師也會(huì)根據(jù)自己感興趣的主題進(jìn)行訂閱。如果學(xué)生 A 訂閱了分布式主題瞧栗,那么當(dāng)會(huì)議方或出版社發(fā)布分布式相關(guān)的論文后斯稳,會(huì)議網(wǎng)站會(huì)將這些論文推送給學(xué)生 A。
與點(diǎn)對(duì)點(diǎn)模式相比迹恐,發(fā)布訂閱模式中一個(gè)消息可以被多個(gè)消費(fèi)者進(jìn)行消費(fèi)平挑,這也是和點(diǎn)對(duì)點(diǎn)模式的本質(zhì)區(qū)別。
以上就是發(fā)布訂閱中的兩種典型模式了
在分布式系統(tǒng)中系草,通常會(huì)為多用戶服務(wù)通熄,而多個(gè)用戶通常會(huì)關(guān)注相同類型的消息,因此發(fā)布訂閱模式在分布式系統(tǒng)中非常常見找都。接下來唇辨,我再結(jié)合經(jīng)典的分布式發(fā)布訂閱消息系統(tǒng) Kafka 的發(fā)布訂閱原理及工作機(jī)制,來幫助你鞏固對(duì)發(fā)布訂閱的理解能耻。
Kafka 發(fā)布訂閱原理及工作機(jī)制
Kafka 是一種典型的發(fā)布訂閱消息系統(tǒng)赏枚,其系統(tǒng)架構(gòu)也是包括生產(chǎn)者、消費(fèi)者和消息中心三部分晓猛。
生產(chǎn)者(Producer)負(fù)責(zé)發(fā)布消息到消息中心饿幅,比如電子論文的會(huì)議方或出版社;
消費(fèi)者(Consumer)向消息中心訂閱自己感興趣的消息戒职,獲得數(shù)據(jù)后進(jìn)行數(shù)據(jù)處理栗恩,比如訂閱電子論文的老師或?qū)W生;
消息中心(Broker)負(fù)責(zé)存儲(chǔ)生產(chǎn)者發(fā)布的消息和管理消費(fèi)者訂閱信息洪燥,根據(jù)消費(fèi)者訂閱信息磕秤,將消息推送給消費(fèi)者,比如論文網(wǎng)站捧韵。在 Kafka 中市咆,消息中心本質(zhì)上就是一組服務(wù)器,也可以說是 Kafka 集群再来。
Kafka 的架構(gòu)圖蒙兰,如下所示:
?
可以看到,Kafka 中除了 Producer芒篷、Broker搜变、Consumer 之外,還有一個(gè) ZooKeeper 集群梭伐。Zookeeper 集群用來協(xié)調(diào)和管理 Broker 和 Consumer痹雅,實(shí)現(xiàn)了 Broker 和 Consumer 的解耦,并為系統(tǒng)提供可靠性保證糊识。
ZooKeeper 集群可以看作是一個(gè)提供了分布式服務(wù)協(xié)同能力的第三方組件绩社,Consumer 和 Broker 啟動(dòng)時(shí)均會(huì)向 ZooKeeper 進(jìn)行注冊(cè)摔蓝,由 ZooKeeper 進(jìn)行統(tǒng)一管理和協(xié)調(diào)。
ZooKeeper 中會(huì)存儲(chǔ)一些元數(shù)據(jù)信息愉耙,比如對(duì)于 Broker贮尉,會(huì)存儲(chǔ)主題對(duì)應(yīng)哪些分區(qū)(Partition),每個(gè)分區(qū)的存儲(chǔ)位置等朴沿;對(duì)于 Consumer猜谚,會(huì)存儲(chǔ)消費(fèi)組(Consumer Group)中包含哪些 Consumer,每個(gè) Consumer 會(huì)負(fù)責(zé)消費(fèi)哪些分區(qū)等赌渣。
接下來魏铅,我們看看分區(qū)和消費(fèi)組的原理和作用吧。
從上面的介紹可以看出坚芜,Broker 負(fù)責(zé)存儲(chǔ)消息數(shù)據(jù)览芳,Consumer 負(fù)責(zé)消費(fèi)數(shù)據(jù),Consumer 消費(fèi)數(shù)據(jù)的能力會(huì)影響 Broker 數(shù)據(jù)存儲(chǔ)是否溢出的問題鸿竖。若 Consumer 消費(fèi)太慢沧竟,會(huì)導(dǎo)致 Broker 存儲(chǔ)溢出,Broker 就會(huì)丟棄一部分消息缚忧。
因此悟泵,Broker 和 Consumer 是 Kafka 的核心。接下來闪水,我將帶你進(jìn)一步了解 Kafka 中 Broker 和 Consumer 的關(guān)鍵技術(shù)糕非,如下圖所示:
?
首先,我們看一下 Broker敦第。
在 Kafka 中峰弹,為了解決消息存儲(chǔ)的負(fù)載均衡和系統(tǒng)可靠性問題,所以引入了主題和分區(qū)的概念芜果。其中,主題是一個(gè)邏輯概念融师,指的是消息類型或數(shù)據(jù)類型右钾,就好比電子論文案例所講的分布式是一個(gè)主題。
而分區(qū)是針對(duì)主題而言的旱爆,指的是一個(gè)主題的內(nèi)容可以被劃分成多個(gè)集合舀射,分布在不同的 Broker 上,不同的 Broker 在不同的節(jié)點(diǎn)上怀伦。這里的集合就是分區(qū)脆烟,其中同一個(gè)分區(qū)只屬于一個(gè) Broker。
那么房待,分區(qū)有什么好處呢邢羔?
在我看來驼抹,分區(qū)的好處主要包括如下兩點(diǎn):
實(shí)現(xiàn)負(fù)載均衡,避免單個(gè) Broker 上的負(fù)載過高拜鹤。比如框冀,Topic 0 被分為 Partiton-0、Partiton-1 和 Partiton-2 三個(gè)分區(qū)敏簿,分別分布在 Broker 0明也、Broker 1 和 Broker 2 上。這惯裕,就使得 Topic 0 的消息可以分布在這 3 個(gè)分區(qū)中温数,實(shí)現(xiàn)負(fù)載均衡。
實(shí)現(xiàn)消息的備份蜻势,從而保證系統(tǒng)的高可靠帆吻。比如,Topic 1 包含兩個(gè)分區(qū) Partiton-0咙边、Partiton-1猜煮,每個(gè)分區(qū)內(nèi)容一致,分別存儲(chǔ)在 Broker 0 和 Broker 1 上败许,借此實(shí)現(xiàn)了數(shù)據(jù)備份王带。
接下來,我們?cè)倏纯?b>Consumer吧市殷。
Kafka 中的消費(fèi)組愕撰,指的是多個(gè)消費(fèi)者的一個(gè)集合。一個(gè)消費(fèi)組中的消費(fèi)者共同消費(fèi)主題消息醋寝,并且主題中每個(gè)消息只可以由消費(fèi)組中的某一個(gè)消費(fèi)者進(jìn)行消費(fèi)搞挣。
引入消費(fèi)組的目的是什么呢?我們知道音羞,在消息過多的情況下囱桨,單個(gè)消費(fèi)者消費(fèi)能力有限時(shí),會(huì)導(dǎo)致消費(fèi)效率過低嗅绰,從而導(dǎo)致 Broker 存儲(chǔ)溢出舍肠,丟棄一部分消息。Kafka 為了解決這個(gè)問題窘面,所以引入了消費(fèi)組翠语。
這樣一來,我們對(duì)發(fā)布訂閱的基本工作機(jī)制就比較清楚了财边。接下來肌括,我們?cè)俳Y(jié)合電商購物平臺(tái)的例子,來看看發(fā)布訂閱技術(shù)的具體應(yīng)用吧酣难。
發(fā)布訂閱實(shí)踐應(yīng)用
假設(shè)在電商購物平臺(tái)(為了方便理解谍夭,我對(duì)電商購物平臺(tái)做了一定的簡(jiǎn)化)中黑滴,用戶首先在訂單系統(tǒng)下單,下單后庫存系統(tǒng)會(huì)進(jìn)行出貨慧库,通知系統(tǒng)則負(fù)責(zé)通知用戶跷跪,整個(gè)流程可以用發(fā)布訂閱的模式進(jìn)行,如下圖所示:
?
訂單系統(tǒng)對(duì)應(yīng)發(fā)布訂閱模式中的生產(chǎn)者齐板,消息中心有個(gè)主題專門存放下單信息吵瞻,每次用戶下單后,訂單系統(tǒng)會(huì)向該主題寫入數(shù)據(jù)甘磨;
庫存系統(tǒng)和通知系統(tǒng)對(duì)應(yīng)發(fā)布訂閱模式中的消費(fèi)者橡羞,它們會(huì)向消息中心訂閱下單信息相關(guān)的主題;
訂單系統(tǒng)向消息中心發(fā)布訂單信息后济舆,庫存系統(tǒng)和通知系統(tǒng)都會(huì)獲取到相應(yīng)的下單信息卿泽,然后進(jìn)行各自后續(xù)的操作,即庫存系統(tǒng)進(jìn)行出貨滋觉,通知系統(tǒng)通過短信或郵件等方式通知用戶签夭。
接下來,我們總結(jié)下發(fā)布訂閱模式的關(guān)鍵特征吧椎侠。
實(shí)現(xiàn)了系統(tǒng)解耦第租,易于維護(hù)。生產(chǎn)者 / 發(fā)布者只負(fù)責(zé)消息的發(fā)布我纪,不需要知道訂閱者 / 消費(fèi)者的數(shù)量慎宾,也不需要知道訂閱者 / 消費(fèi)者獲取消息用來做什么,而訂閱者 / 消費(fèi)者也不需要知道什么時(shí)候生產(chǎn)者 / 發(fā)布者會(huì)發(fā)布消息浅悉。
所以趟据,生產(chǎn)者 / 發(fā)布者和訂閱者 / 消費(fèi)者互相獨(dú)立,進(jìn)而實(shí)現(xiàn)了系統(tǒng)解耦术健,每個(gè)部分可以單獨(dú)維護(hù)汹碱,減少了因?yàn)樯a(chǎn)者和消費(fèi)者的耦合引入的一些相互影響。比如苛坚,如果兩者耦合在一起比被,當(dāng)生產(chǎn)者邏輯更改需要修改代碼時(shí),消費(fèi)者部分的代碼也受影響泼舱,因此每個(gè)部分單獨(dú)維護(hù)降低了維護(hù)的復(fù)雜度。
實(shí)現(xiàn)了異步執(zhí)行枷莉,避免高負(fù)載娇昙。生產(chǎn)者 / 發(fā)布者發(fā)布消息到消息中心,當(dāng)消息超過消息中心可以存儲(chǔ)的容量后笤妙,消息中心會(huì)丟棄掉超出的消息冒掌,這樣系統(tǒng)就不會(huì)因?yàn)橄?shù)量多而導(dǎo)致系統(tǒng)故障噪裕。
總結(jié),我首先通過論文訂閱的案例股毫,與你介紹了什么是發(fā)布訂閱以及發(fā)布訂閱的基本原理膳音,然后介紹了一個(gè)經(jīng)典的分布式發(fā)布訂閱消息系統(tǒng) Kafka,最后以一個(gè)電商購物平臺(tái)的案例描述了發(fā)布訂閱模式的應(yīng)用場(chǎng)景铃诬。希望對(duì)你有幫助
下一篇預(yù)告:分布式通信消息隊(duì)列
在下方公眾號(hào)【架構(gòu)師修煉】菜單中可自行獲取專屬架構(gòu)視頻資料祭陷,包括不限于 java架構(gòu)、python系列趣席、人工智能系列兵志、架構(gòu)系列,以及最新面試宣肚、小程序想罕、大前端均無私奉獻(xiàn),你會(huì)感謝我的哈
往期精選
分布式通信技術(shù)之遠(yuǎn)程調(diào)用:RPC
分布式流水線計(jì)算模式霉涨,學(xué)機(jī)器學(xué)習(xí)的同學(xué)要注意了
分布式計(jì)算模式之Actor按价,助你徹底搞定分布式計(jì)算技術(shù)
分布式計(jì)算技術(shù)之流計(jì)算Stream,打通實(shí)時(shí)數(shù)據(jù)處理
分布式計(jì)算技術(shù)MapReduce 詳細(xì)解讀
今天來設(shè)計(jì)一套高可用高并發(fā)笙瑟、海量存儲(chǔ)以及可伸縮的消息中間件生產(chǎn)架構(gòu)
消息隊(duì)列Broker主從架構(gòu)詳細(xì)設(shè)計(jì)方案楼镐,這一篇就搞定主從架構(gòu)
消息中間件路由中心你會(huì)設(shè)計(jì)嗎,不會(huì)就來學(xué)學(xué)
【分布式技術(shù)】分布式系統(tǒng)調(diào)度架構(gòu)之兩層調(diào)度鸠蚪,解決單體調(diào)度問題
數(shù)據(jù)庫分庫分表师溅,手把手教你怎么去動(dòng)態(tài)擴(kuò)容索容
?