国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

架構(gòu)師的36項(xiàng)修煉-03架構(gòu)核心技術(shù)之分布式消息隊(duì)列

這篇具有很好參考價(jià)值的文章主要介紹了架構(gòu)師的36項(xiàng)修煉-03架構(gòu)核心技術(shù)之分布式消息隊(duì)列。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

本課時(shí)的主題是分布式消息隊(duì)列,分布式消息隊(duì)列的知識(shí)結(jié)構(gòu)如下圖。
架構(gòu)師的36項(xiàng)修煉-03架構(gòu)核心技術(shù)之分布式消息隊(duì)列,java,架構(gòu),分布式,java,后端
本課時(shí)主要介紹以下內(nèi)容。

&同步架構(gòu)和異步架構(gòu)的區(qū)別。異步架構(gòu)的主要組成部分:消息生產(chǎn)者、消息消費(fèi)者、分布式消息隊(duì)列。異步架構(gòu)的兩種主要模型:點(diǎn)對點(diǎn)模型和發(fā)布訂閱模型。

&分布式消息隊(duì)列異步架構(gòu)的好處:異步處理實(shí)現(xiàn)快速響應(yīng);消費(fèi)者易于伸縮;高并發(fā)訪問壓力的時(shí)削峰填谷,減輕訪問高峰的系統(tǒng)負(fù)載壓力;隔離失敗任務(wù),消費(fèi)者處理任務(wù)失敗,不會(huì)影響主業(yè)務(wù)流程;業(yè)務(wù)邏輯解耦,系統(tǒng)易于開發(fā)和維護(hù)。

&異步架構(gòu)的挑戰(zhàn):消息無序,競態(tài)條件,系統(tǒng)復(fù)雜度提高。

&使用分布式消息隊(duì)列異步架構(gòu)的反模式:消息隊(duì)列阻塞式調(diào)用,生產(chǎn)者消費(fèi)者顯式依賴,缺乏壞消息處理機(jī)制。

&常用的消息隊(duì)列產(chǎn)品:RabbitMQ,ActiveMQ,RocketMQ,Kafka 等。

同步調(diào)用與異步調(diào)用

同步調(diào)用

先看一下什么是同步調(diào)用。所謂的同步調(diào)用,就是說從請求的發(fā)起一直到最終的處理完成期間,請求的調(diào)用方一直在同步阻塞,等待調(diào)用的處理完成。下圖所示的例子中,客戶端代碼 ClientCode,需要執(zhí)行發(fā)送郵件 sendEmail 這樣一個(gè)操作,它會(huì)調(diào)用 EmailService 進(jìn)行發(fā)送,而 EmailService 會(huì)調(diào)用 SmtpEmailAdapter 類來進(jìn)行處理,這個(gè)類會(huì)調(diào)用遠(yuǎn)程的一個(gè)服務(wù),通過 SMTP 和 TCP 協(xié)議發(fā)送請求。
架構(gòu)師的36項(xiàng)修煉-03架構(gòu)核心技術(shù)之分布式消息隊(duì)列,java,架構(gòu),分布式,java,后端
而遠(yuǎn)程服務(wù)器收到消息以后會(huì)對消息進(jìn)行一系列的操作,然后將郵件發(fā)送出去,再進(jìn)行返回。Adapter 收到返回后,再返回給 EmailService。EmailService 收到返回后再把返回結(jié)果返回給 ClientCode。

ClientCode 在 sendEmail 發(fā)出請求后,就一直都阻塞在這里,等待最終調(diào)用結(jié)果的返回,是成功還是失敗。因?yàn)檫@個(gè)過程是阻塞等待的,所以這個(gè)過程是同步調(diào)用。

異步調(diào)用
與同步調(diào)用相反的是異步調(diào)用。異步調(diào)用過程,如下圖所示,用戶 ClientCode 調(diào)用 EmailService 以后,EmailService 會(huì)把這個(gè)調(diào)用請求發(fā)送給消息隊(duì)列,然后就立即返回了。ClientCode 收到返回以后繼續(xù)向下處理,不會(huì)繼續(xù)阻塞等待,實(shí)際上消息發(fā)送到 Queue 后,還沒有被處理。可以看到后面的消息消費(fèi),其實(shí)要比 EmailService 返回可能還要晚一點(diǎn),EmailService 返回以后消息才會(huì)被消費(fèi)處理。
架構(gòu)師的36項(xiàng)修煉-03架構(gòu)核心技術(shù)之分布式消息隊(duì)列,java,架構(gòu),分布式,java,后端
QueueConsumer 消息隊(duì)列的消費(fèi)者,從消息隊(duì)列中取出這個(gè)消息,再把這個(gè)消息發(fā)送給 SmtpAdapter,也就是調(diào)用 SmtpAdapter,處理邏輯跟同步調(diào)用一樣。SmtpAdapter 通過 SMTP 的通訊協(xié)議,把消息發(fā)送給遠(yuǎn)程的一個(gè)服務(wù)器,進(jìn)行郵件發(fā)送,通過 RemoteServer 進(jìn)行處理,處理完了收到返回,再把返回結(jié)果通知消息隊(duì)列 Queue。

在這個(gè)過程中,客戶端的調(diào)用,也就是應(yīng)用程序的調(diào)用,和業(yè)務(wù)邏輯真正發(fā)送郵件的操作是不同步的。在進(jìn)行郵件發(fā)送操作的處理過程中,客戶端的代碼已經(jīng)返回了,它可以繼續(xù)進(jìn)行自己的后續(xù)操作,而不需要等待郵件的發(fā)送,這就叫做異步調(diào)用。

消息隊(duì)列構(gòu)建異步調(diào)用架構(gòu)
使用異步調(diào)用架構(gòu)的主要手段,就是通過消息隊(duì)列構(gòu)建。架構(gòu)圖如下圖所示。
架構(gòu)師的36項(xiàng)修煉-03架構(gòu)核心技術(shù)之分布式消息隊(duì)列,java,架構(gòu),分布式,java,后端
消息的生產(chǎn)者將消息發(fā)送到消息隊(duì)列以后,由消息的消費(fèi)者從消息隊(duì)列中獲取消息,然后進(jìn)行業(yè)務(wù)邏輯的處理,消息的生產(chǎn)者和消費(fèi)者是異步處理的,彼此不會(huì)等待阻塞,所以叫做異步架構(gòu)。

使用消息隊(duì)列構(gòu)建一個(gè)異步調(diào)用架構(gòu),你需要了解 3 個(gè)角色:一是消息的生產(chǎn)者,二是消息隊(duì)列,三是消息的消費(fèi)者。
架構(gòu)師的36項(xiàng)修煉-03架構(gòu)核心技術(shù)之分布式消息隊(duì)列,java,架構(gòu),分布式,java,后端
消息生產(chǎn)者

消息的生產(chǎn)者是客戶端應(yīng)用程序代碼的一部分,用來初始化異步調(diào)用處理流程。在消息隊(duì)列的處理中,生產(chǎn)者的職責(zé)非常少,它要做的就是創(chuàng)建一個(gè)合法的消息,并把這個(gè)消息發(fā)送到消息隊(duì)列中,由應(yīng)用開發(fā)者決定生產(chǎn)者的代碼在哪里執(zhí)行,什么時(shí)候發(fā)送消息。

消息隊(duì)列

消息隊(duì)列異步架構(gòu)的另一個(gè)重要組成部分就是消息隊(duì)列,消息隊(duì)列是消息發(fā)送的目的地,也是發(fā)給消費(fèi)者過程中的一個(gè)緩沖。消息隊(duì)列實(shí)現(xiàn)的方法有好多種,可以用共享文件夾,也可以用關(guān)系數(shù)據(jù)庫或者 NoSQL 系統(tǒng),當(dāng)然最主要的還是使用專門的分布式消息隊(duì)列服務(wù)器。

消息消費(fèi)者

業(yè)務(wù)架構(gòu)的第三個(gè)重要角色就是消息的消費(fèi)者。消息的消費(fèi)者從消息隊(duì)列中接收并處理消息,也是由應(yīng)用開發(fā)者實(shí)現(xiàn)的,但是一個(gè)異步處理的組件。消息的消費(fèi)者不需要知道生產(chǎn)者存在,它只依賴消息隊(duì)列中的消息。消息的消費(fèi)者通常部署在獨(dú)立的服務(wù)器上,和消息的生產(chǎn)者完全隔離,并且可以通過添加硬件的方式進(jìn)行伸縮。

點(diǎn)對點(diǎn)模型

知道以上 3 種主要角色之后,使用消息隊(duì)列構(gòu)建異步的調(diào)用架構(gòu),還需要知道兩種模型:點(diǎn)對點(diǎn)模型和發(fā)布訂閱模型。

首先來看點(diǎn)對點(diǎn)模型。消費(fèi)者和生產(chǎn)者只需要知道消息隊(duì)列的名字,生產(chǎn)者發(fā)送消息到消息隊(duì)列中,而消息隊(duì)列的另一端是多個(gè)消費(fèi)者競爭消費(fèi)消息,每個(gè)到達(dá)消息隊(duì)列的消息只會(huì)被路由到一個(gè)消費(fèi)者中去,所以消費(fèi)者看到的是全部消息的一個(gè)子集。如下圖所示,消息的生產(chǎn)者有多個(gè),消息的消費(fèi)者也有多個(gè),多個(gè)生產(chǎn)者將消息發(fā)送到消息隊(duì)列中,而有多個(gè)消費(fèi)者去消息隊(duì)列中對消息進(jìn)行競爭性的消費(fèi)。每條消息只會(huì)被一個(gè)消費(fèi)者消費(fèi),每個(gè)消費(fèi)者只會(huì)消費(fèi)消息隊(duì)列中的一部分消息。
架構(gòu)師的36項(xiàng)修煉-03架構(gòu)核心技術(shù)之分布式消息隊(duì)列,java,架構(gòu),分布式,java,后端
發(fā)布訂閱模型

再來看發(fā)布訂閱模型。在發(fā)布訂閱模型中,消息可能被發(fā)送到不止一個(gè)消費(fèi)者,生產(chǎn)者發(fā)送消息到一個(gè)主題,而不是隊(duì)列中。消息被發(fā)布到主題后,就會(huì)被克隆給每一個(gè)訂閱它的消費(fèi)者,每個(gè)消費(fèi)者接收一份消息復(fù)制到自己的私有隊(duì)列。消費(fèi)者可以獨(dú)立于其他消費(fèi)者使用自己訂閱的消息,消費(fèi)者之間不會(huì)競爭消息。常用的分布式消息隊(duì)列都支持發(fā)布訂閱模型,也就是說消息的發(fā)布訂閱模型是分布式消息隊(duì)列的一個(gè)功能特性。
架構(gòu)師的36項(xiàng)修煉-03架構(gòu)核心技術(shù)之分布式消息隊(duì)列,java,架構(gòu),分布式,java,后端
兩種模型對比

兩種模型結(jié)合對比來看,通常使用點(diǎn)對點(diǎn)模型的,是一些耗時(shí)較長的、邏輯相對獨(dú)立的業(yè)務(wù),比如前面講到的發(fā)送郵件這樣一個(gè)操作。因?yàn)榘l(fā)送郵件比較耗時(shí),而且應(yīng)用程序其實(shí)并不太關(guān)心郵件發(fā)送是否成功,發(fā)送郵件的邏輯也相對比較獨(dú)立,所以它只需要把郵件消息丟到消息隊(duì)列中就可以返回了。消費(fèi)者也不需要關(guān)心是哪個(gè)生產(chǎn)者去發(fā)送的郵件,它只需要把郵件消息內(nèi)容取出來以后進(jìn)行消費(fèi),通過遠(yuǎn)程服務(wù)器將郵件發(fā)送出去就可以了。而且每個(gè)郵件只需要被發(fā)送一次。所以消息只被一個(gè)消費(fèi)者消費(fèi)就可以了。

相對應(yīng)的另一些情況,比如新用戶注冊,就適合使用發(fā)布訂閱模型。一個(gè)新用戶注冊成功以后,需要給用戶發(fā)送一封激活郵件,發(fā)送一條歡迎短信,還需要將用戶注冊數(shù)據(jù)寫入數(shù)據(jù)庫,甚至需要將新用戶信息發(fā)送給關(guān)聯(lián)企業(yè)的系統(tǒng),比如淘寶新用戶信息發(fā)送給支付寶,這樣允許用戶可以一次注冊就能登錄使用多個(gè)關(guān)聯(lián)產(chǎn)品。那么對于新用戶注冊這樣一個(gè)消息,就需要使用按主題發(fā)布的方式,也就是發(fā)布訂閱模型這種方式。一個(gè)新用戶注冊,會(huì)把注冊消息發(fā)送給一個(gè)主題,多種消費(fèi)者可以訂閱這個(gè)主題,比如發(fā)送郵件的消費(fèi)者、發(fā)送短信的消費(fèi)者、將注冊信息寫入數(shù)據(jù)庫的消費(fèi)者,跨系統(tǒng)同步消息的消費(fèi)者等。

消息隊(duì)列的好處

通過前面的例子,可以看出消息隊(duì)列有這樣的一些優(yōu)點(diǎn),包括異步處理、易伸縮、使峰值變平緩、失敗隔離及自我修復(fù)、解耦。

異步處理

第一個(gè)好處是實(shí)現(xiàn)異步處理,提升處理性能。對一些比較耗時(shí)的操作,我們可以把處理過程通過消息隊(duì)列進(jìn)行異步處理。這樣做一個(gè)顯而易見的好處就是,可以推遲耗時(shí)操作的處理,使耗時(shí)操作異步化,而不必阻塞客戶端的程序,客戶端的程序在得到處理結(jié)果之前就可以繼續(xù)執(zhí)行,從而提高客戶端程序的處理性能。

易伸縮

第二個(gè)好處,它可以讓系統(tǒng)獲得更好的伸縮性。因?yàn)楹臅r(shí)的任務(wù)可以通過分布式消息隊(duì)列向多臺(tái)消費(fèi)者服務(wù)器并行發(fā)送消息,然后在很多臺(tái)消費(fèi)者服務(wù)器上并行處理消息,也就是說可以在多臺(tái)物理服務(wù)器上運(yùn)行消費(fèi)者。那么當(dāng)負(fù)載上升的時(shí)候,可以很容易地添加更多的機(jī)器成為消費(fèi)者。

如下圖所示,用戶上傳文件后,通過發(fā)布消息的方式,通知后端的消費(fèi)者獲取數(shù)據(jù)、讀取文件,進(jìn)行異步的文件處理操作。那么當(dāng)前端發(fā)布更多文件的時(shí)候,或者處理邏輯比較復(fù)雜的時(shí)候,就可以通過添加后端的消費(fèi)者服務(wù)器,增強(qiáng)系統(tǒng)的處理能力。
架構(gòu)師的36項(xiàng)修煉-03架構(gòu)核心技術(shù)之分布式消息隊(duì)列,java,架構(gòu),分布式,java,后端
使峰值平緩

使用消息隊(duì)列的第三個(gè)好處是可以平衡流量峰值,削峰填谷。使用消息隊(duì)列,即便是訪問流量持續(xù)的增長,系統(tǒng)依然可以持續(xù)地接收請求。這種情況下,雖然生產(chǎn)者發(fā)布消息的速度比消費(fèi)者消費(fèi)消息的速度快,但是可以持續(xù)地將消息納入到消息隊(duì)列中,用消息隊(duì)列作為消息的緩沖,因此短時(shí)間內(nèi),發(fā)布者不會(huì)受到消費(fèi)處理能力的影響。

如下圖所示,因?yàn)橄⒌纳a(chǎn)者是直接面向用戶請求的,而用戶的請求訪問壓力是不均衡的,比如淘寶每天的訪問高峰是在上午 10 點(diǎn)左右,而新浪微博則可能在某個(gè)明星半夜發(fā)一條微博后突然出現(xiàn)訪問高峰。
架構(gòu)師的36項(xiàng)修煉-03架構(gòu)核心技術(shù)之分布式消息隊(duì)列,java,架構(gòu),分布式,java,后端
在訪問高峰,用戶的并發(fā)訪問數(shù)可能超過了系統(tǒng)的處理能力,所以在高峰期就可能會(huì)導(dǎo)致系統(tǒng)負(fù)載過大,響應(yīng)速度變慢,更嚴(yán)重的可能會(huì)導(dǎo)致系統(tǒng)崩潰。這種情況下,通過消息隊(duì)列將用戶請求的消息納入到消息隊(duì)列中,通過消息隊(duì)列緩沖消費(fèi)者處理消息的速度。

如圖中所示,消息的生產(chǎn)者負(fù)載有高峰有低谷,但是到了消費(fèi)者這里,只會(huì)按照自己的最佳處理能力去消費(fèi)消息。高峰期它會(huì)把消息緩沖在消息隊(duì)列中,而在低谷期它也還是使用自己最大的處理能力去獲取消息,將前面緩沖起來、來不及及時(shí)處理的消息處理掉。那么,通過這種手段可以實(shí)現(xiàn)系統(tǒng)負(fù)載削峰填谷,也就是說將訪問的高峰削掉,而將訪問的低谷填平,使系統(tǒng)處在一個(gè)最佳的處理狀態(tài)之下,不會(huì)對系統(tǒng)的負(fù)載產(chǎn)生太大的沖擊。

失敗隔離及自我修復(fù)

消息隊(duì)列的第四個(gè)好處是失敗隔離和自我修復(fù)。因?yàn)榘l(fā)布者不直接依賴消費(fèi)者,所以分布式消息隊(duì)列可以將消費(fèi)者系統(tǒng)產(chǎn)生的錯(cuò)誤異常與生產(chǎn)者系統(tǒng)隔離開來,生產(chǎn)者不受消費(fèi)者失敗的影響。 當(dāng)在消息消費(fèi)過程中出現(xiàn)處理邏輯失敗的時(shí)候,這個(gè)錯(cuò)誤只會(huì)影響到消費(fèi)者自身,而不會(huì)傳遞給消息的生產(chǎn)者,也就是應(yīng)用程序可以按照原來的處理邏輯繼續(xù)執(zhí)行。

這也就意味著在任何時(shí)候都可以對后端的服務(wù)器執(zhí)行維護(hù)和發(fā)布操作。我們可以重啟、添加或刪除服務(wù)器,而不影響生產(chǎn)者的可用性,這樣簡化了部署和服務(wù)器管理的難度。

解耦

第五個(gè)好處,如下圖所示,使用分布式消息隊(duì)列,可以使生產(chǎn)者和消費(fèi)者的代碼實(shí)現(xiàn)解耦合,也就是說可以多個(gè)生產(chǎn)者發(fā)布消息,多個(gè)消費(fèi)者處理消息,共同完成完整的業(yè)務(wù)處理邏輯,但是它們卻不需要直接進(jìn)行交互調(diào)用,沒有代碼的依賴耦合。在傳統(tǒng)的同步調(diào)用中,調(diào)用者代碼必須要依賴被調(diào)用者的代碼,也就是生產(chǎn)者代碼必須要依賴消費(fèi)者的處理邏輯代碼,代碼需要直接的耦合,而使用消息隊(duì)列,這兩部分的代碼不需要進(jìn)行任何的耦合。耦合程度越低的代碼越容易維護(hù),也越容易進(jìn)行擴(kuò)展。
架構(gòu)師的36項(xiàng)修煉-03架構(gòu)核心技術(shù)之分布式消息隊(duì)列,java,架構(gòu),分布式,java,后端
比如前面提到的新用戶注冊的例子,如果用傳統(tǒng)同步調(diào)用的方式,那么發(fā)郵件、發(fā)短信、寫數(shù)據(jù)庫、通知關(guān)聯(lián)系統(tǒng)這些代碼會(huì)和用戶注冊代碼直接耦合起來,整個(gè)代碼看起來就是完成用戶注冊邏輯后,后面必然跟著發(fā)郵件、發(fā)短信這些代碼。如果要新增一個(gè)功能,比如將監(jiān)控用戶注冊情況,將注冊信息發(fā)送到業(yè)務(wù)監(jiān)控系統(tǒng),就必須要修改前面的代碼,至少增加一行代碼,發(fā)送注冊信息到監(jiān)控系統(tǒng),我們知道,任何代碼的修改都可能會(huì)引起 bug。

而使用分布式消息隊(duì)列實(shí)現(xiàn)生產(chǎn)者和消費(fèi)者解耦合以后,用戶注冊完成,不需要調(diào)用任何后續(xù)處理代碼,只需要將注冊消息發(fā)送到分布式消息隊(duì)列就可以了。如果要增加新功能,只需要寫個(gè)新功能的消費(fèi)者程序,在分布式消息隊(duì)列中,訂閱用戶注冊主題就可以了,不需要修改原來任何一行代碼。

解耦的特點(diǎn)對于團(tuán)隊(duì)的工作分工也很有幫助。從消息生產(chǎn)者的視角看,它只需要構(gòu)建消息,將消息放入消息隊(duì)列中,開發(fā)就完成了;而從消費(fèi)者的開發(fā)視角看,它只需要從消息隊(duì)列中獲取消息,然后進(jìn)行邏輯處理。它們彼此之間不進(jìn)行任何耦合。消息的生產(chǎn)者不關(guān)心放入消息隊(duì)列中下一步會(huì)發(fā)生什么,而消費(fèi)者也不需要知道消息從哪里來。這兩部分程序的開發(fā)者也可以不關(guān)心彼此的工作進(jìn)展,他們開發(fā)的代碼也不需要集成在一起,只要約定好消息格式,就可以各自開發(fā)了。

消息隊(duì)列相關(guān)挑戰(zhàn)

了解到上面的 5 點(diǎn)好處,你會(huì)認(rèn)為消息隊(duì)列是完美的嗎?其實(shí)不是的,接下來講分布式消息隊(duì)列遇到的挑戰(zhàn):消息無序、消息重新入隊(duì)列、競態(tài)條件、復(fù)雜度風(fēng)險(xiǎn)。

消息無序

先來說消息無序。因?yàn)樯a(chǎn)者和消費(fèi)者是異步處理的。雖然消息隊(duì)列本身會(huì)保證先創(chuàng)建的消息在前面,但是消費(fèi)者卻并不能保證先創(chuàng)建的消息先消費(fèi)掉。

如下圖所示,生產(chǎn)者會(huì)創(chuàng)建兩個(gè)消息,一個(gè)是創(chuàng)建用戶,另一個(gè)是歡迎郵件。消費(fèi)者應(yīng)該先消費(fèi)創(chuàng)建用戶,然后再消費(fèi)歡迎郵件,業(yè)務(wù)邏輯有先后順序。但是由于消費(fèi)者可能是在并行執(zhí)行,兩個(gè)消費(fèi)者分別獲得了創(chuàng)建用戶和發(fā)送歡迎郵件兩個(gè)消息。那么,有可能歡迎郵件被消費(fèi)者先處理完了,而創(chuàng)建用戶的消費(fèi)者還沒有來得及處理這條消息,就可能會(huì)導(dǎo)致歡迎郵件在創(chuàng)建用戶之前就已經(jīng)發(fā)出去了。
架構(gòu)師的36項(xiàng)修煉-03架構(gòu)核心技術(shù)之分布式消息隊(duì)列,java,架構(gòu),分布式,java,后端
一個(gè)簡單的解決辦法就是將消息處理的順序設(shè)計(jì)到異步流程中,也就是創(chuàng)建用戶的消費(fèi)者在處理消息后,再發(fā)送一個(gè)歡迎郵件的消息到消息隊(duì)列中。這樣就可以保證郵件發(fā)送一定在創(chuàng)建用戶之后,從而滿足業(yè)務(wù)邏輯的順序性要求。

消息重新入隊(duì)列

另一個(gè)挑戰(zhàn)是消息重新入隊(duì)列,重復(fù)消費(fèi)。有些分布式消息隊(duì)列產(chǎn)品支持將某個(gè)消費(fèi)者處理失敗的消息重新放入到消息隊(duì)列中,被其它的消費(fèi)者重新處理。但是重新放入到消息隊(duì)列中的消息有可能是被處理完成了的,也就是表面看起來處理失敗,實(shí)際上已經(jīng)處理完成,這種情況在軟件運(yùn)行過程中并不鮮見。那么這種情況下就會(huì)導(dǎo)致同一條消息被多次消費(fèi)。

解決這個(gè)問題的主要手段是將消息處理設(shè)計(jì)成冪等性,也就是說消費(fèi)者可以對同一條消息進(jìn)行多次處理計(jì)算,而不會(huì)影響最終的結(jié)果。有些操作天然就是冪等的,比如將商品價(jià)格設(shè)置為 50 元,不管設(shè)置多少次,都是 50 元,不會(huì)影響最終結(jié)果。而有些操作,比如發(fā)送郵件,發(fā)送兩次和發(fā)送一次結(jié)果肯定是不同的,對于這類非天然冪等的操作,需要進(jìn)行特別設(shè)計(jì),才能實(shí)現(xiàn)最終效果上的冪等。

競態(tài)條件

第三個(gè)挑戰(zhàn)是競態(tài)條件。所謂競態(tài)條件就是指在程序并發(fā)執(zhí)行的時(shí)候,不同的執(zhí)行順序會(huì)導(dǎo)致不同的結(jié)果,主要是因?yàn)閷蚕碣Y源的訪問順序不同導(dǎo)致的結(jié)果不同。我們在編程中通過多線程實(shí)現(xiàn)程序的并發(fā)執(zhí)行,消息隊(duì)列可以在分布式的環(huán)境下實(shí)現(xiàn)架構(gòu)層面的并發(fā)執(zhí)行,并發(fā)執(zhí)行就可能會(huì)導(dǎo)致對資源的爭用。在編程中我們通常使用鎖的機(jī)制進(jìn)行并發(fā)的控制,以避免競態(tài)、順序執(zhí)行。在消息隊(duì)列的異步架構(gòu)中也需要對共享資源的并發(fā)訪問進(jìn)行控制,以避免競態(tài)條件的出現(xiàn)。

復(fù)雜度風(fēng)險(xiǎn)

消息隊(duì)列的第四個(gè)挑戰(zhàn)是復(fù)雜度風(fēng)險(xiǎn)。消息隊(duì)列使系統(tǒng)的架構(gòu)和處理流程更加復(fù)雜,帶來了更多的復(fù)雜性問題,從而也對架構(gòu)師的系統(tǒng)架構(gòu)設(shè)計(jì)能力和架構(gòu)把控能力提出了更高的挑戰(zhàn)和要求。

消息隊(duì)列的反模式

所謂模式就是指可多次復(fù)用的解決方案。當(dāng)解決方案一次又一次地被證明是成功的,我們就稱它為“模式”。后面有同類問題出現(xiàn)的時(shí)候,我們就使用相同的解決方案去處理,也就是所謂的模式復(fù)用。

但是如果解決方案被認(rèn)為是錯(cuò)誤的,它們經(jīng)常會(huì)帶來問題,就稱之為“反模式”。典型的反模式一開始用起來不錯(cuò),但是時(shí)間越長問題越多。熟悉反模式,你就能在未來避免它們,就像對常見的設(shè)計(jì)缺陷產(chǎn)生免疫一樣。

接下來介紹消息隊(duì)列常見的幾種反模式。

阻塞式調(diào)用

有些分布式消息隊(duì)列產(chǎn)品允許生產(chǎn)者阻塞,也就是生產(chǎn)者發(fā)送消息以后,阻塞等待消息隊(duì)列處理結(jié)果,等消費(fèi)者處理完成返回處理結(jié)果以后,繼續(xù)向下執(zhí)行。這樣就使消息隊(duì)列成為一個(gè)同步的調(diào)用模式。使用同步模式看起來在某些場合下是比較合理的,因?yàn)榭梢缘却龍?zhí)行結(jié)果,拿到結(jié)果后繼續(xù)處理,但是這種方式使得消息隊(duì)列異步架構(gòu)的各種好處都喪失了。

耦合生產(chǎn)者和消費(fèi)者

另一種反模式是耦合生產(chǎn)者和消費(fèi)者。雖然消息隊(duì)列將生產(chǎn)和消費(fèi)者解耦合了,但是不恰當(dāng)?shù)脑O(shè)計(jì)依然會(huì)使生產(chǎn)者和消費(fèi)者產(chǎn)生耦合。比如說在消息中包含處理邏輯,也就是說在消息中約定消費(fèi)者應(yīng)該如何進(jìn)行處理?;蛘呤钦f使用特定的序列化協(xié)議編碼消息。那么消費(fèi)者必須要按照特定的序列化格式,才能解碼消息。這些情況都使得生產(chǎn)者和消費(fèi)者產(chǎn)生了不必要的耦合。

缺少壞消息處理

還有一種反模式是缺少壞消息的處理。使用消息隊(duì)列的時(shí)候,不能總是假定消息永遠(yuǎn)正確。對于引發(fā)消費(fèi)者崩潰的消息,應(yīng)該丟棄而不是重新處理。因?yàn)槿绻麑?dǎo)致消費(fèi)者失敗的原因是消息本身,那么每次重新處理都會(huì)導(dǎo)致消費(fèi)者失敗,最后導(dǎo)致整個(gè)消費(fèi)者服務(wù)器集群都崩潰,系統(tǒng)什么也干不了。

常用消息隊(duì)列產(chǎn)品

目前業(yè)界常用的消息隊(duì)列產(chǎn)品,主要有:RabbitMQ 、ActiveMQ、RocketMQ 、Kafka。

& RabbitMQ 的主要特點(diǎn)是性能好,社區(qū)活躍,但是 RabbitMQ 用 Erlang 開發(fā),我們的應(yīng)用很少用 Erlang,所以不便于二次開發(fā)和維護(hù)。

& ActiveMQ 影響比較廣泛,可以跨平臺(tái),使用 Java 開發(fā),對 Java 開發(fā)者比較友好。

& RocketMQ 是阿里推出的一個(gè)開源產(chǎn)品,也是使用 Java 開發(fā),性能比較好,可靠性也比較高。

& Kafka 是 Linkedin 出品的,專門針對分布式場景進(jìn)行了優(yōu)化,因此分布式的伸縮性會(huì)比較好。

   目前看來,Kafka 因?yàn)樽畛蹙褪轻槍ヂ?lián)網(wǎng)的分布式、高可用應(yīng)用場景而設(shè)計(jì)的,并且在大數(shù)據(jù)領(lǐng)域得到廣泛支持,資料文檔更加完善,因此在互聯(lián)網(wǎng)企業(yè)得到更多的應(yīng)用。
   
   分享一個(gè)技術(shù)產(chǎn)品選型的小技巧,技術(shù)決策時(shí)可作為參考。當(dāng)在幾個(gè)相似的技術(shù)產(chǎn)品中進(jìn)行選型決策,并且拿不定主意、感覺都差不多的時(shí)候,一個(gè)辦法就是利用搜索引擎搜索一下這些產(chǎn)品的名字。搜索結(jié)果最多的產(chǎn)品,一般是最熱門,文檔資料最多,遇到問題有更大概率找到答案的,最有發(fā)展前景不會(huì)半途而廢沒人維護(hù)的。利用這個(gè)技巧,我們看一下消息隊(duì)列(MQ)的產(chǎn)品選型,Kafka 在百度中的搜索結(jié)果數(shù)量是其它三個(gè) MQ 產(chǎn)品的搜索結(jié)果數(shù)量之和,那么如果你拿不定主意,選擇 Kafka 至少不會(huì)是最糟糕的選擇。

總結(jié)回顧

使用異步調(diào)用的架構(gòu)方法,就是使用消息隊(duì)列,將生產(chǎn)者和消費(fèi)者進(jìn)行隔離。主要的架構(gòu)模型有兩種,一種是點(diǎn)對點(diǎn)模型,一種是發(fā)布訂閱模型。其中點(diǎn)對點(diǎn)模型,一個(gè)消息只會(huì)被一個(gè)消費(fèi)者消費(fèi);而發(fā)布訂閱模型,一個(gè)消息可以被多個(gè)消費(fèi)者訂閱。

消息隊(duì)列實(shí)現(xiàn)的異步架構(gòu)可以在架構(gòu)上帶來更多的好處。它可以實(shí)現(xiàn)業(yè)務(wù)邏輯的異步處理,從而獲得更好性能特性;可以使系統(tǒng)具有更好的伸縮性;可以平衡用戶訪問流量,實(shí)現(xiàn)削峰填谷;還可以隔離失敗,并進(jìn)行自我修復(fù);以及對生產(chǎn)者和消費(fèi)者進(jìn)行解耦,使系統(tǒng)擁有更好的擴(kuò)展和維護(hù)能力。

同時(shí)我們需要關(guān)注異步消息隊(duì)列架構(gòu)帶來的挑戰(zhàn)。第一個(gè)是消息無序,第二個(gè)是消息重復(fù)處理,第三個(gè)是競態(tài)條件,還有一個(gè)是系統(tǒng)的復(fù)雜度的增加。

總之,消息隊(duì)列實(shí)際上可以帶來很多架構(gòu)上的好處,但是不正確地使用消息隊(duì)列可能會(huì)喪失這些好處。文章來源地址http://www.zghlxwxcb.cn/news/detail-820528.html

到了這里,關(guān)于架構(gòu)師的36項(xiàng)修煉-03架構(gòu)核心技術(shù)之分布式消息隊(duì)列的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包