如何保证消息不被重复消费啊(如何保证消息消费时的幂等性)?
1、面試題
如何保證消息不被重復(fù)消費(fèi)啊(如何保證消息消費(fèi)時(shí)的冪等性)?
2、面試官心里分析
其實(shí)這個(gè)很常見的一個(gè)問題,這倆問題基本可以連起來問。既然是消費(fèi)消息,那肯定要考慮考慮會(huì)不會(huì)重復(fù)消費(fèi)?能不能避免重復(fù)消費(fèi)?或者重復(fù)消費(fèi)了也別造成系統(tǒng)異常可以嗎?這個(gè)是MQ領(lǐng)域的基本問題,其實(shí)本質(zhì)上還是問你使用消息隊(duì)列如何保證冪等性,這個(gè)是你架構(gòu)里要考慮的一個(gè)問題。
面試官問你,肯定是必問的,這是你要考慮的實(shí)際生產(chǎn)上的系統(tǒng)設(shè)計(jì)問題。
3、面試題剖析
回答這個(gè)問題,首先你別聽到重復(fù)消息這個(gè)事兒,就一無所知吧,你先大概說一說可能會(huì)有哪些重復(fù)消費(fèi)的問題。
首先就是比如rabbitmq、rocketmq、kafka,都有可能會(huì)出現(xiàn)消費(fèi)重復(fù)消費(fèi)的問題,正常。因?yàn)檫@問題通常不是mq自己保證的,是給你保證的。然后我們挑一個(gè)kafka來舉個(gè)例子,說說怎么重復(fù)消費(fèi)吧。
?
Kafka實(shí)際上有個(gè)offset的概念,就是每個(gè)消息寫進(jìn)去,都有一個(gè)offset,代表它的序號(hào),然后consumer消費(fèi)了數(shù)據(jù)之后,每隔一段時(shí)間,會(huì)把自己消費(fèi)過的消息的offset提交一下,代表我已經(jīng)消費(fèi)過了,下次我要是重啟啥的,你就讓我繼續(xù)從上次消費(fèi)到的offset來繼續(xù)消費(fèi)吧。
但是凡事總有意外,比如我們之前生產(chǎn)經(jīng)常遇到的,就是你有時(shí)候重啟系統(tǒng),看你怎么重啟了,如果碰到點(diǎn)著急的,直接kill進(jìn)程了,再重啟。這會(huì)導(dǎo)致consumer有些消息處理了,但是沒來得及提交offset,尷尬了。重啟之后,少數(shù)消息會(huì)再次消費(fèi)一次。
其實(shí)重復(fù)消費(fèi)不可怕,可怕的是你沒考慮到重復(fù)消費(fèi)之后,怎么保證冪等性。
給你舉個(gè)例子吧。假設(shè)你有個(gè)系統(tǒng),消費(fèi)一條往數(shù)據(jù)庫里插入一條,要是你一個(gè)消息重復(fù)兩次,你不就插入了兩條,這數(shù)據(jù)不就錯(cuò)了?但是你要是消費(fèi)到第二次的時(shí)候,自己判斷一下已經(jīng)消費(fèi)過了,直接扔了,不就保留了一條數(shù)據(jù)?
一條數(shù)據(jù)重復(fù)出現(xiàn)兩次,數(shù)據(jù)庫里就只有一條數(shù)據(jù),這就保證了系統(tǒng)的冪等性
冪等性,我通俗點(diǎn)說,就一個(gè)數(shù)據(jù),或者一個(gè)請(qǐng)求,給你重復(fù)來多次,你得確保對(duì)應(yīng)的數(shù)據(jù)是不會(huì)改變的,不能出錯(cuò)。
那所以第二個(gè)問題來了,怎么保證消息隊(duì)列消費(fèi)的冪等性?
?
其實(shí)還是得結(jié)合業(yè)務(wù)來思考,我這里給幾個(gè)思路:還有比如基于數(shù)據(jù)庫的唯一鍵來保證重復(fù)數(shù)據(jù)不會(huì)重復(fù)插入多條,我們之前線上系統(tǒng)就有這個(gè)問題,就是拿到數(shù)據(jù)的時(shí)候,每次重啟可能會(huì)有重復(fù),因?yàn)閗afka消費(fèi)者還沒來得及提交offset,重復(fù)數(shù)據(jù)拿到了以后我們插入的時(shí)候,因?yàn)橛形ㄒ绘I約束了,所以重復(fù)數(shù)據(jù)只會(huì)插入報(bào)錯(cuò),不會(huì)導(dǎo)致數(shù)據(jù)庫中出現(xiàn)臟數(shù)據(jù)。
如何保證MQ的消費(fèi)是冪等性的,需要結(jié)合具體的業(yè)務(wù)來看。
轉(zhuǎn)載于:https://www.cnblogs.com/tuhooo/p/10564558.html
總結(jié)
以上是生活随笔為你收集整理的如何保证消息不被重复消费啊(如何保证消息消费时的幂等性)?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据流中的中位数
- 下一篇: 从零构建vue+webpack (一)