所有中間件都是為了解決特定領(lǐng)域的某個(gè)問(wèn)題照皆。
MsgBroker解決:分布式系統(tǒng)的消息傳遞的問(wèn)題。
首先先了解消息中間件的一些背景知識(shí)
1.消息中間件
1.1消息中間件是什么
- 消息中間件用于分布式系統(tǒng)的消息傳遞
- 利用高效可靠的消息傳遞機(jī)制進(jìn)行與平臺(tái)無(wú)關(guān)的數(shù)據(jù)交流
- 基于數(shù)據(jù)通信來(lái)進(jìn)行分布式系統(tǒng)的集成
- 通過(guò)提供消息傳遞和消息排隊(duì)模型
1.2為什么要有消息中間件
原本的RPC接口調(diào)用有什么問(wèn)題
- 客戶端服務(wù)進(jìn)程和服務(wù)端服務(wù)進(jìn)程的生命周期緊密耦合沸停,緊密耦合帶來(lái)三個(gè)問(wèn)題
- 客戶端進(jìn)程和服務(wù)端進(jìn)程必須都正常運(yùn)行膜毁,如果由于服務(wù)方的對(duì)象錯(cuò)誤或者網(wǎng)絡(luò)錯(cuò)誤等引起的請(qǐng)求不可達(dá),客戶端的請(qǐng)求就會(huì)異常愤钾。
- 后續(xù)客戶端有其他業(yè)務(wù)變更的時(shí)候服務(wù)端的服務(wù)也得做出相應(yīng)調(diào)整瘟滨。
- 同步處理導(dǎo)致服務(wù)端需要等待客戶端處理完后才能處理完,處理時(shí)間慢能颁。
消息中間件解決了什么問(wèn)題
- 客戶端和服務(wù)端的對(duì)象生命周期的松耦合關(guān)系:客戶端進(jìn)程和服務(wù)端對(duì)象進(jìn)程不要求都正常運(yùn)行杂瘸,如果由于服務(wù)對(duì)象崩潰或者網(wǎng)絡(luò)故障導(dǎo)致客戶的請(qǐng)求不可達(dá),客戶不會(huì)接收到異常伙菊,消息中間件能保證消息不會(huì)丟失败玉。
- 用異步通信模式:發(fā)送消息者可以在發(fā)送消息后進(jìn)行其它的工作,不用等待接收者的回應(yīng)镜硕,而接收者也不必在接到消息后立即對(duì)發(fā)送者的請(qǐng)求進(jìn)行處理运翼;
一個(gè)例子
一個(gè)賬單查詢Case,基本業(yè)務(wù)邏輯:
- 賬單服務(wù):檢索數(shù)據(jù)庫(kù)兴枯,獲取指定賬戶的賬單記錄血淌。
- 風(fēng)險(xiǎn)控制服務(wù):記錄用戶的檢索行為,為風(fēng)險(xiǎn)控制提供數(shù)據(jù)積累财剖。
- 短信通知服務(wù):發(fā)送短信到用戶手機(jī)悠夯,通知用戶其賬單被查詢事件。
方案1峰伙,同步RPC調(diào)用
方案2疗疟,異步消息中間件
方案2對(duì)比方案1的優(yōu)點(diǎn):
- 賬單服務(wù)處理這個(gè)case時(shí)間減少了許多,提高了吞吐量
- 賬單服務(wù)瞳氓,風(fēng)險(xiǎn)控制服務(wù)和短信通知服務(wù)完全解耦策彤,后續(xù)有其他業(yè)務(wù)變更時(shí)栓袖,賬單服務(wù)不需要變更
- 風(fēng)險(xiǎn)控制服務(wù)和短信通知服務(wù)不可用時(shí),不會(huì)導(dǎo)致賬單服務(wù)不可用
1.3消息中間件應(yīng)用場(chǎng)景
- 系統(tǒng)集成:系統(tǒng)集成除了通過(guò)接口還可以通過(guò)消息店诗。不同點(diǎn):接口通過(guò)模塊間直接調(diào)用裹刮;使用消息中間件的系統(tǒng)通過(guò)消息模塊通信,通過(guò)消息來(lái)分解系統(tǒng)庞瘸。
- 業(yè)務(wù)解耦:如果模塊之間不存在直接調(diào)用捧弃,那么修改或新增模塊對(duì)其他模塊影響最小。增加消息中間件后擦囊,業(yè)務(wù)模塊僅需關(guān)注自己的業(yè)務(wù)邏輯和如何將消息發(fā)送給消息服務(wù)器违霞,消息由中間件存儲(chǔ)和分發(fā)。
- 異步處理:多個(gè)應(yīng)用對(duì)消息中間件的同一消息處理瞬场,應(yīng)用間并發(fā)處理消息买鸽,比起串行處理,減少處理時(shí)間贯被。
- 改善系統(tǒng)性能(削峰填谷):比如上游系統(tǒng)的吞吐能力高于下游系統(tǒng)眼五,在流量洪峰時(shí)可能會(huì)沖垮下游系統(tǒng),消息中間件可以在流量高峰時(shí)堆積消息彤灶,而在峰值過(guò)去后下游系統(tǒng)慢慢消費(fèi)消息解決流量洪峰的問(wèn)題
- 跨平臺(tái):跨平臺(tái)使用看幼,降低網(wǎng)絡(luò)協(xié)議的復(fù)雜性
- 事務(wù)型消息:基于消息的通信是可靠的胖眷,消息不會(huì)丟失橄妆∫绬可以發(fā)送事務(wù)性消息拱燃,而且大多數(shù)消息中間件都提供將消息持久化到磁盤的功能。
1.4消息中間件主要特點(diǎn)
- 可靠性:基于消息的通信是可靠的耍铜,大多數(shù)消息中間件都提供將消息持久化到磁盤的功能畦戒,可以發(fā)送離線消息,消息不會(huì)丟失搬卒。在分布式事務(wù)中擔(dān)當(dāng)重要的角色。
- 異步:基于事件驅(qū)動(dòng)架構(gòu)翎卓,將調(diào)用異步化
- 分布式:消息中間件都是分布式的
1.5兩種模式
點(diǎn)對(duì)點(diǎn)模式 (point to point)
點(diǎn)對(duì)點(diǎn)模式下包括三個(gè)角色:
- 消息隊(duì)列
- 發(fā)送者 (生產(chǎn)者)
-
接收者(消費(fèi)者)
image
消息發(fā)送者生產(chǎn)消息發(fā)送到queue中契邀,然后消息接收者從queue中取出并且消費(fèi)消息。消息被消費(fèi)以后失暴,queue中不再有存儲(chǔ)坯门,所以消息接收者不可能消費(fèi)到已經(jīng)被消費(fèi)的消息。
點(diǎn)對(duì)點(diǎn)模式特點(diǎn):
- 每個(gè)消息只有一個(gè)接收者(Consumer)(即一旦被消費(fèi)逗扒,消息就不再在消息隊(duì)列中)古戴;
- 發(fā)送者和接收者間沒(méi)有依賴性,發(fā)送者發(fā)送消息之后矩肩,不管有沒(méi)有接收者在運(yùn)行现恼,都不會(huì)影響到發(fā)送者下次發(fā)送消息;
- 接收者在成功接收消息之后需向隊(duì)列應(yīng)答成功,以便消息隊(duì)列刪除當(dāng)前接收的消息叉袍;
發(fā)布/訂閱模式(publish/subcribe)
發(fā)布/訂閱模式下包括三個(gè)角色:
- 角色主題(Topic)
- 發(fā)布者(Publisher)
- 訂閱者(Subscriber)
發(fā)布者將消息發(fā)送到Topic,系統(tǒng)將這些消息傳遞給多個(gè)訂閱者始锚。
發(fā)布/訂閱模式特點(diǎn):
- 每個(gè)消息可以有多個(gè)訂閱者;
- 發(fā)布者和訂閱者之間有時(shí)間上的依賴性喳逛。針對(duì)某個(gè)主題(Topic)的訂閱者瞧捌,它必須創(chuàng)建一個(gè)訂閱者之后,才能消費(fèi)發(fā)布者的消息润文。
- 為了消費(fèi)消息姐呐,訂閱者需要提前訂閱該角色主題,并保持在線運(yùn)行典蝌;
1.6消費(fèi)消息的推拉模式
- 推模式push:由消息中間件主動(dòng)發(fā)消息給消費(fèi)者
- 拉模式pull:消費(fèi)者主動(dòng)從消息中間件拉取消息
- 比較:采用push模式皮钠,可以盡可能快的把消息發(fā)給消費(fèi)者,但是如果消費(fèi)者處理一條消息能力較弱(處理時(shí)間長(zhǎng))赠法,消息中間件會(huì)不斷的發(fā)消息給消費(fèi)者麦轰,到時(shí)消費(fèi)者的緩存區(qū)溢出;采用pull模式砖织,可能會(huì)增加消息的延遲款侵。
1.7引入消息中間件需要注意點(diǎn)
- 復(fù)雜性:消息中間件都是分布式的,引入分布式會(huì)大大增加系統(tǒng)復(fù)雜度侧纯,在不同主機(jī)新锈、不同進(jìn)程之間的調(diào)用和調(diào)試,會(huì)帶來(lái)更多的不穩(wěn)定性眶熬。分布式系統(tǒng)還會(huì)增加對(duì)外部系統(tǒng)的依賴妹笆。即使自己的系統(tǒng)沒(méi)有問(wèn)題,也可能會(huì)因?yàn)橐蕾囅到y(tǒng)出問(wèn)題而導(dǎo)致系統(tǒng)不穩(wěn)定娜氏。
- 異步調(diào)用:帶來(lái)的業(yè)務(wù)交互的改變拳缠,有一定的操作延遲。
- 同步調(diào)用:盡管消息中間件也可用于同步調(diào)用贸弥,但這并不是它的長(zhǎng)項(xiàng)窟坐,同步調(diào)用可以考慮使用HTTP、NIO等其他方式绵疲。
然后再看螞蟻的消息中間件msgbroker是怎么做的哲鸳,重點(diǎn)講述MsgBroker的事務(wù)型消息
2.MsgBroker
2.1MsgBroker原理架構(gòu)圖
2.2MsgBroker組成
- 消息發(fā)布者Publisher:發(fā)送消息的應(yīng)用系統(tǒng),發(fā)送消息到可靠消息組件 (MsgBroker)盔憨。
- 可靠消息組件MsgBroker:即MsgBroker徙菠,負(fù)責(zé)接收發(fā)布者發(fā)送的消息,根據(jù)消息類型和訂閱關(guān)系將消息分發(fā)投遞到一個(gè)或多個(gè)消息訂閱者郁岩。
- 消息訂閱者Subscriber:指訂閱消息的應(yīng)用系統(tǒng)婿奔,收到的消息來(lái)自可靠消息組件 (MsgBroker)缺狠。
- 消息類型Message Type:一種消息類型由 TOPIC 和 EVENTCODE 唯一標(biāo)識(shí)。
- 訂閱關(guān)系Binding:用來(lái)描述一種消息類型被訂閱者訂閱脸秽。
2.3Msgbroker特性
- 可靠性:MsgBroker確保消息可以投遞到訂閱者儒老,發(fā)送者和訂閱者都不必?fù)?dān)心消息丟失
- 事務(wù)一致性:保證消息和本地?cái)?shù)據(jù)庫(kù)事務(wù)的一致性
- 不保證消息不重復(fù):所以訂閱者要做好冪等
- 不保證消息投遞順序:如果訂閱者有需求需要自己實(shí)現(xiàn)
2.4普通消息
普通消息:較簡(jiǎn)單的發(fā)送和投遞兩個(gè)過(guò)程
2.5事務(wù)型消息
什么是事務(wù)型消息
一種特殊類型的消息:消息中間件收到消息發(fā)布者發(fā)布的消息后不會(huì)立刻投遞給消費(fèi)者,而是根據(jù)發(fā)布者應(yīng)用的數(shù)據(jù)庫(kù)事務(wù)狀態(tài)來(lái)決定是否投遞记餐,如果數(shù)據(jù)庫(kù)事務(wù)是提交驮樊,就投遞;是回滾就不投遞片酝。
為什么要設(shè)計(jì)事務(wù)型消息
為了保證在分布式系統(tǒng)中數(shù)據(jù)庫(kù)變更之間以及數(shù)據(jù)庫(kù)變更和業(yè)務(wù)處理保持事務(wù)一致性囚衔。
事務(wù)型消息如何保證數(shù)據(jù)一致性
事務(wù)型消息通過(guò)“二階段”來(lái)保證一致性
- 第一個(gè)階段:當(dāng)發(fā)送端像發(fā)送普通消息一樣,將消息發(fā)送給Broker雕沿,Broker會(huì)將該條記錄保存在數(shù)據(jù)庫(kù)中练湿,并將其事務(wù)狀態(tài)設(shè)置為未知狀態(tài)。 入庫(kù)操作完成后审轮,Broker會(huì)向發(fā)送端返回一個(gè)消息確認(rèn)的信息肥哎,一階段結(jié)束。
- 第二個(gè)階段:發(fā)送端的代碼包在事務(wù)模板中疾渣,當(dāng)這個(gè)事務(wù)完結(jié)的時(shí)候篡诽,發(fā)送端會(huì)將本地事務(wù)的執(zhí)行結(jié)果(提交/回滾)發(fā)送給Broker,Broker對(duì)結(jié)果做出判斷榴捡。提交則發(fā)送杈女,回滾則不發(fā)送
思考
- 為什么發(fā)送消息要在事務(wù)操作之前?
- 如果Msgbroker一直收不到事務(wù)的執(zhí)行結(jié)果狀態(tài)(提交/回滾)時(shí)要怎么辦吊圾?
- 第一個(gè)問(wèn)題达椰,如果順序反過(guò)來(lái),先執(zhí)行事務(wù)项乒,事務(wù)執(zhí)行完成提交后再發(fā)送消息啰劲,那么消息發(fā)送失敗就會(huì)導(dǎo)致本地事務(wù)回滾,這個(gè)肯定是不合理的板丽,因?yàn)槭聞?wù)回滾比重發(fā)消息代價(jià)高很多
- 第二個(gè)問(wèn)題呈枉,如果MsgBroker一直沒(méi)收到事務(wù)的執(zhí)行結(jié)果,這個(gè)在分布式系統(tǒng)里屬于異常情況埃碱,也是有可能發(fā)生的,比如 說(shuō)網(wǎng)絡(luò)異常等酥泞,而Msgbroker作為一個(gè)嚴(yán)謹(jǐn)?shù)南⒅虚g件也考慮到了這種異常情況砚殿,設(shè)計(jì)了“回查階段”,這個(gè)階段只會(huì)在事務(wù)“提交/回滾消息”失敗時(shí)才會(huì)被觸發(fā)芝囤。
總結(jié)
- 消息中間件MsgBroker事務(wù)型消息通過(guò)“二階段”消息實(shí)現(xiàn)
- 事務(wù)型消息是否投遞與本地事務(wù)狀態(tài)保持一致
- 事務(wù)型消息狀態(tài)回查是為了保證事務(wù)型消息的嚴(yán)謹(jǐn)性
事務(wù)型消息(事務(wù)成功時(shí)消息才提交):
事務(wù)型消息(事務(wù)回滾時(shí)不發(fā)送消息):
4.幾個(gè)消息隊(duì)列比較
電商似炎、金融對(duì)事務(wù)型消息要求較高辛萍,因此MsgBroker重點(diǎn)在于支持事務(wù)型消息
MsgBroker | RocketMQ | ActiveMQ | RabbitMQ | KafKa | |
---|---|---|---|---|---|
所屬公司社區(qū) | 螞蟻 | 阿里 | Apache | Mozilla | Apache |
開(kāi)發(fā)語(yǔ)言 | Java | Java | Java | Relang | Scale&Java |
消息消費(fèi)模式(pull/push) | push | 多協(xié)議,均支持 | 多協(xié)議羡藐,均支持 | 多協(xié)議贩毕,均支持 | pull |
數(shù)據(jù)可靠性 | 可靠 | 可靠,同步刷盤仆嗦,同/異步復(fù)制 | 可靠辉阶,master/slave | 保證數(shù)據(jù)不丟,slave備份 | 可靠瘩扼,replica機(jī)制谆甜,容錯(cuò)容災(zāi) |
持久化能力 | DB | 磁盤文件 | 內(nèi)存/文件/DB | DB / 文件 | 磁盤文件 |
是否有序 | 無(wú)序 | 有序 | 可以支持有序 | 一個(gè)Client才有序 | 多Client有序 |
事務(wù)型消息 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
負(fù)載均衡 | 支持 | 支持 | 支持 | 支持 | 支持 |
關(guān)鍵場(chǎng)景 | 事務(wù),高可靠 | 高吞吐集绰,高可靠 | 高擴(kuò)展 | 高并發(fā)规辱,高可靠 | 高吞吐,分布式 |
5.知識(shí)點(diǎn)回顧
從本地事務(wù)到分布式事務(wù)到消息隊(duì)列
5.1事務(wù)
事務(wù):一系列指令的集合
滿足:ACID原則
- Automicity(原子性):操作這些指令栽燕,要么全部成功罕袋,要么全部失敗
- Consistency(一致性):事務(wù)執(zhí)行使得數(shù)據(jù)庫(kù)從一個(gè)狀態(tài)到另一個(gè)狀態(tài),但是對(duì)于整個(gè)數(shù)據(jù)的完整性保持一致
- Isolation(隔離性):在一個(gè)事務(wù)執(zhí)行過(guò)程中碍岔,任何數(shù)據(jù)變更都只存在于這一個(gè)事務(wù)中浴讯,不會(huì)被外界感知,只有事務(wù)執(zhí)行完成后付秕,其他事務(wù)才能感知到這個(gè)事務(wù)引起的數(shù)據(jù)變更兰珍。
- Durability(持久性):事務(wù)正確完成后,它帶來(lái)的數(shù)據(jù)變更時(shí)永久的询吴。
5.2本地事務(wù)
本地事務(wù)是在單個(gè)數(shù)據(jù)源上進(jìn)行數(shù)據(jù)訪問(wèn)和更新掠河,資源由資源管理器本地管理
本地事務(wù)特點(diǎn):
- 一次事務(wù)只連接一個(gè)支持事務(wù)的數(shù)據(jù)庫(kù)
- 事務(wù)的執(zhí)行保證ACID原則
- 會(huì)用到數(shù)據(jù)庫(kù)鎖
5.3分布式事務(wù)
跨越多個(gè)數(shù)據(jù)源進(jìn)行數(shù)據(jù)訪問(wèn)和更新。
隨著業(yè)務(wù)變得復(fù)雜猛计,一個(gè)單機(jī)應(yīng)用的一個(gè)數(shù)據(jù)庫(kù)會(huì)被拆成多庫(kù)多表唠摹,一個(gè)應(yīng)用也會(huì)被拆成多個(gè)應(yīng)用,整個(gè)系統(tǒng)處于分布式的狀態(tài)奉瘤,這個(gè)時(shí)候就需要保證分布式架構(gòu)下的數(shù)據(jù)一致性勾拉。關(guān)于分布式事務(wù)在之后學(xué)習(xí)XTS中間件的時(shí)候再深入了解。