(二)分布式事務?No, 最終一致性(2)

最終一致性解決方案

1. 兩階段提交

2.異步確保(沒有事務消息)

3.異步確保(事務消息)

4. 補償交易(Compensating? Transaction)

5.消息重試

6.冪等(接口支持重入)

A給B轉100元。

1. 兩階段提交

有協(xié)調(diào)者,協(xié)調(diào)操作流程。Pre commit資源,commit或rollback時提交或釋放資源。

調(diào)用A的commit接口超時了,繼續(xù)重試。要求下游接口冪等。下游故障,短時重試不能解決,定時處理中間狀態(tài):扔到重試MQ。重試策略,失敗返回

2.異步確保(沒有事務消息)

不只為一致性,考慮響應時間,下游穩(wěn)定性

關鍵要有消息表。一般有隊列(不丟消息,但不支持事務消息),基本思路

生產(chǎn)方消息表記錄消息發(fā)送狀態(tài),和數(shù)據(jù)一個事務提交(存儲耦合)。只是增加一個字段業(yè)務強耦合,處理不同交易數(shù)據(jù)可通用處理。

消費方需處理消息成功,給生產(chǎn)方confirm失敗放MQ。支持重試省事兒,不支持回隊尾或建隊列處理。如成功才繼續(xù),block(不會這么做)。Kafka lowlevel接口是支持自己設置offset的,可實現(xiàn)block。

生產(chǎn)方定時掃描本地消息表,沒處理完的消息由發(fā)送一遍。自動對賬補賬,這一步可省略。丟消息或者下游處理失敗場景少??礃I(yè)務上能不能容忍不一致到對賬補賬周期。

ps:不要MQ。腳本處理低頻場景,離線掃表讓人不爽。業(yè)務量初期也可以

一致性要求不高兜底方案(對賬補賬),不需要confirm扔給消息萬事大吉

3.異步確保(事務消息)

理想:消息扔到MQ,肯定被消費成功。不用擔心失敗丟失。

現(xiàn)實:處理失敗,繼續(xù)消費直到成功為止

大部分MQ都不支持事務消息比如kafka。RocketMQ號稱支持,事務消息關鍵封裝消息狀態(tài)和重發(fā)等。沒成熟事務消息MQ。網(wǎng)傳RMQ提供2PC提交接口。

1.生產(chǎn)方發(fā)送prepared消息給RMQ。失敗返回

2.執(zhí)行本地事務,成功發(fā)Confirm消息給RMQ。失敗,調(diào)用RMQ cancel接口。

3.步超時如何處理呢?第四步驟

4.生產(chǎn)方實現(xiàn)check接口告知RMQ自己本地事務是否執(zhí)行成功(第4步)。定時輪訓pre消息,調(diào)用check接口,決定是否可提交。

5.可能失敗。這時候需要RMQ支持消息重試。處理失敗的消息果斷時間再進行重試,直到成功為止(超過重試次數(shù)后會進死信隊列,可能得人肉處理了,因為沒用過所以細節(jié)不是很了解)。

支持消息重試

P.S. 阿里內(nèi)部因歷史原因,用notify比RMQ要多,原理類似。

4. 補償交易(Compensating? Transaction)

和操作本身一個事務里完成。跟2PC比,核心價值少鎖代價。

如A:-100? B:+100。如B:+100失敗,補償A:+100。看起來跟注冊個單庫事務一樣簡單。做到業(yè)務無感知。

5.消息重試

事務消息解決生產(chǎn)者和MQ之間一致性,重試確保消費者MQ之間的一致性

pullpush模式。失敗,放重試隊列。延遲時間固定(2s),隊首消息時間到達才被消費。

時間為水位,期望執(zhí)行時間大于當前時間的消息高于水位。其他消息consumer不可見。如消息延遲時間不一樣:

(1)基于隊列方案:按秒建多個隊列。按執(zhí)行時間不同隊列,一天86400個隊列(一般丑陋)。按時間消費不同隊列。

(2)基于DB:不依賴隊列,支付時消息進去時候,設置下次執(zhí)行時間,時間做索引

(3)redis的延時隊列,支持重試。zset處理時間排序。遇到的持久化問題,內(nèi)存數(shù)據(jù)丟失問題,重試次數(shù)控制,消息追溯等

總結:MQ提供消息重試最好

6.冪等(接口支持重入)

沒有MQ,重試也是無處不在的。冪等怎么做?

insert,依賴唯一鍵,異?;貪L事務

update,那么狀態(tài)機控制和版本控制異常重要。這里要多加小心。

引入log表。該log對操作id(消息id?)插入log失敗整個回滾

不能查log表或者用redis,加鎖。除非在事務里查。唯一鍵沖突回滾掉就好

用唯一鍵擋重入是目前為止個人覺得最有安全感的方式。當然對數(shù)據(jù)庫會有一些額外性能損耗。問題就變成了有多大的并發(fā),其中又有多大是需要重試的?

Fasion IO卡+分庫分表之后,不會到db性能瓶頸(對金融類場景)。

后記

最終一致性問題,萬惡之源是RPC本身會失敗。生涯大部分時間都會跟各種失敗和timeout搏斗了。用MQ實現(xiàn)最終一致性原因:

1. MQ強大,可不丟數(shù)據(jù)。對事務消息更普及。

2. 異步處理能力(響應時間、吞吐量)和穩(wěn)定性(99.99%的服務依賴99.9%的服務)服務之間解耦

https://zhuanlan.zhihu.com/p/25933039

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容