摘要:本文整理自滴滴的江海挺在2018年9月1日Apache RocketMQ開發(fā)者沙龍北京站的分享。江海挺是Apache RocketMQ Contributor杰刽,北大信科畢業(yè)后菠发,一直在做消息隊(duì)列相關(guān)的服務(wù)王滤,在消息隊(duì)列方面積累了豐富的經(jīng)驗(yàn)。
本文的主要內(nèi)容包括以下幾個(gè)方面:
- 滴滴的消息技術(shù)選型
- 為什么選擇RocketMQ
- 如何構(gòu)建自己的消息隊(duì)列服務(wù)
- RocketMQ擴(kuò)展改造
- RocketMQ使用經(jīng)驗(yàn)
1. 滴滴的消息技術(shù)選型
1.1 消息歷史
如圖滓鸠,初期公司內(nèi)部沒有專門的團(tuán)隊(duì)維護(hù)消息隊(duì)列服務(wù)雁乡,所以消息隊(duì)列使用方式較多,主要以kafka為主糜俗,有業(yè)務(wù)直連的踱稍,也有通過獨(dú)立的服務(wù)轉(zhuǎn)發(fā)消息的。另外有一些團(tuán)隊(duì)也會用 RocketMQ吩跋、Redis的list寞射,甚至?xí)帽容^非主流的beanstalkkd。導(dǎo)致的結(jié)果就是锌钮,比較混亂桥温,無法維護(hù),資源使用也很浪費(fèi)梁丘。
1.2 棄用kafka
一個(gè)核心業(yè)務(wù)在使用kafka的時(shí)候侵浸,出現(xiàn)了集群數(shù)據(jù)寫入抖動(dòng)非常嚴(yán)重的情況,經(jīng)常會有數(shù)據(jù)寫失敗氛谜。
主要有兩點(diǎn)原因:
- 隨著業(yè)務(wù)增長掏觉,topic的數(shù)據(jù)增多,集群負(fù)載增大值漫,性能下降澳腹。
- 我們用的是kafka 0.8.2那個(gè)版本,有個(gè)bug杨何,會導(dǎo)致副本重新復(fù)制酱塔,復(fù)制的時(shí)候有大量的讀,我們存儲盤用的又是機(jī)械盤危虱,導(dǎo)致磁盤IO過大羊娃,影響寫入。
所以我們決定做自己的消息隊(duì)列服務(wù)埃跷。
首先需要解決上面的解決業(yè)務(wù)方消息生產(chǎn)失敗的問題蕊玷。因?yàn)檫@個(gè)kafka用的是發(fā)布/訂閱模式,一個(gè)topic的訂閱方會有很多弥雹,涉及到的下游業(yè)務(wù)也就非常多垃帅,沒辦法一口氣直接替換kafka,遷移到新的一個(gè)消息隊(duì)列服務(wù)上缅糟。
所以我們當(dāng)時(shí)的方案是加了一層代理挺智,然后利用codis作為緩存,解決了kafka不定期寫入失敗的問題,如上圖赦颇。
就是當(dāng)后面的kafka出現(xiàn)不可寫入的時(shí)候二鳄,我們就會先把數(shù)據(jù)寫入到codis中,然后延時(shí)進(jìn)行重試媒怯,直到寫成功為止订讼。
1.3 選擇RocketMQ
經(jīng)過一系列的調(diào)研和測試之后,我們決定采用RocketMQ扇苞。具體原因在后面會介紹欺殿。
為了支持多語言環(huán)境、解決一些遷移和某些業(yè)務(wù)的特殊需求鳖敷,我們又在消費(fèi)側(cè)加上了一個(gè)代理服務(wù)脖苏。
然后形成了這么一個(gè)核心框架。業(yè)務(wù)端只跟代理層交互定踱。中間的消息引擎棍潘,負(fù)責(zé)消息的核心存儲。
在之前的基本框架之后崖媚,我們后面就主要圍繞三個(gè)方向做亦歉。
一個(gè)是遷移。把之前提到的所有五花八門的隊(duì)列環(huán)境畅哑,全部遷移到我們上面肴楷。這里面的遷移方案后面會跟大家介紹一下。
第二個(gè)就是功能迭代和成本性能上的優(yōu)化荠呐。
最后一個(gè)重點(diǎn)就是服務(wù)化赛蔫,業(yè)務(wù)直接通過平臺界面來申請資源,申請到之后直接使用泥张。
1.4 演進(jìn)中的架構(gòu)
這張圖是我們消息隊(duì)列服務(wù)的一個(gè)比較新的現(xiàn)狀濒募。
先縱向看,上面是生產(chǎn)的客戶端圾结,包括了7種語言。然后是我們的生產(chǎn)代理服務(wù)齿诉。
在中間的是我們的消息存儲層筝野。目前主要的消息存儲引擎是RocketMQ。然后還有一些在遷移過程中的Kafka粤剧。還有一個(gè)chronos歇竟,它是我們延遲消息的一個(gè)存儲引擎。
再下面就是消費(fèi)代理抵恋。
消費(fèi)代理同樣提供了多種語言的客戶端焕议。然后還支持多種協(xié)議的消息主動(dòng)推送功能。包括HTTP 協(xié)議 RESTful方式弧关。結(jié)合我們的groovy腳本功能盅安,還能實(shí)現(xiàn)將消息直接轉(zhuǎn)存到redis唤锉、hbase和hdfs上。更多的下游存儲别瞭,我們都在陸續(xù)接入窿祥。
除了存儲系統(tǒng)之外,我們還對接了實(shí)時(shí)計(jì)算平臺蝙寨,像Flink晒衩,Spark,Storm這些平臺墙歪,我們也都提供了支持听系。
左邊是我們的用戶控制臺和運(yùn)維控制臺。這個(gè)是我們服務(wù)化的重點(diǎn)虹菲。
用戶在需要使用隊(duì)列的時(shí)候靠胜,就通過界面申請topic,填寫各種信息届惋,包括身份信息髓帽,消息的峰值流量,消息大小脑豹,消息格式等等郑藏。
然后消費(fèi)方,通過我們的界面瘩欺,就可以申請消費(fèi)必盖。
運(yùn)維控制臺,主要負(fù)責(zé)我們集群的管理俱饿,自動(dòng)化部署歌粥,流量調(diào)度,狀態(tài)顯示之類的功能拍埠。
最后所有運(yùn)維和用戶操作會影響線上的配置失驶,都會通過zookeeper進(jìn)行同步。
2. 為什么選擇RocketMQ
因?yàn)閺膶?shí)際測試結(jié)果來看枣购,RocketMQ的效果更好嬉探。
主要圍繞兩個(gè)測試進(jìn)行。
2.1 測試-topic數(shù)量的支持
如下圖所示棉圈,測試環(huán)境:
Kafka 0.8.2
RocketMQ 3.4.6
1.0 Gbps Network
16 threads
這張圖是Kafka和RocketMQ在不同topic數(shù)量下的吞吐測試涩堤。橫坐標(biāo)是每秒消息數(shù),縱坐標(biāo)是測試case分瘾。同時(shí)覆蓋了有無消費(fèi)胎围,和不同消息體的場景。一共8組測試數(shù)據(jù),每組數(shù)據(jù)分別在topic個(gè)數(shù)為16白魂、32汽纤、64、128碧聪、256時(shí)獲得的冒版,每個(gè)topic包括8個(gè)partition。下面四組數(shù)據(jù)是發(fā)送消息大小為128字節(jié)的情況逞姿,上面四種是發(fā)送2k消息大小的情況晒奕。on 表示消息發(fā)送的時(shí)候芦圾,同時(shí)進(jìn)行消息消費(fèi),off表示僅進(jìn)行消息發(fā)送。
先看最上面一組數(shù)據(jù)晰韵,用的是kafka推掸,開啟消費(fèi)游岳,每條消息大小為2048字節(jié)身隐。可以看到买窟,隨著topic數(shù)量增加丰泊,到256 topic之后,吞吐極具下始绍。
可以先看最上面的一組結(jié)果瞳购,用的是Kafka,開啟消費(fèi)亏推,每條消息是2kb(2048)学赛。可以看到吞杭,隨著topic數(shù)量增加盏浇,到256個(gè)topic之后,吞吐急劇下降芽狗。
第二組是是RocketMQ绢掰⊥妫可以看到,topic增大之后,影響非常小乙嘀。
第三組和第四組虎谢,是上面兩組關(guān)閉了消費(fèi)的情況。結(jié)論基本類似擎场,整體吞吐量會高那么一點(diǎn)點(diǎn)章蚣。
下面的四組跟上面的區(qū)別是使用了128字節(jié)的小消息體矾策〖炙洌可以看到榄鉴,kafka吞吐受topic數(shù)量的影響特別明顯驶忌。對比來看飞蹂,雖然topic比較小的時(shí)候伸眶,RocketMQ吞吐較小,但是基本非常穩(wěn)定,對于我們這種共享集群來說比較友好族铆。
2.2 測試-延遲
- Kafka
測試環(huán)境:
Kafka 0.8.2.2
topic=1/8/32
Ack=1/all栅葡,replica=3
測試結(jié)果:如下圖
(橫坐標(biāo)對應(yīng)吞吐,縱坐標(biāo)對應(yīng)延遲時(shí)間)
上面的一組的3條線對應(yīng)ack=3欣簇,需要3個(gè)備份都確認(rèn)后才完成數(shù)據(jù)的寫入规脸。
下面的一組的3條線對應(yīng)ack=1,有1個(gè)備份收到數(shù)據(jù)后就可以完成寫入熊咽。
可以看到下面一組只需要主備份確認(rèn)的寫入莫鸭,延遲明顯較低。
每組的三條線之間主要是topic數(shù)量的區(qū)別横殴,topic數(shù)量增加被因,延遲也增大了。
- RocketMQ
測試環(huán)境:
RocketMQ 3.4.6
brokerRole=ASYNC/SYNC_MASTER, 2 Slave
flushDiskType=SYNC_FLUSH/ASYNC_FLUSH
測試結(jié)果:如下圖
上面兩條是同步刷盤的情況衫仑,延遲相對比較高梨与。下面的是異步刷盤。
橙色的線是同步主從文狱,藍(lán)色的線是異步主從粥鞋。
然后可以看到在副本同步復(fù)制的情況下,即橙色的線瞄崇,4w的tps之內(nèi)都不超過1ms陷虎。用這條橙色的線和上面Kafka的圖中的上面三條線橫向比較來看到踏,kafka超過1w tps 就超過1ms了。kafka的延遲明顯更高尚猿。
3. 如何構(gòu)建自己的消息隊(duì)列服務(wù)
3.1 問題與挑戰(zhàn)
面臨的挑戰(zhàn)(順時(shí)針看):
- 客戶端語言。需要支持PHP楣富、GO凿掂、Java、C++纹蝴。
- 只有3個(gè)開發(fā)人員庄萎。
- 決定用RocketMQ,但是沒看過源碼塘安。
- 上線時(shí)間緊糠涛,線上的kafka還有問題。
- 可用性要求高兼犯。
使用RocketMQ時(shí)的兩個(gè)問題:
- 客戶端語言支持不全忍捡,它主要支持Java,而我們還需要支持PHP切黔、Go砸脊、C++,RocketMQ目前提供的Go的sdk我們測的有一些問題纬霞。
- 功能特別多凌埂,如tag、property诗芜、消費(fèi)過濾瞳抓、RETRY topic、死信隊(duì)列伏恐、延遲消費(fèi)之類的功能孩哑,非常豐富。但是這個(gè)對我們穩(wěn)定性維護(hù)來說脐湾,挑戰(zhàn)非常大臭笆。
解決辦法,如下圖所示:
使用Thrift RPC框架來解決跨語言的問題秤掌。
簡化調(diào)用接口愁铺。可以認(rèn)為只有兩個(gè)接口闻鉴,send用來生產(chǎn)茵乱,pull用來消費(fèi)。
主要策略就是堅(jiān)持KISS原則(Keep it simple, stupid)孟岛,保持簡單瓶竭,先解決最主要的問題督勺,讓消息能夠流轉(zhuǎn)起來。
然后我們把其他主要邏輯都放在了proxy這一層來做斤贰,比如限流智哀、權(quán)限認(rèn)證、消息過濾荧恍、格式轉(zhuǎn)化之類的瓷叫。這樣,我們就能盡可能地簡化客戶端的實(shí)現(xiàn)邏輯送巡,不需要把很多功能用各種語言都寫一遍摹菠。
3.2 遷移方案
架構(gòu)確定后,接下來是我們的一個(gè)遷移過程骗爆。
遷移這個(gè)事情次氨,在pub-sub的消息模型下,會比較復(fù)雜摘投。因?yàn)橄掠蔚臄?shù)據(jù)消費(fèi)方可能很多煮寡,上游的數(shù)據(jù)沒法做到一刀切流量,這就會導(dǎo)致整個(gè)遷移的周期特別長谷朝。然后我們?yōu)榱吮M可能地減少業(yè)務(wù)遷移的負(fù)擔(dān)洲押,加快遷移的效率,我們在proxy層提供了雙寫和雙讀的功能圆凰。
- 雙寫:Procucer Proxy同時(shí)寫RocketMQ和kafka杈帐。
- 雙讀:Consumer Proxy同時(shí)從RocketMQ和kafka消費(fèi)數(shù)據(jù)。
有了這兩個(gè)功能之后专钉,我們就能提供以下兩種遷移方案了挑童。
3.2.1 雙寫
生產(chǎn)端雙寫,同時(shí)往kafka和rocketmq寫同樣的數(shù)據(jù)跃须,保證兩邊在整個(gè)遷移過程中都有同樣的全量數(shù)據(jù)站叼。kafka和RocketMQ有相同的數(shù)據(jù),這樣下游的業(yè)務(wù)也就可以開始遷移菇民。
如果消費(fèi)端不關(guān)心丟數(shù)據(jù)尽楔,那么可以直接切換,切完直接更新消費(fèi)進(jìn)度第练。
如果需要保證消費(fèi)必達(dá)阔馋,可以先在Consumer Proxy設(shè)置消費(fèi)進(jìn)度,消費(fèi)客戶端保證沒有數(shù)據(jù)堆積后再去遷移娇掏,這樣會有一些重復(fù)消息呕寝,一般客戶端會保證消費(fèi)處理的冪等。
生產(chǎn)端的雙寫其實(shí)也有兩種方案:
- 客戶端雙寫婴梧,如下圖:
業(yè)務(wù)那邊不停原來的kafka 客戶端下梢。只是加上我們的客戶端客蹋,往RocketMQ里追加寫。
這種方案在整個(gè)遷移完成之后孽江,業(yè)務(wù)還需要把老的寫入停掉讶坯。相當(dāng)于兩次上線。
- Producer Proxy雙寫岗屏,如下圖:
業(yè)務(wù)方直接切換生產(chǎn)的客戶端闽巩,只往我們的proxy上寫數(shù)據(jù)。然后我們的proxy負(fù)責(zé)把數(shù)據(jù)復(fù)制担汤,同時(shí)寫到兩個(gè)存儲引擎中。
這樣在遷移完成之后洼冻,我們只需要在proxy上關(guān)掉雙寫功能就可以了崭歧。對生產(chǎn)的業(yè)務(wù)方來說是無感知的,生產(chǎn)方全程只需要改造一次撞牢,上一下線就可以了率碾。
所以表面看起來,應(yīng)該還是第二種方案更加簡單屋彪。但是所宰,從整體可靠性的角度來看,一般還是認(rèn)為第一種相對高一點(diǎn)畜挥。因?yàn)榭蛻舳说絢afka這一條鏈路仔粥,業(yè)務(wù)之前都已經(jīng)跑穩(wěn)定了。一般不會出問題蟹但。但是寫我們proxy就不一定了躯泰,在接入過程中,是有可能出現(xiàn)一些使用上的問題华糖,導(dǎo)致數(shù)據(jù)寫入失敗麦向,這就對業(yè)務(wù)方測試質(zhì)量的要求會高一點(diǎn)。
然后消費(fèi)的遷移過程客叉,其實(shí)風(fēng)險(xiǎn)是相對比較低的诵竭。出問題的時(shí)候,可以立即回滾兼搏。因?yàn)樗诶系膋afka上消費(fèi)進(jìn)度卵慰,是一直保留的,而且在遷移過程中向族,可以認(rèn)為是全量雙消費(fèi)呵燕。
以上就是數(shù)據(jù)雙寫的遷移方案,這種方案的特點(diǎn)就是兩個(gè)存儲引擎都有相同的全量數(shù)據(jù)件相。
3.2.2 雙讀
特點(diǎn):保證不會重復(fù)消費(fèi)再扭。對于p2p 或者消費(fèi)下游不太多氧苍,或者對重復(fù)消費(fèi)數(shù)據(jù)比較敏感的場景比較適用。
這個(gè)方案的過程是這樣的泛范,消費(fèi)先切換让虐。全部遷移到到我們的proxy上消費(fèi),proxy從kafka上獲取罢荡。這個(gè)時(shí)候rocketmq上沒有流量赡突。但是我們的消費(fèi)proxy保證了雙消費(fèi),一旦rocketmq有流量了区赵,客戶端同樣也能收到惭缰。
然后生產(chǎn)方改造客戶端,直接切流到rocketmq中笼才,這樣就完成了整個(gè)流量遷移過程漱受。
運(yùn)行一段時(shí)間,比如kafka里的數(shù)據(jù)都過期之后骡送,就可以把消費(fèi)proxy上的雙消費(fèi)關(guān)了昂羡,下掉kafka集群。
整個(gè)過程中摔踱,生產(chǎn)直接切流虐先,所以數(shù)據(jù)不會重復(fù)存儲。然后在消費(fèi)遷移的過程中派敷,我們消費(fèi)proxy上的group和業(yè)務(wù)原有的group可以用一個(gè)名字蛹批,這樣就能實(shí)現(xiàn)遷移過程中自動(dòng)rebalance,這樣就能實(shí)現(xiàn)沒有大量重復(fù)數(shù)據(jù)的效果膀息。
所以這個(gè)方案對重復(fù)消費(fèi)比較敏感的業(yè)務(wù)會比較適合的般眉。
這個(gè)方案的整個(gè)過程中,消費(fèi)方和生產(chǎn)方都只需要改造一遍客戶端潜支,上一次線就可以完成甸赃。
4. RocketMQ擴(kuò)展改造
說完遷移方案,這里再簡單介紹一下冗酿,我們在我們的rocketmq分支上做的一些比較重要的事情埠对。
首先一個(gè)非常重要的一點(diǎn)是主從的自動(dòng)切換。熟悉RocketMQ的同學(xué)應(yīng)該知道裁替,目前開源版本的RocketMQ broker 是沒有主從自動(dòng)切換的项玛。如果你的master掛了,那你就寫不進(jìn)去了弱判。然后slave只能提供只讀的功能襟沮。
當(dāng)然如果你的topic在多個(gè)主節(jié)點(diǎn)上都創(chuàng)建了,雖然不會完全寫不進(jìn)去,但是對單分片順序消費(fèi)的場景开伏,還是會產(chǎn)生影響膀跌。
所以呢,我們就自己加了一套主從自動(dòng)切換的功能固灵。
第二個(gè)是批量生產(chǎn)的功能捅伤。RocketMQ 4.0之后的版本是支持批量生產(chǎn)功能的。但是限制了巫玻,只能是同一個(gè)ConsumerQueue的丛忆。這個(gè)對于我們的proxy服務(wù)來說,不太友好仍秤,因?yàn)槲覀兊膒roxy是有多個(gè)不同的topic的熄诡,所以我們就擴(kuò)展了一下,讓它能夠支持不同topic诗力、不同consume queue粮彤。原理上其實(shí)差不多,只是在傳輸?shù)臅r(shí)候姜骡,把topic和consumerqueue的信息都編碼進(jìn)去。
第三個(gè)屿良,目前RocketMQ 單機(jī)能夠支持的topic數(shù)量圈澈,基本在幾萬這么一個(gè)量級,在增加上去之后尘惧,元信息的管理就會非常耗時(shí)康栈,對整個(gè)吞吐的性能影響相對來說就會非常大。 然后我們有個(gè)場景又需要支持單機(jī)百萬左右的topic數(shù)量喷橙,所以我們就改造了一下元信息管理部分啥么,讓RocketMQ單機(jī)能夠支撐的topic數(shù)量達(dá)到了百萬。
后面一些就不太重要了贰逾,比如集成了我們公司內(nèi)部的一些監(jiān)控和部署工具悬荣,修了幾個(gè)bug,也給提了PR疙剑。最新版都已經(jīng)修掉了氯迂。
5. RocketMQ使用經(jīng)驗(yàn)
接下來,再簡單介紹一下言缤,我們在 RocketMQ在使用和運(yùn)維上的一些經(jīng)驗(yàn)嚼蚀。主要是涉及在磁盤IO性能不夠的時(shí)候,一些參數(shù)的調(diào)整管挟。
5.1 讀老數(shù)據(jù)的問題
我們都知道轿曙,RocketMQ的數(shù)據(jù)是要落盤的,一般只有最新寫入的數(shù)據(jù)才會在PageCache中。比如下游消費(fèi)數(shù)據(jù)导帝,因?yàn)橐恍┰蛲A艘惶熘笫匚剑滞蝗黄饋硐M(fèi)數(shù)據(jù)。這個(gè)時(shí)候就需要讀磁盤上的數(shù)據(jù)舟扎。
然后RocketMQ的消息體是全部存儲在一個(gè)append only的 commitlog 中的分飞。如果這個(gè)集群中混雜了很多不同topic的數(shù)據(jù)的話,要讀的兩條消息就很有可能間隔很遠(yuǎn)睹限。最壞情況就是一次磁盤IO讀一條消息譬猫。這就基本等價(jià)于隨機(jī)讀取了。如果磁盤的IOPS(Input/Output Operations Per Second)扛不住羡疗,還會影響數(shù)據(jù)的寫入染服,這個(gè)問題就嚴(yán)重了。
值得慶幸的是叨恨,RocketMQ提供了自動(dòng)從Slave讀取老數(shù)據(jù)的功能柳刮。這個(gè)功能主要由slaveReadEnable這個(gè)參數(shù)控制。默認(rèn)是關(guān)的(slaveReadEnable = false by default)痒钝。推薦把它打開秉颗,主從都要開。
這個(gè)參數(shù)打開之后送矩,在客戶端消費(fèi)數(shù)據(jù)時(shí)蚕甥,會判斷,當(dāng)前讀取消息的物理偏移量跟最新的位置的差值栋荸,是不是超過了內(nèi)存容量的一個(gè)百分比(accessMessageInMemoryMaxRatio = 40 by default)菇怀。如果超過了,就會告訴客戶端去備機(jī)上消費(fèi)數(shù)據(jù)晌块。如果采用異步主從爱沟,也就是brokerRole 等于ASYNC_AMSTER的時(shí)候,你的備機(jī)IO打爆匆背,其實(shí)影響不太大呼伸。但是如果你采用同步主從,那還是有影響钝尸。所以這個(gè)時(shí)候蜂大,最好掛兩個(gè)備機(jī)。因?yàn)镽ocketMQ的主從同步復(fù)制蝶怔,只要一個(gè)備機(jī)響應(yīng)了確認(rèn)寫入就可以了奶浦,一臺IO打爆,問題不大踢星。
5.2 過期數(shù)據(jù)刪除
第二個(gè)是刪除過期數(shù)據(jù)的問題澳叉。
RocketMQ默認(rèn)數(shù)據(jù)保留72個(gè)小時(shí)(fileReservedTime=72)。
然后它默認(rèn)在凌晨4點(diǎn)開始刪過期數(shù)據(jù)(deleteWhen="04")。你可以設(shè)置多個(gè)值用分號隔開成洗。
因?yàn)閿?shù)據(jù)都是定時(shí)刪除的五督,所以在磁盤充足的情況,數(shù)據(jù)的最長保留會比你設(shè)置的還多一天瓶殃。
因?yàn)槟J(rèn)都是同一時(shí)間充包,刪除一整天的數(shù)據(jù),如果用了機(jī)械硬盤遥椿,一般磁盤容量會比較大基矮,需要?jiǎng)h除的數(shù)據(jù)會特別多,這個(gè)就會導(dǎo)致在刪除數(shù)據(jù)的時(shí)候冠场,磁盤IO被打滿家浇。這個(gè)時(shí)候又要影響寫入了。
為了解決這個(gè)問題碴裙,可以嘗試多個(gè)方法钢悲,一個(gè)是設(shè)置文件刪除的間隔,有兩個(gè)參數(shù)可以設(shè)置舔株,
- deleteCommitLogFilesInterval = 100(毫秒)莺琳。每刪除10個(gè)commitLog文件的時(shí)間間隔。
- deleteConsumeQueueFilesInterval=100(毫秒)载慈。每刪除一個(gè)ConsumeQueue文件的時(shí)間間隔芦昔。
另外一個(gè)就是增加刪除頻率,把00-23都寫到deleteWhen娃肿,就可以實(shí)現(xiàn)每個(gè)小時(shí)都刪數(shù)據(jù)。
5.3 索引
最后一個(gè)功能是索引的問題珠十。
默認(rèn)情況下料扰,所有的broker都會建立索引(messageIndexEnable=true)。這個(gè)索引功能可以支持按照消息的uniqId焙蹭,消息的key來查詢消息體晒杈。
索引文件實(shí)現(xiàn)的時(shí)候,本質(zhì)上也就是基于磁盤的個(gè)一個(gè)hashmap孔厉。
如果broker上消息數(shù)量比較多拯钻,查詢的頻率比較高,這也會造成一定的IO負(fù)載撰豺。
所以我們的推薦方案是在master上關(guān)掉了index功能粪般,只在slave上打開。然后所有的index查詢?nèi)吭趕lave上進(jìn)行污桦。
當(dāng)然這個(gè)需要簡單修改一下MQAdminImpl里的實(shí)現(xiàn)亩歹。因?yàn)槟J(rèn)情況下,它會向master發(fā)出請求。
2018年度最受歡迎開源軟件評選活動(dòng)開始啦小作,喜歡 RocketMQ的亭姥,必須投上一票。
https://www.oschina.net/project/top_cn_2018