三张表有重复字段_什么?搞不定Kafka重复消费?
生活随笔
收集整理的這篇文章主要介紹了
三张表有重复字段_什么?搞不定Kafka重复消费?
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
點(diǎn)戳藍(lán)字“架構(gòu)之美”關(guān)注我們哦!
? 前言?
今天我們聊一個(gè)話題,這個(gè)話題大家可能在面試過(guò)程中,或者是工作當(dāng)中經(jīng)常遇到 ?如何保證 Kafka 消息不重復(fù)消費(fèi)?我們?cè)谧鲩_(kāi)發(fā)的時(shí)候?yàn)榱顺绦虻慕研?#xff0c;在使用 Kafka 的時(shí)候一般都會(huì)設(shè)置重試的次數(shù),但是因?yàn)榫W(wǎng)絡(luò)的一些原因,設(shè)置了重試就有可能導(dǎo)致有些消息重復(fù)發(fā)送了(當(dāng)然導(dǎo)致消息重復(fù)也有可能是其他原因),那么怎么解決消息重復(fù)這個(gè)問(wèn)題呢?關(guān)于這個(gè)問(wèn)題,我這兒提供了如下三種解決方案,供大家參考。?解決方案
方案一? /? 保存并查詢(xún)給每個(gè)消息都設(shè)置一個(gè)獨(dú)一無(wú)二的 key,消費(fèi)的時(shí)候把 key 記錄下來(lái),然后每次消費(fèi)新的消息的時(shí)候都查詢(xún)一下,看當(dāng)前消息的這個(gè) key 是否消費(fèi)過(guò),如果沒(méi)有消費(fèi)過(guò)才進(jìn)行消費(fèi)。(這種方式好想,但是其實(shí)實(shí)現(xiàn)起來(lái)一點(diǎn)也不簡(jiǎn)單)方案二?/??利用冪等冪等(Idempotence)在數(shù)學(xué)上是這樣定義的,如果一個(gè)函數(shù) f(x) 滿(mǎn)足:f(f(x)) = f(x),則函數(shù) f(x) 滿(mǎn)足冪等性。這個(gè)概念被拓展到計(jì)算機(jī)領(lǐng)域,被用來(lái)描述一個(gè)操作、方法或者服務(wù)。一個(gè)冪等操作的特點(diǎn)是,其任意多次執(zhí)行所產(chǎn)生的影響均與一次執(zhí)行的影響相同。一個(gè)冪等的方法,使用同樣的參數(shù),對(duì)它進(jìn)行多次調(diào)用和一次調(diào)用,對(duì)系統(tǒng)產(chǎn)生的影響是一樣的。所以,對(duì)于冪等的方法,不用擔(dān)心重復(fù)執(zhí)行會(huì)對(duì)系統(tǒng)造成任何改變。我們舉個(gè)例子?來(lái)說(shuō)明一下。在不考慮并發(fā)的情況下,“將 X 老師的賬戶(hù)余額設(shè)置為 100 萬(wàn)元”,執(zhí)行一次后對(duì)系統(tǒng)的影響是,X 老師的賬戶(hù)余額變成了 100 萬(wàn)元。只要提供的參數(shù) 100萬(wàn)元不變,那即使再執(zhí)行多少次,X 老師的賬戶(hù)余額始終都是 100萬(wàn)元,不會(huì)變化,這個(gè)操作就是一個(gè)冪等的操作。再舉一個(gè)例子?,“將 X 老師的余額加 100 萬(wàn)元”,這個(gè)操作它就不是冪等的,每執(zhí)行一次,賬戶(hù)余額就會(huì)增加 100 萬(wàn)元,執(zhí)行多次和執(zhí)行一次對(duì)系統(tǒng)的影響(也就是賬戶(hù)的余額)是不一樣的。所以,通過(guò)這兩個(gè)例子,我們可以想到如果系統(tǒng)消費(fèi)消息的業(yè)務(wù)邏輯具備冪等性,那就不用擔(dān)心消息重復(fù)的問(wèn)題了,因?yàn)橥粭l消息,消費(fèi)一次和消費(fèi)多次對(duì)系統(tǒng)的影響是完全一樣的。也就可以認(rèn)為,消費(fèi)多次等于消費(fèi)一次。那么,如何實(shí)現(xiàn)冪等操作呢?最好的方式就是,從業(yè)務(wù)邏輯設(shè)計(jì)上入手,將消費(fèi)的業(yè)務(wù)邏輯設(shè)計(jì)成具備冪等性的操作。但是,不是所有的業(yè)務(wù)都能設(shè)計(jì)成天然冪等的,這里就需要一些方法和技巧來(lái)實(shí)現(xiàn)冪等。下面我們介紹一種常用的方法:利用數(shù)據(jù)庫(kù)的唯一約束實(shí)現(xiàn)冪等。例如,我們剛剛提到的那個(gè)不具備冪等特性的轉(zhuǎn)賬的例子:將 X 老師的賬戶(hù)余額加 100 萬(wàn)元。在這個(gè)例子中,我們可以通過(guò)改造業(yè)務(wù)邏輯,讓它具備冪等性。首先,我們可以限定,對(duì)于每個(gè)轉(zhuǎn)賬單每個(gè)賬戶(hù)只可以執(zhí)行一次變更操作,在分布式系統(tǒng)中,這個(gè)限制實(shí)現(xiàn)的方法非常多,最簡(jiǎn)單的是我們?cè)跀?shù)據(jù)庫(kù)中建一張轉(zhuǎn)賬流水表,這個(gè)表有三個(gè)字段:轉(zhuǎn)賬單 ID、賬戶(hù) ID 和變更金額,然后給轉(zhuǎn)賬單 ID 和賬戶(hù) ID 這兩個(gè)字段聯(lián)合起來(lái)創(chuàng)建一個(gè)唯一約束,這樣對(duì)于相同的轉(zhuǎn)賬單 ID 和賬戶(hù) ID,表里至多只能存在一條記錄。這樣,我們消費(fèi)消息的邏輯可以變?yōu)?#xff1a;“在轉(zhuǎn)賬流水表中增加一條轉(zhuǎn)賬記錄,然后再根據(jù)轉(zhuǎn)賬記錄,異步操作更新用戶(hù)余額即可。”在轉(zhuǎn)賬流水表增加一條轉(zhuǎn)賬記錄這個(gè)操作中,由于我們?cè)谶@個(gè)表中預(yù)先定義了“賬戶(hù) ID 轉(zhuǎn)賬單 ID”的唯一約束,對(duì)于同一個(gè)轉(zhuǎn)賬單同一個(gè)賬戶(hù)只能插入一條記錄,后續(xù)重復(fù)的插入操作都會(huì)失敗,這樣就實(shí)現(xiàn)了一個(gè)冪等的操作。方案三 /??設(shè)置前置條件為更新的數(shù)據(jù)設(shè)置前置條件另外一種實(shí)現(xiàn)冪等的思路是,給數(shù)據(jù)變更設(shè)置一個(gè)前置條件,如果滿(mǎn)足條件就更新數(shù)據(jù),否則拒絕更新數(shù)據(jù),在更新數(shù)據(jù)的時(shí)候,同時(shí)變更前置條件中需要判斷的數(shù)據(jù)。
這樣,重復(fù)執(zhí)行這個(gè)操作時(shí),由于第一次更新數(shù)據(jù)的時(shí)候已經(jīng)變更了前置條件中需要判斷的數(shù)據(jù),不滿(mǎn)足前置條件,則不會(huì)重復(fù)執(zhí)行更新數(shù)據(jù)操作。
比如,剛剛我們說(shuō)過(guò),“將 X 老師的賬戶(hù)的余額增加 100 萬(wàn)元”這個(gè)操作并不滿(mǎn)足冪等性,我們可以把這個(gè)操作加上一個(gè)前置條件,變?yōu)?#xff1a;“如果X老師的賬戶(hù)當(dāng)前的余額為 500萬(wàn)元,將余額加 100萬(wàn)元”,這個(gè)操作就具備了冪等性。
對(duì)應(yīng)到消息隊(duì)列中的使用時(shí),可以在發(fā)消息時(shí)在消息體中帶上當(dāng)前的余額,在消費(fèi)的時(shí)候進(jìn)行判斷數(shù)據(jù)庫(kù)中,當(dāng)前余額是否與消息中的余額相等,只有相等才執(zhí)行變更操作。
但是,如果我們要更新的數(shù)據(jù)不是數(shù)值,或者我們要做一個(gè)比較復(fù)雜的更新操作怎么辦?用什么作為前置判斷條件呢?更加通用的方法是,給你的數(shù)據(jù)增加一個(gè)版本號(hào)屬性,每次更數(shù)據(jù)前,比較當(dāng)前數(shù)據(jù)的版本號(hào)是否和消息中的版本號(hào)一致,如果不一致就拒絕更新數(shù)據(jù),更新數(shù)據(jù)的同時(shí)將版本號(hào) +1,一樣可以實(shí)現(xiàn)冪等。
?最后
今天給大家提供的消息重復(fù)的解決方案,也參考了《消息隊(duì)列高手課》里的思路,大家如果有什么好的解決方案,歡迎討論!!大家加油!!·end·
奈學(xué)教育科技技術(shù)人成長(zhǎng)之路的指路人
點(diǎn)贊支持技術(shù)創(chuàng)業(yè)?
總結(jié)
以上是生活随笔為你收集整理的三张表有重复字段_什么?搞不定Kafka重复消费?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 中国博物馆里的枪械为什么要把枪管堵死?
- 下一篇: 王牌部队里面有李沁吗