用redis來(lái)實(shí)現(xiàn)具有ack機(jī)制的消息隊(duì)列

消息隊(duì)列(MQ)

相信大家對(duì)MQ這個(gè)詞都不會(huì)陌生,不管用過(guò)還是沒(méi)用過(guò)的,大多會(huì)對(duì)他有一定的了解,
那么消息隊(duì)列有什么好處呢

  1. 解耦(接觸服務(wù)之間的耦合度關(guān)系)
  2. 削峰(例如我某個(gè)促銷活動(dòng)在某個(gè)時(shí)間點(diǎn)有非常大的流量涌入,這個(gè)時(shí)候用Mq做緩存是最好的方式了)
  3. 異步化(例如有些服務(wù)是我不需要在同步鏈中進(jìn)行調(diào)用的,那么可以用mq來(lái)做一個(gè)異步消費(fèi))

傳統(tǒng)MQ的缺點(diǎn)

MQ基本上和緩存一樣是居家必備之良藥。然而消息隊(duì)列雖然重要,但是同時(shí)其實(shí)是蠻重的一個(gè)組件浙垫。例如我們?cè)谟胷abbitMq的話斩箫,我們需要為它搭建一個(gè)服務(wù)端退腥,如果考慮到可用性,那么我們需要為服務(wù)端建立一個(gè)集群惕稻,同時(shí)蔗衡,我們?nèi)绻€上問(wèn)題可能還需要在Mq中做查找纤虽,那么這些工作就可能加大我們整體的工作量。

利用redis來(lái)實(shí)現(xiàn)MQ

所以就想能不能先簡(jiǎn)單的通過(guò)Redis來(lái)實(shí)現(xiàn)消息隊(duì)列呢绞惦?不考慮PubSub逼纸、分布式、持久化济蝉、事務(wù)等復(fù)雜的情況杰刽。就像JDK的各種Queue一樣。答案當(dāng)然是可以的王滤,因?yàn)镽edis提供的list數(shù)據(jù)結(jié)構(gòu)就非常適合做消息隊(duì)列贺嫂。大家可能會(huì)發(fā)現(xiàn),網(wǎng)上有很多redis的消息隊(duì)列雁乡,但是目前為止第喳,我沒(méi)有發(fā)現(xiàn)一個(gè)消息隊(duì)列是具有ack機(jī)制的。

這里我們會(huì)講述怎么利用list的api中的lpush/brpoplpush來(lái)實(shí)現(xiàn)一個(gè)具有ack機(jī)制的消息隊(duì)列

實(shí)現(xiàn)思路

初步實(shí)現(xiàn)

實(shí)現(xiàn)ack的話蔗怠,(暫時(shí)先不考慮集群版墩弯,只是單機(jī)版本)

  1. 我可以用lpush做生產(chǎn)者,每次有消息需要生產(chǎn)的時(shí)候寞射,就發(fā)送一個(gè)message到pending隊(duì)列中。
  2. brpoplpush做消費(fèi)者锌钮,每次取到消息的時(shí)候進(jìn)行業(yè)務(wù)消費(fèi)桥温。在消費(fèi)的同時(shí)吧消息放到另一個(gè)doing的隊(duì)列中
  3. 每次消費(fèi)者完成任務(wù),從doing隊(duì)列中刪除任務(wù)msg梁丘,用來(lái)告知這個(gè)消息被成功消費(fèi)掉了
  4. 然后開一個(gè)線程去定時(shí)輪詢查doing中侵浸,如果一定時(shí)間(架設(shè)我們的message實(shí)現(xiàn)了我們的協(xié)議旺韭,message中帶有任務(wù)開始的時(shí)間戳),這個(gè)任務(wù)還沒(méi)被消費(fèi)成功掏觉,那么就把這個(gè)doing隊(duì)列的那個(gè)就重新塞到pending的隊(duì)列里

發(fā)現(xiàn)問(wèn)題

但是這時(shí)候可能會(huì)出現(xiàn)這樣的問(wèn)題区端,我輪詢doing的隊(duì)列在取任務(wù)的時(shí)候可能因?yàn)槲蚁M(fèi)者的任務(wù)因?yàn)槟承┰蜃龅穆诵敲催@時(shí)候就會(huì)被重新塞會(huì)pending隊(duì)列里澳腹,但是過(guò)兩秒我的doing確實(shí)消費(fèi)完了织盼。

那么怎么解決這個(gè)問(wèn)題呢?

解決方式其實(shí)很簡(jiǎn)單,就是上面的進(jìn)行步驟3的時(shí)候,如果從doing隊(duì)列進(jìn)行刪除的時(shí)候酱塔,如果返回值表示刪除失敗的話,那么說(shuō)明我們的任務(wù)被系統(tǒng)認(rèn)為過(guò)期了沥邻,他被賽入pending中了,那么我們只需要在這個(gè)時(shí)候去pending中重新刪除這個(gè)message消息即可

延伸問(wèn)題

ok羊娃,那么大家覺得這時(shí)候已經(jīng)完工了嗎唐全?其實(shí)并沒(méi)有。蕊玷。邮利。為什么呢?
因?yàn)闀?huì)出現(xiàn)如下這樣一種比較極端的情況:

就是任務(wù)完成之后去doing隊(duì)列中刪除message失敗,然后去pending中刪除也失敗,因?yàn)橛锌赡茉谌蝿?wù)掃描的時(shí)候,吧任務(wù)剛放入pending隊(duì)列中垃帅,沒(méi)等doing完成呢延届,pending中重新放入的任務(wù)就被消費(fèi)了。那么這時(shí)候依然是消息出現(xiàn)重復(fù)

這種情況下的最佳解決方案是什么呢挺智?就是消費(fèi)端做好冪等性處理(其實(shí)像阿里的RocketMq)也會(huì)出現(xiàn)消息重復(fù)的情況(雖然極低概率),但是在Mq中祷愉,似乎設(shè)計(jì)一個(gè)精確只發(fā)一次的模型,是一件比較難的事情赦颇。

深層延伸的方案

上面的消息重復(fù)其實(shí)還是有優(yōu)化的余地,具體的實(shí)現(xiàn)思路如下:

  1. 優(yōu)化掃描的模型,吧掃描doing過(guò)期任務(wù)變成一個(gè)延遲掃描(如用delayedQueue實(shí)現(xiàn)延遲任務(wù)掃描)
  2. 吧每個(gè)執(zhí)行的任務(wù)模型用ExecutorService來(lái)管理二鳄,存儲(chǔ)正在執(zhí)行的Future
  3. 每次掃描到超時(shí)的任務(wù)就去內(nèi)存中查找這個(gè)任務(wù)的Future是否存在,如果存在則不需要吧doing的message放到pending中
  4. 如果需要超時(shí)機(jī)制的話,找到對(duì)應(yīng)的Future并且取消當(dāng)前任務(wù)的執(zhí)行媒怯,并把之前執(zhí)行的操作進(jìn)行業(yè)務(wù)回滾/rollback订讼,把message放到pending中

不過(guò)我并不推薦這一套方案,因?yàn)檫@一套方案過(guò)于復(fù)雜扇苞,本身就是不是我們用redis作為消息隊(duì)列的初衷欺殿。

總結(jié)

redis作為消息隊(duì)列是有很大的局限性的,本身作為一個(gè)以緩存/內(nèi)存存儲(chǔ)為主的東西,只是因?yàn)槟承゛pi上的特性鳖敷,我們得以實(shí)現(xiàn)一個(gè)簡(jiǎn)單的隊(duì)列服務(wù)脖苏,本身我們要選擇好業(yè)務(wù)的取舍,靈活的使用redis的MQ支持定踱,才能實(shí)現(xiàn)一個(gè)好的服務(wù)棍潘。

基于上述思想的代碼實(shí)踐我已經(jīng)放到了github上,部分代碼還在做成中。
github地址 : https://github.com/wgd12389/redisses/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市亦歉,隨后出現(xiàn)的幾起案子恤浪,更是在濱河造成了極大的恐慌,老刑警劉巖肴楷,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件水由,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡赛蔫,警方通過(guò)查閱死者的電腦和手機(jī)砂客,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)濒募,“玉大人鞭盟,你說(shuō)我怎么就攤上這事」逄辏” “怎么了齿诉?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)晌姚。 經(jīng)常有香客問(wèn)我粤剧,道長(zhǎng),這世上最難降的妖魔是什么挥唠? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任抵恋,我火速辦了婚禮,結(jié)果婚禮上宝磨,老公的妹妹穿的比我還像新娘弧关。我一直安慰自己,他們只是感情好唤锉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布世囊。 她就那樣靜靜地躺著,像睡著了一般窿祥。 火紅的嫁衣襯著肌膚如雪株憾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天晒衩,我揣著相機(jī)與錄音嗤瞎,去河邊找鬼。 笑死听系,一個(gè)胖子當(dāng)著我的面吹牛贝奇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播靠胜,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼弃秆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼届惋!你這毒婦竟也來(lái)了髓帽?” 一聲冷哼從身側(cè)響起菠赚,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎郑藏,沒(méi)想到半個(gè)月后衡查,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡必盖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年拌牲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片歌粥。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡塌忽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出失驶,到底是詐尸還是另有隱情土居,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布嬉探,位于F島的核電站擦耀,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏涩堤。R本人自食惡果不足惜眷蜓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望胎围。 院中可真熱鬧吁系,春花似錦、人聲如沸白魂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)碧聪。三九已至冒版,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間逞姿,已是汗流浹背辞嗡。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留滞造,地道東北人续室。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像谒养,于是被迫代替她去往敵國(guó)和親挺狰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子明郭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)丰泊,斷路器薯定,智...
    卡卡羅2017閱讀 134,652評(píng)論 18 139
  • 消息隊(duì)列已經(jīng)逐漸成為企業(yè)IT系統(tǒng)內(nèi)部通信的核心手段。它具有低耦合瞳购、可靠投遞话侄、廣播、流量控制学赛、最終一致性等一系列功能...
    Sophie12138閱讀 722評(píng)論 0 7
  • “ 消息隊(duì)列已經(jīng)逐漸成為企業(yè)IT系統(tǒng)內(nèi)部通信的核心手段年堆。它具有低耦合、可靠投遞盏浇、廣播变丧、流量控制、最終一致性等一系列...
    落羽成霜丶閱讀 3,984評(píng)論 1 41
  • 女兒明天高考绢掰。 為騙自己痒蓬,連續(xù)幾天裝模作樣的去接下夜自習(xí)的女兒。之所以這么說(shuō)是因?yàn)槎淅锶艘粚?duì)耳機(jī)曼月,街邊少男倩女...
    方樹閱讀 299評(píng)論 0 0
  • 周末終于和心心念念的小伙伴處了一天谊却。得知她要去我家,當(dāng)時(shí)的心情簡(jiǎn)直像充滿了氣了的氣球哑芹,飄飄然炎辨。一瞬間就在家里...
    南蒲草閱讀 299評(píng)論 0 0