RabbitMQ最后一天

一、RabbitMQ如何保證消息不丟失?

這是面試時最喜歡問的問題宙刘,其實這是個所有MQ的一個共性的問題轨功,大致的解決思路也是差不多的,但是針對不同的MQ產(chǎn)品會有不同的解決方案炊苫。而RabbitMQ設(shè)計之處就是針對企業(yè)內(nèi)部系統(tǒng)之間進行調(diào)用設(shè)計的裁厅,所以他的消息可靠性是比較高的。

注意:千萬不要再回答 手動確認了侨艾。

1.哪些環(huán)節(jié)會有丟消息的可能执虹?

我們考慮一個通用的MQ場景:

其中,1唠梨,2袋励,4三個場景都是跨網(wǎng)絡(luò)的,而跨網(wǎng)絡(luò)就肯定會有丟消息的可能当叭。

然后關(guān)于3這個環(huán)節(jié)茬故,通常MQ存盤時都會先寫入操作系統(tǒng)的緩存page cache中,然后再由操作系統(tǒng)異步的將消息寫入硬盤蚁鳖。這個中間有個時間差磺芭,就可能會造成消息丟失。如果服務(wù)掛了才睹,緩存中還沒有來得及寫入硬盤的消息就會丟失徘跪。這也是任何用戶態(tài)的應(yīng)用程序無法避免的。

對于任何MQ產(chǎn)品琅攘,都應(yīng)該從這四個方面來考慮數(shù)據(jù)的安全性垮庐。那我們看看用RabbitMQ時要如何解決這個問題。

2.RabbitMQ消息零丟失方案

1)生產(chǎn)者保證消息正確發(fā)送到RabbitMQ

對于單個數(shù)據(jù)坞琴,可以使用生產(chǎn)者確認機制哨查。通過多次確認的方式,保證生產(chǎn)者的消息能夠正確的發(fā)送到RabbitMQ中剧辐。

RabbitMQ的生產(chǎn)者確認機制分為同步確認和異步確認寒亥。同步確認主要是通過在生產(chǎn)者端使用Channel.waitForConfirmsOrDie()指定一個等待確認的完成時間。異步確認機制則是通過channel.addConfirmListener(ConfirmCallback var1, ConfirmCallback var2)在生產(chǎn)者端注入兩個回調(diào)確認函數(shù)荧关。第一個函數(shù)是在生產(chǎn)者發(fā)送消息時調(diào)用溉奕,第二個函數(shù)則是生產(chǎn)者收到Broker的消息確認請求時調(diào)用。兩個函數(shù)需要通過sequenceNumber自行完成消息的前后對應(yīng)忍啤。sequenceNumber的生成方式需要通過channel的序列獲取加勤。int sequenceNumber = channel.getNextPublishSeqNo();

在RabbitMQ中仙辟,另外還有一種手動事務(wù)的方式,可以保證消息正確發(fā)送鳄梅。

手動事務(wù)機制主要有幾個關(guān)鍵的方法: channel.txSelect() 開啟事務(wù)叠国; channel.txCommit() 提交事務(wù); channel.txRollback() 回滾事務(wù)戴尸; 用這幾個方法來進行事務(wù)管理粟焊。但是這種方式需要手動控制事務(wù)邏輯,并且手動事務(wù)會對channel產(chǎn)生阻塞孙蒙,造成吞吐量下降项棠。

2)RabbitMQ消息存盤不丟消息

這個在RabbitMQ中比較好處理,對于Classic經(jīng)典隊列马篮,直接將隊列聲明成為持久化隊列即可沾乘。而新增的Quorum隊列和Stream隊列,都是明顯的持久化隊列浑测,能更好的保證服務(wù)端消息不會丟失翅阵。

3)RabbitMQ 主從消息同步時不丟消息

這涉及到RabbitMQ的集群架構(gòu)。首先他的普通集群模式迁央,消息是分散存儲的掷匠,不會主動進行消息同步了,是有可能丟失消息的岖圈。而鏡像模式集群讹语,數(shù)據(jù)會主動在集群各個節(jié)點當中同步,這時丟失消息的概率不會太高蜂科。

另外顽决,啟用Federation聯(lián)邦機制,給包含重要消息的隊列建立一個遠端備份导匣,也是一個不錯的選擇才菠。

4)RabbitMQ消費者不丟失消息

RabbitMQ在消費消息時可以指定是自動應(yīng)答,還是手動應(yīng)答贡定。如果是自動應(yīng)答模式赋访,消費者會在完成業(yè)務(wù)處理后自動進行應(yīng)答,而如果消費者的業(yè)務(wù)邏輯拋出異常缓待,RabbitMQ會將消息進行重試蚓耽,這樣是不會丟失消息的,但是有可能會造成消息一直重復(fù)消費旋炒。

將RabbitMQ的應(yīng)答模式設(shè)定為手動應(yīng)答可以提高消息消費的可靠性步悠。

另外這個應(yīng)答模式在SpringBoot集成案例中,也可以在配置文件中通過屬性spring.rabbitmq.listener.simple.acknowledge-mode 進行指定瘫镇《κ蓿可以設(shè)定為 AUTO 自動應(yīng)答芹壕; MANUAL 手動應(yīng)答;NONE 不應(yīng)答接奈; 其中這個NONE不應(yīng)答,就是不啟動應(yīng)答機制通孽,RabbitMQ只管往消費者推送消息后序宦,就不再重復(fù)推送消息了,相當于RocketMQ的sendoneway背苦, 這樣效率更高互捌,但是顯然會有丟消息的可能。

最后行剂,任何用戶態(tài)的應(yīng)用程序都無法保證絕對的數(shù)據(jù)安全秕噪,所以,備份與恢復(fù)的方案也需要考慮到厚宰。

二腌巾、如何保證消息冪等?

RabbitMQ的自動重試功能:當消費者消費消息處理業(yè)務(wù)邏輯時铲觉,如果拋出異常澈蝙,或者不向RabbitMQ返回響應(yīng),默認情況下撵幽,RabbitMQ會無限次數(shù)的重復(fù)進行消息消費灯荧。

處理冪等問題,首先要設(shè)定RabbitMQ的重試次數(shù)盐杂。在SpringBoot集成RabbitMQ時逗载,可以在配置文件中指定spring.rabbitmq.listener.simple.retry開頭的一系列屬性,來制定重試策略链烈。

然后厉斟,需要在業(yè)務(wù)上處理冪等問題

處理冪等問題的關(guān)鍵是要給每個消息一個唯一的標識测垛。

在SpringBoot框架集成RabbitMQ后捏膨,可以給每個消息指定一個全局唯一的MessageID,在消費者端針對MessageID做冪等性判斷食侮。關(guān)鍵代碼:

要注意下這里用的message要是org.springframework.amqp.core.Message?

在原生API當中号涯,也是支持MessageId的。當然锯七,在實際工作中链快,最好還是能夠添加一個具有業(yè)務(wù)意義的數(shù)據(jù)作為唯一鍵會更好,這樣能更好的防止重復(fù)消費問題對業(yè)務(wù)的影響眉尸。比如域蜗,針對訂單消息巨双,那就用訂單ID來做唯一鍵。在RabbitMQ中霉祸,消息的頭部就是一個很好的攜帶數(shù)據(jù)的地方筑累。

三、如何保證消息的順序丝蹭?

某些場景下慢宗,需要保證消息的消費順序,例如一個下單過程奔穿,需要先完成扣款镜沽,然后扣減庫存,然后通知快遞發(fā)貨贱田,這個順序不能亂缅茉。如果每個步驟都通過消息進行異步通知的話,這一組消息就必須保證他們的消費順序是一致的男摧。

在RabbitMQ當中蔬墩,針對消息順序的設(shè)計其實是比較弱的。唯一比較好的策略就是 單隊列+單消息推送耗拓。即一組有序消息筹我,只發(fā)到一個隊列中,利用隊列的FIFO特性保證消息在隊列內(nèi)順序不會亂帆离。但是蔬蕊,顯然,這是以極度消耗性能作為代價的哥谷,在實際適應(yīng)過程中岸夯,應(yīng)該盡量避免這種場景。

然后在消費者進行消費時们妥,保證只有一個消費者猜扮,同時指定prefetch屬性為1,即每次RabbitMQ都只往客戶端推送一個消息监婶。像這樣:

而在多隊列情況下旅赢,如何保證消息的順序性,目前使用RabbitMQ的話惑惶,還沒有比較好的解決方案煮盼。在使用時,應(yīng)該盡量避免這種情況带污。

四僵控、關(guān)于RabbitMQ的數(shù)據(jù)堆積問題

RabbitMQ一直以來都有一個缺點,就是對于消息堆積問題的處理不好鱼冀。當RabbitMQ中有大量消息堆積時报破,整體性能會嚴重下降悠就。而目前新推出的Quorum隊列以及Stream隊列,目的就在于解決這個核心問題充易。但是這兩種隊列的穩(wěn)定性和周邊生態(tài)都還不夠完善梗脾,因此,在使用RabbitMQ時盹靴,還是要非常注意消息堆積的問題藐唠。盡量讓消息的消費速度和生產(chǎn)速度保持一致。

而如果確實出現(xiàn)了消息堆積比較嚴重的場景鹉究,就需要從數(shù)據(jù)流轉(zhuǎn)的各個環(huán)節(jié)綜合考慮,設(shè)計適合的解決方案踪宠。

1)首先在消息生產(chǎn)者端:

對于生產(chǎn)者端自赔,最明顯的方式自然是降低消息生產(chǎn)的速度。但是柳琢,生產(chǎn)者端產(chǎn)生消息的速度通常是跟業(yè)務(wù)息息相關(guān)的绍妨,一般情況下不太好直接優(yōu)化。但是可以選擇盡量多采用批量消息的方式柬脸,降低IO頻率他去。

2)然后在RabbitMQ服務(wù)端:

從前面的分享中也能看出,RabbitMQ本身其實也在著力于提高服務(wù)端的消息堆積能力倒堕。對于消息堆積嚴重的隊列灾测,可以預(yù)先添加懶加載機制,或者創(chuàng)建Sharding分片隊列垦巴,這些措施都有助于優(yōu)化服務(wù)端的消息堆積能力媳搪。另外,嘗試使用Stream隊列骤宣,也能很好的提高服務(wù)端的消息堆積能力秦爆。

3)接下來在消息消費者端:

要提升消費速度最直接的方式,就是增加消費者數(shù)量了憔披。尤其當消費端的服務(wù)出現(xiàn)問題等限,已經(jīng)有大量消息堆積時。這時芬膝,可以盡量多的申請機器望门,部署消費端應(yīng)用锰霜,爭取在最短的時間內(nèi)消費掉積壓的消息怒允。但是這種方式需要注意對其他組件的性能壓力锈遥。

對于單個消費者端勘畔,可以通過配置提升消費者端的吞吐量。例如:

靈活配置這幾個參數(shù)丽惶,能夠在一定程度上調(diào)整每個消費者實例的吞吐量炫七,減少消息堆積數(shù)量钾唬。

當確實遇到緊急狀況,來不及調(diào)整消費者端時抡秆,可以緊急上線一個消費者組奕巍,專門用來將消息快速轉(zhuǎn)錄。保存到數(shù)據(jù)庫或者Redis儒士,然后再慢慢進行處理的止。

五着撩、RabbitMQ的備份與恢復(fù)

文檔地址:?https://www.rabbitmq.com/backup.html

RabbitMQ有一個data目錄會保存分配到該節(jié)點上的所有消息。我們的實驗環(huán)境中拖叙,默認是在/var/lib/rabbitmq/mnesia目錄下?這個目錄里面的備份分為兩個部分,一個是元數(shù)據(jù)(定義結(jié)構(gòu)的數(shù)據(jù))薯鳍,一個是消息存儲目錄。

對于元數(shù)據(jù)挖滤,可以在Web管理頁面通過json文件直接導(dǎo)出或?qū)搿?/b>

而對于消息,可以手動進行備份恢復(fù)悯舟。

其實對于消息,由于MQ的特性抵怎,是不建議進行備份恢復(fù)的岭参。而RabbitMQ如果要進行數(shù)據(jù)備份恢復(fù)反惕,也非常簡單演侯。

1)首先,要保證要恢復(fù)的RabbitMQ中已經(jīng)有了全部的元數(shù)據(jù),這個可以通過上一步的json文件來恢復(fù)狡汉。

2)然后,備份過程必須要先停止應(yīng)用盾戴。如果是針對鏡像集群,還需要把整個集群全部停止尖啡。

3)最后剩膘,在RabbitMQ的數(shù)據(jù)目錄中衅斩,有按virtual hosts組織的文件夾怠褐。你只需要按照虛擬主機,將整個文件夾復(fù)制到新的服務(wù)中即可惫搏。持久化消息和非持久化消息都會一起備份蚕涤。?我們實驗環(huán)境的默認目錄是/var/lib/rabbitmq/mnesia/rabbit@worker2/msg_stores/vhosts

六、RabbitMQ的性能監(jiān)控

關(guān)于RabbitMQ的性能監(jiān)控揖铜,在管理控制臺中提供了非常豐富的展示。例如在下面這個簡單的集群節(jié)點圖中天吓,就監(jiān)控了非常多系統(tǒng)的關(guān)鍵資源。

還包括消息的生產(chǎn)消費頻率汰规、關(guān)鍵組件使用情況等等非常多的信息,都可以從這個管理控制臺上展現(xiàn)出來溜哮。但是,對于構(gòu)建一個自動化的性能監(jiān)控系統(tǒng)來說色解,這個管理頁面就不太夠用了。為此科阎,RabbitMQ也提供了一系列的HTTP接口,通過這些接口可以非常全面的使用并管理RabbitMQ的各種功能锣笨。

這些HTTP的接口不需要專門去查手冊道批,在部署的管理控制臺頁面下方已經(jīng)集成了詳細的文檔朴读,我們只需要打開HTTP API的頁面就能看到屹徘。

比如最常用的 http://[server:port]/api/overview 接口衅金,會列出非常多的信息,包含系統(tǒng)的資源使用情況氮唯。通過這個接口,就可以很好的對接Promethus豆励、Grafana等工具,構(gòu)建更靈活的監(jiān)控告警體系良蒸。

可以看到,這里面的接口相當豐富嫩痰,不光可以通過GET請求獲取各種消息窍箍,還可以通過其他類型的HTTP請求來管理RabbitMQ中的各種資源串纺,因此在實際使用時椰棘,還需要考慮這些接口的安全性纺棺。

七邪狞、搭建HAProxy,實現(xiàn)高可用集群

我們之前搭建的鏡像集群帆卓,已經(jīng)具備了集群的功能,請求發(fā)送到任何一個節(jié)點上罪郊,數(shù)據(jù)都是在集群內(nèi)共享的。但是悔橄,在企業(yè)使用時,通常還會選擇在集群基礎(chǔ)上增加負載均衡的能力。即希望將客戶端的請求能夠盡量均勻的分配到集群中各個節(jié)點上癣疟,這樣可以讓集群的壓力得到平衡。

實現(xiàn)負載均衡的方式有很多睛挚,HAProxy就是其中一種可選方案。HAProxy是一個免費侧到、快速并且可靠的解決方案,有很多大型互聯(lián)網(wǎng)公司都在使用匠抗。通過HAProxy污抬,應(yīng)用可以直連一個單一的IP地址汞贸,然后HAProxy會將這個IP地址的TCP請求進行轉(zhuǎn)發(fā),并在轉(zhuǎn)發(fā)過程中實現(xiàn)負載均衡印机。

很多有實力的大企業(yè)會采用F5等其他的一些負載均衡工具。

安裝步驟如下:

1射赛、安裝HAProxy

2、配置HAProxy

修改haproxy.cfg文件咒劲。下面是參考配置诫隅。注意將節(jié)點的IP地址和端口換成你自己的環(huán)境。

八逐纬、總結(jié)

基于MQ的事件驅(qū)動機制蛔屹,給龐大的互聯(lián)網(wǎng)應(yīng)用帶來了不一樣的方向豁生。MQ的異步、解耦甸箱、削峰三大功能特點在很多業(yè)務(wù)場景下都能帶來極大的性能提升,在日常工作過程中芍殖,應(yīng)該嘗試總結(jié)這些設(shè)計的思想。

雖然MQ的功能,說起來比較簡單隐锭,但是隨著MQ的應(yīng)用逐漸深化,所需要解決的問題也更深入计贰。對各種細化問題的挖掘程度,很大程度上決定了開發(fā)團隊能不能真正Hold得住MQ產(chǎn)品荞怒。通常面向互聯(lián)網(wǎng)的應(yīng)用場景樱溉,更加注重MQ的吞吐量,需要將消息盡快的保存下來福贞,再供后端慢慢消費。而針對企業(yè)內(nèi)部的應(yīng)用場景挖帘,更加注重MQ的數(shù)據(jù)安全性,在復(fù)雜多變的業(yè)務(wù)場景下逻族,每一個消息都需要有更加嚴格的安全保障。而在當今互聯(lián)網(wǎng)聘鳞,Kafka是第一個場景的不二代表要拂,但是他會丟失消息的特性,讓kafka的使用場景比較局限脱惰。RabbitMQ作為一個老牌產(chǎn)品,是第二個場景最有力的代表拉一。當然,隨著互聯(lián)網(wǎng)應(yīng)用不斷成熟磅氨,也不斷有其他更全能的產(chǎn)品冒出來嫡纠,比如阿里的RocketMQ以及雅虎的Pulsar决瞳。但是不管未來MQ領(lǐng)域會是什么樣子,RabbitMQ依然是目前企業(yè)級最為經(jīng)典也最為重要的一個產(chǎn)品皮胡。他的功能最為全面赏迟,周邊生態(tài)也非常成熟,并且RabbitMQ有龐大的Spring社區(qū)支持锌杀,本身也在吸收其他產(chǎn)品的各種優(yōu)點,持續(xù)進化糕再,所以未來RabbitMQ的重要性也會更加凸顯。

從RabbitMQ的安裝殴蹄、應(yīng)用猾担、擴展等多個方面袭灯,綜合介紹了RabbitMQ的各種常用使用方法以及業(yè)務(wù)場景绑嘹。希望能夠帶你打開一扇大門,更真實姨丈,更深入的理解MQ這個工具。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蟋恬,一起剝皮案震驚了整個濱河市惕鼓,隨后出現(xiàn)的幾起案子唐础,更是在濱河造成了極大的恐慌,老刑警劉巖一膨,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異价淌,居然都是意外死亡,警方通過查閱死者的電腦和手機蝉衣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來濒翻,“玉大人啦膜,你說我怎么就攤上這事有送∩遥” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵阵赠,是天一觀的道長肌稻。 經(jīng)常有香客問我,道長灯萍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任齿风,我火速辦了婚禮绑洛,結(jié)果婚禮上救斑,老公的妹妹穿的比我還像新娘真屯。我一直安慰自己,他們只是感情好绑蔫,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布配深。 她就那樣靜靜地躺著,像睡著了一般篓叶。 火紅的嫁衣襯著肌膚如雪羞秤。 梳的紋絲不亂的頭發(fā)上左敌,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音矫限,去河邊找鬼。 笑死奇唤,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的甲葬。 我是一名探鬼主播懈贺,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼梭灿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起堡妒,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤皮迟,失蹤者是張志新(化名)和其女友劉穎搬泥,沒想到半個月后伏尼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡燥透,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年辨图,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片徒役。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡窖壕,死狀恐怖杉女,靈堂內(nèi)的尸體忽然破棺而出鸳吸,到底是詐尸還是另有隱情,我是刑警寧澤晌砾,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站哼勇,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏积担。R本人自食惡果不足惜猬仁,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望湿刽。 院中可真熱鬧,春花似錦诈闺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嗤军。三九已至晃危,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間僚饭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工苇瓣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留偿乖,地道東北人击罪。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓媳禁,卻偏偏與公主長得像眠副,于是被迫代替她去往敵國和親竣稽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容