偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

一次教會(huì)你如何解決RabbitMQ消息丟失問(wèn)題

開(kāi)發(fā) 架構(gòu)
這篇文章,我們轉(zhuǎn)移到消息中間件的生產(chǎn)端,一起來(lái)看看如何保證投遞到MQ的數(shù)據(jù)不丟失。

一、前情提示

上篇文章:《?一篇全面而且透徹的RabbitMQ性能優(yōu)化指南?!》,我們分析了RabbitMQ開(kāi)啟手動(dòng)ack機(jī)制保證消費(fèi)端數(shù)據(jù)不丟失的時(shí)候,prefetch機(jī)制對(duì)消費(fèi)者的吞吐量以及內(nèi)存消耗的影響。

通過(guò)分析,我們知道了prefetch過(guò)大容易導(dǎo)致內(nèi)存溢出,prefetch過(guò)小又會(huì)導(dǎo)致消費(fèi)吞吐量過(guò)低,所以在實(shí)際項(xiàng)目中需要慎重測(cè)試和設(shè)置。

這篇文章,我們轉(zhuǎn)移到消息中間件的生產(chǎn)端,一起來(lái)看看如何保證投遞到MQ的數(shù)據(jù)不丟失。

如果投遞出去的消息在網(wǎng)絡(luò)傳輸過(guò)程中丟失,或者在RabbitMQ的內(nèi)存中還沒(méi)寫入磁盤的時(shí)候宕機(jī),都會(huì)導(dǎo)致生產(chǎn)端投遞到MQ的數(shù)據(jù)丟失。

而且丟失之后,生產(chǎn)端自己還感知不到,同時(shí)還沒(méi)辦法來(lái)補(bǔ)救。

下面的圖就展示了這個(gè)問(wèn)題。

所以本文呢,我們就來(lái)逐步分析一下。

二、保證投遞消息不丟失的confirm機(jī)制

其實(shí)要解決這個(gè)問(wèn)題,相信大家看過(guò)之前的消費(fèi)端ack機(jī)制之后,也都猜到了。

很簡(jiǎn)單,就是生產(chǎn)端(比如上圖的訂單服務(wù))首先需要開(kāi)啟一個(gè)confirm模式,接著投遞到MQ的消息,如果MQ一旦將消息持久化到磁盤之后,必須也要回傳一個(gè)confirm消息給生產(chǎn)端。

這樣的話,如果生產(chǎn)端的服務(wù)接收到了這個(gè)confirm消息,就知道是已經(jīng)持久化到磁盤了。

否則如果沒(méi)有接收到confirm消息,那么就說(shuō)明這條消息半路可能丟失了,此時(shí)你就可以重新投遞消息到MQ去,確保消息不要丟失。

而且一旦你開(kāi)啟了confirm模式之后,每次消息投遞也同樣是有一個(gè)delivery tag的,也是起到唯一標(biāo)識(shí)一次消息投遞的作用。

這樣,MQ回傳ack給生產(chǎn)端的時(shí)候,會(huì)帶上這個(gè)delivery tag。你就知道具體對(duì)應(yīng)著哪一次消息投遞了,可以刪除這條消息。

此外,如果RabbitMQ接收到一條消息之后,結(jié)果內(nèi)部出錯(cuò)發(fā)現(xiàn)無(wú)法處理這條消息,那么他會(huì)回傳一個(gè)nack消息給生產(chǎn)端。此時(shí)你就會(huì)感知到這條消息可能處理有問(wèn)題,你可以選擇重新再次投遞這條消息到MQ去。

或者另一種情況,如果某條消息很長(zhǎng)時(shí)間都沒(méi)給你回傳ack/nack,那可能是極端意外情況發(fā)生了,數(shù)據(jù)也丟了,你也可以自己重新投遞消息到MQ去。

通過(guò)這套confirm機(jī)制,就可以實(shí)現(xiàn)生產(chǎn)端投遞消息不會(huì)丟失的效果。大家來(lái)看看下面的圖,一起來(lái)感受一下。

三、confirm機(jī)制的代碼實(shí)現(xiàn)

下面,我們?cè)賮?lái)看看confirm機(jī)制的代碼實(shí)現(xiàn):

四、confirm機(jī)制投遞消息的高延遲性

這里有一個(gè)很關(guān)鍵的點(diǎn),就是一旦啟用了confirm機(jī)制投遞消息到MQ之后,MQ是不保證什么時(shí)候會(huì)給你一個(gè)ack或者nack的。

因?yàn)镽abbitMQ自己內(nèi)部將消息持久化到磁盤,本身就是通過(guò)異步批量的方式來(lái)進(jìn)行的。

正常情況下,你投遞到RabbitMQ的消息都會(huì)先駐留在內(nèi)存里,然后過(guò)了幾百毫秒的延遲時(shí)間之后,再一次性批量把多條消息持久化到磁盤里去。

這樣做,是為了兼顧高并發(fā)寫入的吞吐量和性能的,因?yàn)橐悄銇?lái)一條消息就寫一次磁盤,那么性能會(huì)很差,每次寫磁盤都是一次fsync強(qiáng)制刷入磁盤的操作,是很耗時(shí)的。

所以正是因?yàn)檫@個(gè)原因,你打開(kāi)了confirm模式之后,很可能你投遞出去一條消息,要間隔幾百毫秒之后,MQ才會(huì)把消息寫入磁盤,接著你才會(huì)收到MQ回傳過(guò)來(lái)的ack消息,這個(gè)就是所謂confirm機(jī)制投遞消息的高延遲性。

大家看看下面的圖,一起來(lái)感受一下。

五、高并發(fā)下如何投遞消息才能不丟失

大家可以考慮一下,在生產(chǎn)端高并發(fā)寫入MQ的場(chǎng)景下,你會(huì)面臨兩個(gè)問(wèn)題:

1、你每次寫一條消息到MQ,為了等待這條消息的ack,必須把消息保存到一個(gè)存儲(chǔ)里。

并且這個(gè)存儲(chǔ)不建議是內(nèi)存,因?yàn)楦卟l(fā)下消息是很多的,每秒可能都幾千甚至上萬(wàn)的消息投遞出去,消息的ack要等幾百毫秒的話,放內(nèi)存可能有內(nèi)存溢出的風(fēng)險(xiǎn)。

2、絕對(duì)不能以同步寫消息 + 等待ack的方式來(lái)投遞,那樣會(huì)導(dǎo)致每次投遞一個(gè)消息都同步阻塞等待幾百毫秒,會(huì)導(dǎo)致投遞性能和吞吐量大幅度下降。

針對(duì)這兩個(gè)問(wèn)題,相對(duì)應(yīng)的方案其實(shí)也呼之欲出了。

首先,用來(lái)臨時(shí)存放未ack消息的存儲(chǔ)需要承載高并發(fā)寫入,而且我們不需要什么復(fù)雜的運(yùn)算操作,這種存儲(chǔ)首選絕對(duì)不是MySQL之類的數(shù)據(jù)庫(kù),而建議采用kv存儲(chǔ)。kv存儲(chǔ)承載高并發(fā)能力極強(qiáng),而且kv操作性能很高。

其次,投遞消息之后等待ack的過(guò)程必須是異步的,也就是類似上面那樣的代碼,已經(jīng)給出了一個(gè)初步的異步回調(diào)的方式。

消息投遞出去之后,這個(gè)投遞的線程其實(shí)就可以返回了,至于每個(gè)消息的異步回調(diào),是通過(guò)在channel注冊(cè)一個(gè)confirm監(jiān)聽(tīng)器實(shí)現(xiàn)的。

收到一個(gè)消息ack之后,就從kv存儲(chǔ)中刪除這條臨時(shí)消息;收到一個(gè)消息nack之后,就從kv存儲(chǔ)提取這條消息然后重新投遞一次即可;也可以自己對(duì)kv存儲(chǔ)里的消息做監(jiān)控,如果超過(guò)一定時(shí)長(zhǎng)沒(méi)收到ack,就主動(dòng)重發(fā)消息。

大家看看下面的圖,一起來(lái)體會(huì)一下:

六、消息中間件全鏈路100%數(shù)據(jù)不丟失能做到嗎?

到此為止,我們已經(jīng)把生產(chǎn)端和消費(fèi)端如何保證消息不丟失的相關(guān)技術(shù)方案結(jié)合RabbitMQ這種中間件都給大家分析過(guò)了。

其實(shí),架構(gòu)思想是通用的, 無(wú)論你用的是哪一種MQ中間件,他們提供的功能是不太一樣的,但是你都需要考慮如下幾點(diǎn):

?1.生產(chǎn)端如何保證投遞出去的消息不丟失:消息在半路丟失,或者在MQ內(nèi)存中宕機(jī)導(dǎo)致丟失,此時(shí)你如何基于MQ的功能保證消息不要丟失?

2.MQ自身如何保證消息不丟失:起碼需要讓MQ對(duì)消息是有持久化到磁盤這個(gè)機(jī)制。

3.消費(fèi)端如何保證消費(fèi)到的消息不丟失:如果你處理到一半消費(fèi)端宕機(jī),導(dǎo)致消息丟失,此時(shí)怎么辦??

目前來(lái)說(shuō),我們初步的借著RabbitMQ舉例,已經(jīng)把從前到后一整套技術(shù)方案的原理、設(shè)計(jì)和實(shí)現(xiàn)都給大家分析了一遍了。

但是此時(shí)真的能做到100%數(shù)據(jù)不丟失嗎?恐怕未必,大家再考慮一下個(gè)特殊的場(chǎng)景。

生產(chǎn)端投遞了消息到MQ,而且持久化到磁盤并且回傳ack給生產(chǎn)端了。

?但是此時(shí)MQ還沒(méi)投遞消息給消費(fèi)端,結(jié)果MQ部署的機(jī)器突然宕機(jī),而且因?yàn)槲粗脑虼疟P損壞了,直接在物理層面導(dǎo)致MQ持久化到磁盤的數(shù)據(jù)找不回來(lái)了。

這個(gè)大家千萬(wàn)別以為是開(kāi)玩笑的,大家如果留意留意行業(yè)新聞,這種磁盤損壞導(dǎo)致數(shù)據(jù)丟失的是真的有的。

那么此時(shí)即使你把MQ重啟了,磁盤上的數(shù)據(jù)也丟失了,數(shù)據(jù)是不是還是丟失了?

你說(shuō),我可以用MQ的集群機(jī)制啊,給一個(gè)數(shù)據(jù)做多個(gè)副本,比如后面我們就會(huì)給大家分析RabbitMQ的鏡像集群機(jī)制,確實(shí)可以做到數(shù)據(jù)多副本。

但是即使數(shù)據(jù)多副本,一定可以做到100%數(shù)據(jù)不丟失??

比如說(shuō)你的機(jī)房突然遇到地震,結(jié)果機(jī)房里的機(jī)器全部沒(méi)了,數(shù)據(jù)是不是還是全丟了?

說(shuō)這個(gè),并不是說(shuō)要抬杠。而是告訴大家,技術(shù)這個(gè)東西,100%都是理論上的期望。

應(yīng)該說(shuō),我們凡事都朝著100%去做,但是理論上是不可能完全做到100%保證的,可能就是做到99.9999%的可能性數(shù)據(jù)不丟失,但是還是有千萬(wàn)分之一的概率會(huì)丟失。

當(dāng)然,從實(shí)際的情況來(lái)說(shuō),能做到這種地步,其實(shí)基本上已經(jīng)基本數(shù)據(jù)不會(huì)丟失了。

責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2021-08-04 07:47:18

Kafka消息框架

2022-07-14 14:27:34

Javascript數(shù)字精度二進(jìn)制

2020-09-16 08:26:18

圖像定位尺寸

2021-07-07 10:28:09

分布式架構(gòu)系統(tǒng)

2024-04-23 08:46:45

消息積壓KafkaMQ

2012-09-05 11:09:15

SELinux操作系統(tǒng)

2022-01-07 11:48:59

RabbitMQGolang 項(xiàng)目

2024-03-18 09:10:00

死鎖日志binlog

2020-08-12 08:25:43

數(shù)據(jù)庫(kù)MySQL技術(shù)

2011-05-11 13:48:31

MySQLWeb

2010-04-29 17:46:31

Oracle死鎖

2021-12-12 18:12:13

Hbase線上問(wèn)題

2022-07-27 18:34:32

RabbitMQ宕機(jī)服務(wù)器

2011-08-29 10:34:00

網(wǎng)絡(luò)安全云安全云計(jì)算

2021-06-06 13:05:15

前端跨域CORS

2011-03-23 14:42:47

CPU過(guò)度消耗

2023-10-30 18:35:47

MySQL主從延時(shí)

2017-10-17 09:21:06

2010-07-16 13:52:26

telnet漏洞

2017-07-20 07:30:16

大數(shù)據(jù)數(shù)據(jù)互聯(lián)網(wǎng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)