RabbitMQ第四天

一莱坎、Headers路由

在官網(wǎng)的體驗(yàn)示例中,還有一種路由策略并沒(méi)有提及着茸,那就是Headers路由。其實(shí)官網(wǎng)之所以沒(méi)有過(guò)多介紹琐旁,就是因?yàn)檫@種策略在實(shí)際中用得比較少,但是在某些比較特殊的業(yè)務(wù)場(chǎng)景猜绣,還是挺好用的灰殴。

官網(wǎng)示例中的集中路由策略, direct,fanout,topic等這些Exchange掰邢,都是以routingkey為關(guān)鍵字來(lái)進(jìn)行消息路由的牺陶,但是這些Exchange有一個(gè)普遍的局限就是都是只支持一個(gè)字符串的形式,而不支持其他形式辣之。Headers類型的Exchange就是一種忽略routingKey的路由方式掰伸。他通過(guò)Headers來(lái)進(jìn)行消息路由。這個(gè)headers是一個(gè)鍵值對(duì)怀估,發(fā)送者可以在發(fā)送的時(shí)候定義一些鍵值對(duì)狮鸭,接受者也可以在綁定時(shí)定義自己的鍵值對(duì)。當(dāng)鍵值對(duì)匹配時(shí)多搀,對(duì)應(yīng)的消費(fèi)者就能接收到消息歧蕉。匹配的方式有兩種,一種是all康铭,表示需要所有的鍵值對(duì)都滿足才行惯退。另一種是any,表示只要滿足其中一個(gè)鍵值就可以了从藤。而這個(gè)值催跪,可以是List、Boolean等多個(gè)類型夷野。

關(guān)于Headers路由的示例懊蒸,首先在Web管理頁(yè)面上,可以看到默認(rèn)創(chuàng)建了一個(gè)amqp.headers這樣的Exchange交換機(jī)悯搔,這個(gè)就是Headers類型的路由交換機(jī)榛鼎。然后關(guān)于Headers路由的示例,可以查看示例代碼鳖孤。BasicDemo和SpringBootDemo中均有詳細(xì)的使用示例者娱。

例如我們收集應(yīng)用日志時(shí),如果需要實(shí)現(xiàn)按Log4j那種向上收集的方式苏揣,就可以使用這種Headers路由策略黄鳍。

日志等級(jí)分為 debug - info - warning - error四個(gè)級(jí)別。而針對(duì)四個(gè)日志級(jí)別平匈,按四個(gè)隊(duì)列進(jìn)行分開(kāi)收集框沟,收集時(shí)藏古,每個(gè)隊(duì)列對(duì)應(yīng)一個(gè)日志級(jí)別,然后收集該日志級(jí)別以上級(jí)別的所有日志(包含當(dāng)前日志級(jí)別)忍燥。像這種場(chǎng)景拧晕,就比較適合使用Headers路由機(jī)制。

二、分組消費(fèi)模式

1.什么是分組消費(fèi)模式

我們回顧下RabbitMQ的消費(fèi)模式,Exchange與Queue之間的消息路由都是通過(guò)RoutingKey關(guān)鍵字來(lái)進(jìn)行的于微,不同類型的Exchange對(duì)RoutingKey進(jìn)行不同的處理剔氏。那有沒(méi)有不通過(guò)RoutingKey來(lái)進(jìn)行路由的策略呢?

這個(gè)問(wèn)題其實(shí)是很常見(jiàn)的,一個(gè)產(chǎn)品的業(yè)務(wù)模型設(shè)計(jì)得再完美,也會(huì)有照顧不到的場(chǎng)景。例如ShardingSphere分庫(kù)分表時(shí)臭墨,默認(rèn)都是基于SQL語(yǔ)句來(lái)進(jìn)行分庫(kù)分表,但是為了保證產(chǎn)品靈活性膘盖,也提供了hint強(qiáng)制路由策略胧弛,脫離了SQL的限制。

在RabbitMQ產(chǎn)品當(dāng)中侠畔,確實(shí)沒(méi)有這樣的路由策略叶圃,但是在SpringCloudStream框架對(duì)RabbitMQ進(jìn)行封裝時(shí),提供了一個(gè)這種策略践图,即分區(qū)消費(fèi)策略掺冠。這種策略很類似于kafka的分組消費(fèi)策略。 我們回憶一下码党,在kafka中的分組策略德崭,是不同的group,都會(huì)消費(fèi)到同樣的一份message副本揖盘,而在同一個(gè)group中眉厨,只會(huì)有一個(gè)消費(fèi)者消費(fèi)到一個(gè)message。這種分組消費(fèi)策略兽狭,嚴(yán)格來(lái)說(shuō)憾股,在Rabbit中是不存在的。RabbitMQ是通過(guò)不同類型的exchange來(lái)實(shí)現(xiàn)不同的消費(fèi)策略的箕慧。這雖然與kafka的這一套完全不同服球,但是在SpringCloudStream針對(duì)RabbitMQ的實(shí)現(xiàn)中,可以很容易的看到kafka這種分組策略的影子颠焦。

當(dāng)有多個(gè)消費(fèi)者實(shí)例消費(fèi)同一個(gè)bingding時(shí)斩熊,Spring Cloud Stream同樣是希望將這種分組策略,移植到RabbitMQ中來(lái)的伐庭。就是在不同的group中粉渠,會(huì)同樣消費(fèi)同一個(gè)Message分冈,而在同一個(gè)group中,只會(huì)有一個(gè)消費(fèi)者消息到一個(gè)Message霸株。

2.實(shí)例測(cè)試

要使用分組消費(fèi)策略雕沉,需要在生產(chǎn)者和消費(fèi)者兩端都進(jìn)行分組配置。

1去件、生產(chǎn)者端 核心配置

2坡椒、消費(fèi)者端啟動(dòng)兩個(gè)實(shí)例,組成一個(gè)消費(fèi)者組

消費(fèi)者1 核心配置

?消費(fèi)者2 核心配置

這樣就完成了一個(gè)分組消費(fèi)的配置箫攀。兩個(gè)消費(fèi)者實(shí)例會(huì)組成一個(gè)消費(fèi)者組。而生產(chǎn)者發(fā)送的消息幼衰,只會(huì)被消費(fèi)者1 消費(fèi)到(生產(chǎn)者的partition-key-expression 和 消費(fèi)者的 instance-index 匹配)靴跛。

3.實(shí)現(xiàn)原理

實(shí)際上,在跟蹤查看RabbitMQ的實(shí)現(xiàn)時(shí)渡嚣,就會(huì)發(fā)現(xiàn)梢睛,Spring Cloud Stream在增加了消費(fèi)者端的分區(qū)設(shè)置后,會(huì)對(duì)每個(gè)有效的分區(qū)創(chuàng)建一個(gè)單獨(dú)的queue识椰,這個(gè)隊(duì)列的隊(duì)列名是在原有隊(duì)列名后面加上一個(gè)索引值绝葡。而發(fā)送者端的消息,會(huì)最終發(fā)送到這個(gè)帶索引值的隊(duì)列上腹鹉,而不是原隊(duì)列上藏畅,這樣就完成了分區(qū)消費(fèi)。

我們的示例中功咒,分組表達(dá)式是直接指定的愉阎,這樣其實(shí)是喪失了靈活性的。實(shí)際開(kāi)發(fā)中力奋,可以將這個(gè)分組表達(dá)式放到消息的header當(dāng)中榜旦,在發(fā)送消息時(shí)指定,這樣就更有靈活性了景殷。

例如:將生產(chǎn)者端的分組表達(dá)式配置為header['partitonkey']

這樣溅呢,就可以在發(fā)送消息時(shí),給消息指定一個(gè)header屬性猿挚,來(lái)控制控制分組消費(fèi)的結(jié)果咐旧。

分組消費(fèi)策略是在原有路由策略上的一個(gè)補(bǔ)充,在實(shí)際生產(chǎn)中也是經(jīng)常會(huì)用到的一種策略绩蜻。并且休偶,MQ的使用場(chǎng)景是非常多的,這也意味著辜羊,不管MQ產(chǎn)品設(shè)計(jì)得如何完善踏兜,在復(fù)雜場(chǎng)景下词顾,往往都不可能滿足所有的使用要求。這時(shí)碱妆,如果想要自行設(shè)計(jì)一些更靈活的使用方式肉盹,那么這種分組消費(fèi)的模式就是一個(gè)很好的示例。

三疹尾、死信隊(duì)列

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

死信隊(duì)列是RabbitMQ中非常重要的一個(gè)特性上忍。簡(jiǎn)單理解,他是RabbitMQ對(duì)于未能正常消費(fèi)的消息進(jìn)行的一種補(bǔ)救機(jī)制纳本。死信隊(duì)列也是一個(gè)普通的隊(duì)列窍蓝,同樣可以在隊(duì)列上聲明消費(fèi)者,繼續(xù)對(duì)消息進(jìn)行消費(fèi)處理繁成。

對(duì)于死信隊(duì)列吓笙,在RabbitMQ中主要涉及到幾個(gè)參數(shù)。

在這里巾腕,x-dead-letter-exchange指定一個(gè)交換機(jī)作為死信交換機(jī)面睛,然后x-dead-letter-routing-key指定交換機(jī)的RoutingKey。而接下來(lái)尊搬,死信交換機(jī)就可以像普通交換機(jī)一樣叁鉴,通過(guò)RoutingKey將消息轉(zhuǎn)發(fā)到對(duì)應(yīng)的死信隊(duì)列中。

1.何時(shí)會(huì)產(chǎn)生死信

有以下三種情況佛寿,RabbitMQ會(huì)將一個(gè)正常消息轉(zhuǎn)成死信:

1)消息被消費(fèi)者確認(rèn)拒絕幌墓。消費(fèi)者把requeue參數(shù)設(shè)置為true(false),并且在消費(fèi)后冀泻,向RabbitMQ返回拒絕克锣。channel.basicReject或者channel.basicNack。

2)消息達(dá)到預(yù)設(shè)的TTL時(shí)限還一直沒(méi)有被消費(fèi)腔长。

3)消息由于隊(duì)列已經(jīng)達(dá)到最長(zhǎng)長(zhǎng)度限制而被丟掉袭祟。

TTL即最長(zhǎng)存活時(shí)間 Time-To-Live 。消息在隊(duì)列中保存時(shí)間超過(guò)這個(gè)TTL捞附,即會(huì)被認(rèn)為死亡巾乳。死亡的消息會(huì)被丟入死信隊(duì)列,如果沒(méi)有配置死信隊(duì)列的話鸟召,RabbitMQ會(huì)保證死了的消息不會(huì)再次被投遞胆绊,并且在未來(lái)版本中,會(huì)主動(dòng)刪除掉這些死掉的消息欧募。

設(shè)置TTL有兩種方式压状,一是通過(guò)配置策略指定,另一種是給隊(duì)列單獨(dú)聲明TTL。

策略配置方式 - Web管理平臺(tái)配置 或者 使用指令配置 60000為毫秒單位:

在聲明隊(duì)列時(shí)指定 - 同樣可以在Web管理平臺(tái)配置种冬,也可以在代碼中配置:

2.死信隊(duì)列的配置方式

RabbitMQ中有兩種方式可以聲明死信隊(duì)列镣丑,一種是針對(duì)某個(gè)單獨(dú)隊(duì)列指定對(duì)應(yīng)的死信隊(duì)列。另一種就是以策略的方式進(jìn)行批量死信隊(duì)列的配置娱两。

針對(duì)多個(gè)隊(duì)列莺匠,可以使用策略方式,配置統(tǒng)一的死信隊(duì)列:

針對(duì)隊(duì)列單獨(dú)指定死信隊(duì)列的方式主要是之前提到的三個(gè)屬性:

這些參數(shù)十兢,也可以在RabbitMQ的管理頁(yè)面進(jìn)行配置趣竣。例如配置策略時(shí):

另外,你會(huì)注意到旱物,在對(duì)隊(duì)列進(jìn)行配置時(shí)遥缕,只有Classic經(jīng)典隊(duì)列和Quorum仲裁隊(duì)列才能配置死信隊(duì)列,而目前Stream流式隊(duì)列宵呛,并不支持配置死信隊(duì)列单匣。

3.關(guān)于參數(shù)x-dead-letter-routing-key

死信在轉(zhuǎn)移到死信隊(duì)列時(shí),他的Routing key 也會(huì)保存下來(lái)烤蜕。但是如果配置了x-dead-letter-routing-key這個(gè)參數(shù)的話封孙,routingkey就會(huì)被替換為配置的這個(gè)值迹冤。

另外讽营,死信在轉(zhuǎn)移到死信隊(duì)列的過(guò)程中,是沒(méi)有經(jīng)過(guò)消息發(fā)送者確認(rèn)的泡徙,所以并不能保證消息的安全性橱鹏。

4.如何確定一個(gè)消息是不是死信

消息被作為死信轉(zhuǎn)移到死信隊(duì)列后,會(huì)在Header當(dāng)中增加一些消息堪藐。在官網(wǎng)的詳細(xì)介紹中莉兰,可以看到很多內(nèi)容,比如時(shí)間礁竞、原因(rejected,expired,maxlen)糖荒、隊(duì)列等。然后header中還會(huì)加上第一次成為死信的三個(gè)屬性模捂,并且這三個(gè)屬性在以后的傳遞過(guò)程中都不會(huì)更改捶朵。

1)x-first-death-reason

2)x-first-death-queue

3)x-first-death-exchange

5.死信隊(duì)列如何消費(fèi)

其實(shí)從前面的配置過(guò)程能夠看到,所謂死信交換機(jī)或者死信隊(duì)列狂男,不過(guò)是在交換機(jī)或者隊(duì)列之間建立一種死信對(duì)應(yīng)關(guān)系综看,而死信隊(duì)列可以像正常隊(duì)列一樣被消費(fèi)。他與普通隊(duì)列一樣具有FIFO的特性岖食。對(duì)死信隊(duì)列的消費(fèi)邏輯通常是對(duì)這些失效消息進(jìn)行一些業(yè)務(wù)上的補(bǔ)償红碑。

RabbitMQ中,是不存在延遲隊(duì)列的功能的泡垃,而通常如果要用到延遲隊(duì)列析珊,就會(huì)采用TTL+死信隊(duì)列的方式來(lái)處理羡鸥。

RabbitMQ提供了一個(gè)rabbitmq_delayed_message_exchange插件,可以實(shí)現(xiàn)延遲隊(duì)列的功能唾琼,但是并沒(méi)有集成到官方的發(fā)布包當(dāng)中兄春,需要單獨(dú)去下載。這里就不去討論了锡溯。

四赶舆、消費(fèi)優(yōu)先級(jí)與流量控制

文檔地址:?https://www.rabbitmq.com/consumer-priority.html

關(guān)于消費(fèi)隊(duì)列的優(yōu)先級(jí),關(guān)鍵是x-priority?這個(gè)參數(shù)祭饭,可以指定隊(duì)列的優(yōu)先級(jí)芜茵。默認(rèn)情況下,RabbitMQ會(huì)根據(jù)round-robin策略倡蝙,把消息均勻的給不同的消費(fèi)者進(jìn)行處理九串。但是有了優(yōu)先級(jí)之后,RabbitMQ會(huì)保證優(yōu)先級(jí)高的隊(duì)列先進(jìn)行消費(fèi)寺鸥,而同一優(yōu)先級(jí)的隊(duì)列猪钮,還是會(huì)使用round-robin輪詢策略來(lái)進(jìn)行分配。

與之對(duì)應(yīng)的是RabbitMQ的流量控制配置胆建,關(guān)鍵是channel.basicQos(int prefetch_size, int prefetch_count, boolean global)烤低。 這個(gè)方法中,prefetch_count設(shè)置了當(dāng)前消費(fèi)者節(jié)點(diǎn)最多保持的未答復(fù)的消息個(gè)數(shù)笆载, prefetch_size設(shè)置了當(dāng)前消費(fèi)節(jié)點(diǎn)最多保持的未答復(fù)的消息大小扑馁,然后global參數(shù)為true則表示該配置針對(duì)當(dāng)前channel的所有隊(duì)列,而默認(rèn)情況下是false凉驻,表示該配置只針對(duì)當(dāng)前消費(fèi)者隊(duì)列腻要。最常用的方式就是只設(shè)定一個(gè)prefetch_count參數(shù)。

這兩個(gè)參數(shù)實(shí)際上都是為了配置當(dāng)前消費(fèi)節(jié)點(diǎn)的消息吞吐量涝登。當(dāng)消費(fèi)者集群中的業(yè)務(wù)處理能力或者消息配置不一樣時(shí)雄家,可以通過(guò)給不同的消費(fèi)節(jié)點(diǎn)配置不同的prefetch_count,再結(jié)合消費(fèi)優(yōu)先級(jí)的配置來(lái)實(shí)現(xiàn)流量控制策略胀滚。

五趟济、遠(yuǎn)程數(shù)據(jù)分發(fā)插件-Federation Plugin

如果我們需要在多個(gè)RabbitMQ服務(wù)之間進(jìn)行消息同步,那么蛛淋,首選的方案自然是通過(guò)RabbitMQ集群來(lái)進(jìn)行咙好。但是,在某些網(wǎng)絡(luò)狀況比較差的場(chǎng)景下褐荷,搭建集群會(huì)不太方便勾效。例如,某大型企業(yè),可能在北京機(jī)房和長(zhǎng)沙機(jī)房分別搭建RabbitMQ服務(wù)层宫,然后希望長(zhǎng)沙機(jī)房需要同步北京機(jī)房的消息杨伙,這樣可以讓長(zhǎng)沙的消費(fèi)者服務(wù)可以直接連接長(zhǎng)沙本地的RabbitMQ,而不用費(fèi)盡周折去連接北京機(jī)房的RabbitMQ服務(wù)萌腿。這時(shí)要如何進(jìn)行數(shù)據(jù)同步呢限匣?搭建一個(gè)網(wǎng)絡(luò)跨度這么大的集群顯然就不太劃算。這時(shí)就可以考慮使用RabbitMQ的Federation插件毁菱,搭建聯(lián)邦隊(duì)列Federation米死。通過(guò)Federation可以搭建一個(gè)單向的數(shù)據(jù)同步通道(當(dāng)然,要搭建雙相同步也是可以的)贮庞。

1.啟動(dòng)插件

RabbitMQ的官方運(yùn)行包中已經(jīng)包含了Federation插件峦筒,只需要啟動(dòng)后就可以直接使用。

插件啟用完成后窗慎,可以在管理控制臺(tái)的Admin菜單看到兩個(gè)新增選項(xiàng) Federation Status和Federation Upstreams物喷。

2.配置Upstream

Upstream表示是一個(gè)外部的服務(wù)節(jié)點(diǎn),在RabbitMQ中遮斥,可以是一個(gè)交換機(jī)峦失,也可以是一個(gè)隊(duì)列。他的配置方式是由下游服務(wù)主動(dòng)配置一個(gè)與上游服務(wù)的鏈接术吗,然后數(shù)據(jù)就會(huì)從上游服務(wù)主動(dòng)同步到下游服務(wù)中尉辑。

接下來(lái)我們用本地localhost的RabbitMQ服務(wù)來(lái)模擬DownStream下游服務(wù),去指向一個(gè)worker2機(jī)器上搭建的RabbitMQ服務(wù)藐翎,搭建一個(gè)聯(lián)邦交換機(jī)Federation Exchange材蹬。

先在本地用程序的方式实幕,聲明一個(gè)交換機(jī)和交換隊(duì)列吝镣。

然后在本地RabbitMQ中配置一個(gè)上游服務(wù),服務(wù)的名字Name屬性隨意昆庇,URI指向Worker2上的/mirror虛擬機(jī)(配置方式參看頁(yè)面上的示例):amqp://admin:admin@worker2:5672/ (注意末贾,在添加時(shí),如果指定了Upstream的Virtual Host是mirror整吆,那么在URI中就不能再添加Virtual host配置了拱撵,默認(rèn)會(huì)在上游服務(wù)中使用相同的VirtualHost。)

注意:?

1表蝙、其他的相關(guān)參數(shù)拴测,可以在頁(yè)面上查看幫助。例如府蛇,默認(rèn)情況下集索,Upstream會(huì)使用和Downstream同名的Exchange,但是也可以通過(guò)Upstream配置中的Exchange參數(shù)指定不同的。

2务荆、關(guān)于Virtual Host虛擬機(jī)配置妆距,如果在配置Upstream時(shí)指定了Virtual Host屬性,那么在URI中就不能再添加Virtaul Host配置了函匕,默認(rèn)會(huì)在Upstream上使用相同的Virtual Host娱据。

3.配置Federation策略

接下來(lái)需要配置一個(gè)指向上游服務(wù)的Federation策略。在配置策略時(shí)可以選擇是針對(duì)Exchange交換機(jī)還是針對(duì)Queue隊(duì)列盅惜。配置策略時(shí)中剩,同樣有很多參數(shù)可以選擇配置。最簡(jiǎn)化的一個(gè)配置如下:

注意:每個(gè)策略的Definition部分抒寂,至少需要指定一個(gè)Federation目標(biāo)咽安。federation-upstream-set參數(shù)表示是以set集合的方式針對(duì)多個(gè)Upstream生效,all表示是全部Upstream蓬推。而federation-upstream參數(shù)表示只對(duì)某一個(gè)Upstream生效妆棒。

4.測(cè)試

?配置完Upstream和對(duì)應(yīng)的策略后,進(jìn)入Federation Status菜單就能看到Federation插件的執(zhí)行情況沸伏。狀態(tài)為running表示啟動(dòng)成功糕珊,如果配置出錯(cuò),則會(huì)提示失敗原因這個(gè)提示非常非常簡(jiǎn)單毅糟。

然后红选,在遠(yuǎn)程服務(wù)Worker2的RabbitMQ服務(wù)中,可以看到對(duì)應(yīng)生成的Federation交換機(jī)姆另。

接下來(lái)就可以嘗試在上游服務(wù)Worker2的fed_exchange中發(fā)送消息喇肋,消息會(huì)同步到Local本地的聯(lián)邦交換機(jī)中,從而被對(duì)應(yīng)的消費(fèi)者消費(fèi)到迹辐。

在很多網(wǎng)絡(luò)情況復(fù)雜的大型項(xiàng)目中蝶防,F(xiàn)ederation插件甚至?xí)如R像集群使用更多,這也是為什么RabbitMQ有了集群機(jī)制后明吩,依然一直保留著Federation插件间学。

在我們的實(shí)驗(yàn)過(guò)程中,會(huì)在上游服務(wù)重新生成一個(gè)新的Exchange交換機(jī)印荔,這顯然是不太符合實(shí)際情況的低葫。我們通常的使用方式是希望將上游MQ中的某一個(gè)已有的Exchange交換機(jī)或者Queue隊(duì)列的數(shù)據(jù)同步到下游一個(gè)新的Exchange或者Queue中。這要如何配置呢仍律?大家自行理解實(shí)驗(yàn)把嘿悬。

六、懶隊(duì)列 Lazy Queue

文檔地址:?https://www.rabbitmq.com/lazy-queues.html

RabbitMQ從3.6.0版本開(kāi)始水泉,就引入了懶隊(duì)列的概念善涨。懶隊(duì)列會(huì)盡可能早的將消息內(nèi)容保存到硬盤當(dāng)中主到,并且只有在用戶請(qǐng)求到時(shí),才臨時(shí)從硬盤加載到RAM內(nèi)存當(dāng)中躯概。

懶隊(duì)列的設(shè)計(jì)目標(biāo)是為了支持非常長(zhǎng)的隊(duì)列(數(shù)百萬(wàn)級(jí)別)登钥。隊(duì)列可能會(huì)因?yàn)橐恍┰蜃兊梅浅iL(zhǎng)-也就是數(shù)據(jù)堆積:

1)消費(fèi)者服務(wù)宕機(jī)了

2)有一個(gè)突然的消息高峰,生產(chǎn)者生產(chǎn)消息超過(guò)消費(fèi)者

3)消費(fèi)者消費(fèi)太慢了

默認(rèn)情況下娶靡,RabbitMQ接收到消息時(shí)牧牢,會(huì)保存到內(nèi)存以便使用,同時(shí)把消息寫到硬盤姿锭。但是塔鳍,消息寫入硬盤的過(guò)程中,是會(huì)阻塞隊(duì)列的呻此。RabbitMQ雖然針對(duì)寫入硬盤速度做了很多算法優(yōu)化轮纫,但是在長(zhǎng)隊(duì)列中,依然表現(xiàn)不是很理想焚鲜,所以就有了懶隊(duì)列的出現(xiàn)掌唾。

懶隊(duì)列會(huì)嘗試盡可能早的把消息寫到硬盤中。這意味著在正常操作的大多數(shù)情況下忿磅,RAM中要保存的消息要少得多糯彬。當(dāng)然,這是以增加磁盤IO為代價(jià)的葱她。

聲明懶隊(duì)列有兩種方式:

1撩扒、給隊(duì)列指定參數(shù)

在代碼中可以通過(guò)x-queue-mode參數(shù)指定:

2、設(shè)定一個(gè)策略吨些,在策略中指定queue-mode 為 lazy

要注意的是搓谆,當(dāng)一個(gè)隊(duì)列被聲明為懶隊(duì)列,那即使隊(duì)列被設(shè)定為不持久化豪墅,消息依然會(huì)寫入到硬盤中泉手。并且,在鏡像集群中但校,大量的消息也會(huì)被同步到當(dāng)前節(jié)點(diǎn)的鏡像節(jié)點(diǎn)當(dāng)中螃诅,并寫入硬盤啡氢。這會(huì)給集群資源造成很大的負(fù)擔(dān)状囱。

最后一句話總結(jié):懶隊(duì)列適合消息量大且長(zhǎng)期有堆積的隊(duì)列,可以減少內(nèi)存使用倘是,加快消費(fèi)速度亭枷。但是這是以大量消耗集群的網(wǎng)絡(luò)及磁盤IO為代價(jià)的

七搀崭、消息分片存儲(chǔ)插件-Sharding Plugin

談到Sharding叨粘,你是不是就想到了分庫(kù)分表猾编?對(duì)于數(shù)據(jù)庫(kù)的分庫(kù)分表,分庫(kù)可以減少數(shù)據(jù)庫(kù)的IO性能壓力升敲,而真正要解決單表數(shù)據(jù)太大的問(wèn)題答倡,就需要分表。

對(duì)于RabbitMQ同樣驴党,通過(guò)集群模式瘪撇,能夠增大他的吞吐量,但是港庄,針對(duì)單個(gè)隊(duì)列倔既,如何增加吞吐量呢?普通集群保證不了數(shù)據(jù)的高可用鹏氧,而鏡像隊(duì)列雖然可以保證消息高可用渤涌,但是消費(fèi)者并不能對(duì)消息增加消費(fèi)并發(fā)度,所以把还,RabbitMQ的集群機(jī)制并不能增加單個(gè)隊(duì)列的吞吐量实蓬。

上面的懶隊(duì)列其實(shí)就是針對(duì)這個(gè)問(wèn)題的一種解決方案。但是很顯然吊履,懶隊(duì)列的方式屬于治標(biāo)不治本瞳秽。真正要提升RabbitMQ單隊(duì)列的吞吐量,還是要從數(shù)據(jù)也就是消息入手率翅,只有將數(shù)據(jù)真正的分開(kāi)存儲(chǔ)才行练俐。RabbitMQ提供的Sharding插件,就是一個(gè)可選的方案冕臭。他會(huì)真正將一個(gè)隊(duì)列中的消息分散存儲(chǔ)到不同的節(jié)點(diǎn)上腺晾,并提供多個(gè)節(jié)點(diǎn)的負(fù)載均衡策略實(shí)現(xiàn)對(duì)等的讀與寫功能。

1.安裝Sharding插件

在當(dāng)前RabbitMQ的運(yùn)行版本中辜贵,已經(jīng)包含了Sharding插件悯蝉,需要使用插件時(shí),只需要安裝啟用即可托慨。

2.配置Sharding策略

啟用完成后鼻由,需要配置Sharding的策略。

按照要求厚棵,就可以配置一個(gè)針對(duì)sharding_開(kāi)頭的交換機(jī)和隊(duì)列的策略:

3.新增帶Sharding的Exchange交換機(jī)

?在創(chuàng)建隊(duì)列時(shí)蕉世,可以看到,安裝了Sharding插件后婆硬,多出了一種隊(duì)列類型狠轻,x-modulus-hash:

4.往分片交換機(jī)上發(fā)送消息

?接下來(lái),就可以用下面的生產(chǎn)者代碼彬犯,在RabbitMQ上聲明一個(gè)x-modulus-hash類型的交換機(jī)向楼,并往里面發(fā)送一萬(wàn)條消息查吊。

啟動(dòng)后,就會(huì)在RabbitMQ上聲明一個(gè)sharding_exchange湖蜕。查看這個(gè)交換機(jī)的詳情逻卖,可以看到他的分片情況:

并且,一萬(wàn)條消息被平均分配到了三個(gè)隊(duì)列當(dāng)中:

Sharding插件帶來(lái)的x-modulus-hash類型Exchange昭抒,會(huì)忽略之前的routingkey配置箭阶,而將消息以輪詢的方式平均分配到Exchange綁定的所有隊(duì)列上。

5.消費(fèi)分片交換機(jī)上的消息

現(xiàn)在sharding2_exchange交換機(jī)上的消息已經(jīng)平均分配到了三個(gè)碎片隊(duì)列上戈鲁。這時(shí)如何去消費(fèi)這些消息呢仇参?你會(huì)發(fā)現(xiàn)這些碎片隊(duì)列的名字并不是毫無(wú)規(guī)律的,他是有一個(gè)固定的格式的婆殿。都是固定的這種格式:sharding: {exchangename}-{node}-{shardingindex}?诈乒。你當(dāng)然可以針對(duì)每個(gè)隊(duì)列去單獨(dú)聲明消費(fèi)者,這樣當(dāng)然是能夠消費(fèi)到消息的婆芦,但是這樣怕磨,你消費(fèi)到的消息就是一些零散的消息了,這不符合分片的業(yè)務(wù)場(chǎng)景要求消约。

數(shù)據(jù)分片后肠鲫,還是希望能夠像一個(gè)普通隊(duì)列一樣消費(fèi)到完整的數(shù)據(jù)副本。這時(shí)或粮,Sharding插件提供了一種偽隊(duì)列的消費(fèi)方式导饲。你可以聲明一個(gè)名字為?exchangename?的偽隊(duì)列,然后像消費(fèi)一個(gè)普通隊(duì)列一樣去消費(fèi)這一系列的碎片隊(duì)列氯材。

為什么說(shuō)是偽隊(duì)列渣锦?exchange、queue傻傻分不清楚氢哮?因?yàn)槊麨閑xchangename的隊(duì)列實(shí)際是不存在的袋毙。

6.注意事項(xiàng)

Sharding插件將消息分散存儲(chǔ)時(shí),是盡量按照輪詢的方式進(jìn)行冗尤。

首先听盖,這些消息在分片的過(guò)程中,是沒(méi)有考慮消息順序的裂七,這會(huì)讓RabbitMQ中原本就不是很嚴(yán)謹(jǐn)?shù)南㈨樞蜃兊酶友┥霞铀钥础K裕?b>Sharding插件適合于那些對(duì)于消息延遲要求不嚴(yán)格,以及對(duì)消費(fèi)順序沒(méi)有任何要求的的場(chǎng)景碍讯。

然后悬蔽,Sharding插件消費(fèi)偽隊(duì)列的消息時(shí),會(huì)從消費(fèi)者最少的碎片中選擇隊(duì)列捉兴。這時(shí)蝎困,如果你的這些碎片隊(duì)列中已經(jīng)有了很多其他的消息,那么再去消費(fèi)偽隊(duì)列消息時(shí)倍啥,就會(huì)受到這些不均勻數(shù)據(jù)的影響禾乘。所以,如果使用Sharding插件虽缕,這些碎片隊(duì)列就盡量不要單獨(dú)使用了始藕。

RabbitMQ針對(duì)各種復(fù)雜場(chǎng)景,還有非常多精妙的設(shè)計(jì)以及擴(kuò)展氮趋。我們多學(xué)習(xí)一些擴(kuò)展的場(chǎng)景伍派,也還只是冰山一角,但是剩胁,這些場(chǎng)景已經(jīng)超出了國(guó)內(nèi)80%企業(yè)的應(yīng)用范圍诉植。多學(xué)習(xí)了解這些擴(kuò)展場(chǎng)景,對(duì)我們的好處不光是能把RabbitMQ用得更好昵观,更重要在于能幫你更深入的理解MQ的應(yīng)用場(chǎng)景以及各種細(xì)節(jié)問(wèn)題晾腔。而對(duì)于業(yè)務(wù)問(wèn)題挖掘深度,才是決定一個(gè)程序員實(shí)力的前提啊犬。

?如果你回頭再看下這一章節(jié)的各種復(fù)雜場(chǎng)景灼擂,你會(huì)發(fā)現(xiàn),這一章節(jié)中的隊(duì)列觉至,還全都只是回到了最初的經(jīng)典隊(duì)列剔应。如果結(jié)合這些場(chǎng)景,再依次來(lái)分析一下新出的Quorum隊(duì)列语御,Stream隊(duì)列领斥,你會(huì)有什么感覺(jué)?

你以為你學(xué)懂了RabbitMQ沃暗,其實(shí)只是坐井觀天月洛。學(xué)得越多,不懂的也越多孽锥!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末嚼黔,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子惜辑,更是在濱河造成了極大的恐慌唬涧,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盛撑,死亡現(xiàn)場(chǎng)離奇詭異碎节,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)抵卫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門狮荔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)胎撇,“玉大人,你說(shuō)我怎么就攤上這事殖氏⊥硎鳎” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵雅采,是天一觀的道長(zhǎng)爵憎。 經(jīng)常有香客問(wèn)我,道長(zhǎng)婚瓜,這世上最難降的妖魔是什么宝鼓? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮巴刻,結(jié)果婚禮上愚铡,老公的妹妹穿的比我還像新娘。我一直安慰自己冈涧,他們只是感情好茂附,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著督弓,像睡著了一般营曼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上愚隧,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天蒂阱,我揣著相機(jī)與錄音,去河邊找鬼狂塘。 笑死录煤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的荞胡。 我是一名探鬼主播妈踊,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼泪漂!你這毒婦竟也來(lái)了廊营?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤萝勤,失蹤者是張志新(化名)和其女友劉穎露筒,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體敌卓,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡慎式,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘪吏。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡癣防,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肪虎,到底是詐尸還是另有隱情劣砍,我是刑警寧澤惧蛹,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布扇救,位于F島的核電站,受9級(jí)特大地震影響香嗓,放射性物質(zhì)發(fā)生泄漏迅腔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一靠娱、第九天 我趴在偏房一處隱蔽的房頂上張望沧烈。 院中可真熱鬧,春花似錦像云、人聲如沸锌雀。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)腋逆。三九已至,卻和暖如春侈贷,著一層夾襖步出監(jiān)牢的瞬間惩歉,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工俏蛮, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留撑蚌,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓搏屑,卻偏偏與公主長(zhǎng)得像争涌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子辣恋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

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