微服務(wù)架構(gòu)實戰(zhàn)筆記--分布式鎖問題

業(yè)務(wù)層面冪等

冗余部署多個進程
存在并發(fā)消費的可能性
并發(fā)轉(zhuǎn)變成串行消費

發(fā)送端會發(fā)送很多次扁位,消費端可能會消費很多次,需要做去重,對共享資源做去重,其實也是一個分布式鎖的問題

本質(zhì)
分布式鎖問題

分布式鎖設(shè)計與實踐

分布式鎖的定義
分布式環(huán)境下齿桃,鎖定全局唯一資源
請求處理串行化
實際表現(xiàn)互斥鎖

分布式鎖的目的

交易訂單鎖定
防止重復下單
解決業(yè)務(wù)層冪等問題

MQ消息消費冪等性
發(fā)送消息重復
消息消費端去重
比如手機提現(xiàn)

在用戶對商品下單后,訂單狀態(tài)為待支付煮盼,在某一時刻用戶正在對該訂單做支付操作短纵,商家對該訂單進行改價操作

狀態(tài)的修改行為需要做串行處理,避免出現(xiàn)數(shù)據(jù)錯亂

基于Redis 分布式鎖

基于Redis 分布式鎖方案

1僵控、唯一線程串行處理

2香到、實現(xiàn)方式
2.1 Redis Setnx(SET if Not eXists) 命令在指定的key不存在時,為key 設(shè)置指定的值

SETNX KEY_NAME VALUE Expire_Time
設(shè)置成功报破,返回1 設(shè)置失敗 返回0

如果Redis 是單機的話很危險悠就,比如T1 在redis上加了一把鎖,這時候Redis掛了泛烙,然后重啟理卑,這時候T2也對相同資源加了一把鎖翘紊,此時就有兩把鎖蔽氨, 當然你對鎖做持久化,但是從架構(gòu)層面上來講是沒有必要的,因為事務(wù)的生命周期比較短鹉究。

2.2 存在問題
鎖時間不可控
無法續(xù)租期
redis鎖依賴于失效時間 expire宇立,比如失效時間為5秒鐘,但是5秒鐘我的事務(wù)還沒執(zhí)行完自赔,鎖失效了妈嘹,另外一個線程又拿到了這把鎖,又得重復去做這個事情绍妨。
單點問題
單實例存在進程一旦死掉润脸,會徹底阻塞業(yè)務(wù)流程
主從方式,主從數(shù)據(jù)異步他去,會存在鎖失效問題

2.2.1毙驯、第一種情況單機如果掛掉的話,如果你的服務(wù)強依賴redis灾测,redis 還沒起來的話爆价,會阻塞業(yè)務(wù)流程。

2.2.2媳搪、第二情況 T1寫到主redis,如果redis 主掛了铭段,還沒有同步到從redis ,根據(jù)哨兵原理秦爆,從redis會切換為主序愚,T2會從新的主去拿,此時T2也會重新生成一把鎖等限,這種情況下展运,T1、T2都會拿到這把鎖精刷。這樣就會出現(xiàn)重復鎖的問題

那么基于Redis分布式鎖到底能不能使用拗胜?取決于你的業(yè)務(wù)場景決定的。
如果你的業(yè)務(wù)是交易場景怒允,嚴格要求他的一致性埂软,極端情況下,鎖重復問題一定是不能忍的纫事。
如果是社交發(fā)消息場景勘畔,極端情況下,如果鎖重復的話丽惶,發(fā)消息重新消費一次炫七,也是能接受的。

redis 作為鎖
高可用無法保證

問題本質(zhì)钾唬,分布式鎖是CP模型万哪,Redis集群是AP模型侠驯,Redis是半同步的。 所以要通過CP模型解決 Redis 自己實現(xiàn)了一套RAFT協(xié)議:redlock

3奕巍、官方建議
Redis 本身建議使用Redlock 算法來保證吟策,但是問題是需要至少三個Redis主從實例來完成,維護成本相對比較高的止,Redlock等同于自己實現(xiàn)簡單的一致性協(xié)議檩坚,細節(jié)繁瑣,且容易出錯诅福。

高可用分布式鎖設(shè)計目標

設(shè)計目標
1匾委、強一致性
其實是任何鎖都要做的事情
2、服務(wù)高可用氓润、系統(tǒng)穩(wěn)健
要保證服務(wù)的高可用剩檀,不能因為一臺機器宕機了就不可用了
3、鎖自動續(xù)約及其自動釋放
要有能力旺芽,在業(yè)務(wù)無感知的情況下沪猴,做自動的續(xù)約,比如Redis 鎖過期時間是5秒鐘采章,當我的事務(wù)5秒鐘還沒有結(jié)束的時候运嗜,自動再續(xù)約5秒鐘。
4悯舟、代碼高度抽象業(yè)務(wù)接入極簡
當然也希望我的代碼比較抽象担租,接入也比較簡單,
5抵怎、可視化管理后臺奋救,監(jiān)控及管理

高可用分布式鎖設(shè)計方案對比

存儲層產(chǎn)品對比

redis zookeeper etcd
一致性算法 paxos(zab) raft
CAP AP CP CP/AP
高可用 主從 N+1可用 N+1可用
接口類型 客戶端 客戶端 http/grpc
實現(xiàn) setNX createEphemeral restful API

zookeeper 為什么是n+1 是因為是奇數(shù)個,etcd 客戶端比較糟糕

1反惕、由于Redis 無法保證數(shù)據(jù)一致性
2尝艘、Zookeeper對鎖實現(xiàn)使用創(chuàng)建臨時節(jié)點和watch機制,執(zhí)行效率姿染、擴展能力背亥、社區(qū)活躍度等方面低于etcd
3、選擇基于etcd 實現(xiàn) tidb也是基于 etcd來實現(xiàn)的

分布式鎖存儲選型

etcd
簡單KV
強一致
高可用--無單點
數(shù)據(jù)高可靠--持久化

分布式鎖整體方案

分布式Client+etcd
clientTTL模式

Client TTL模式
1悬赏、ClientA->etcd->("key","ttl","value","uuid")

2狡汉、ClientB->etcd->("key","ttl","value","uuid");

etcd 只需要填 key ttl ,value隨便填,對于鎖來說value無所謂闽颇,uuid不需要填盾戴,當你成功拿到鎖以后,etcd集群會給你生成一個uuid兵多,這個uuid其實就是你的鎖的唯一的憑證尖啡,接下來所以對鎖的操作橄仆,都是基于這個uuid來實現(xiàn)的。

3可婶、ClientA 拿鎖成功沿癞,ClientB 拿鎖失敗

4援雇、A服務(wù)需要對etcd 保持后臺心跳線程矛渴,比如key的租期是10ms,后臺心跳線程為3ms,心跳線程負責在拿到key之后,每3ms cas 唯一憑證uuid;

比如key的租期是10ms,那么我們的心跳往往會設(shè)置租期的1/3的時間惫搏,也就是3ms,每次心跳的就是就會續(xù)約租期具温,當心跳到的時候,租期還有10-3=7ms,這時候我會刷新ttl改成10ms筐赔,相當于又增加了3ms铣猩。
什么時候釋放呢,這個時候需要業(yè)務(wù)方主動去釋放這個鎖

使用場景一:申請鎖

1茴丰、業(yè)務(wù)放申請資源鎖达皿,調(diào)用時提供key,ttl
2、etcd生成uuid贿肩,作為當前鎖的唯一憑證峦椰,將(key,uuid,ttl)寫etcd
3、檢查etcd中此key 是否存在汰规,如沒有汤功,嘗試寫入key,寫入失敗溜哮,拿鎖失敗滔金,寫入成功拿到鎖。
4茂嗓、拿到鎖后餐茵,客戶端異步心跳線程啟動,心跳線程維持時間為ttl/3,compare and swap uuid ,從而將key 值續(xù)租

5述吸、相關(guān)etcd API
a钟病、申請鎖
curl http://127.0.0.12379/v2/keys/foo -XPUT -d value=bar -d ttl=5 prevExist=false;

b、CAS更新鎖租約
curl http://127.0.0.12379/v2/keys/foo?prevValue=prev_uuid -XPUT -d ttl=5 refresh=true prevExist=true;

c刚梭、CAS刪除鎖
curl http://127.0.0.12379/v2/keys/foo?prevValue=prev_uuid -XDELETE;

使用場景二:申請鎖肠阱,但鎖已被持有

1、業(yè)務(wù)方申請資源鎖朴读,調(diào)用時提供key.ttl
2屹徘、檢查etcd中key的存在,若已存在衅金,拿鎖失敗

使用場景三:鎖的清理

1噪伊、如果調(diào)用方正常結(jié)束簿煌,通過cas 接口調(diào)用delete方法自動清理etcd中的key值
2、如果調(diào)用方異常終止鉴吹,等待原有鎖ttl 過期后姨伟,鎖資源釋放。

如果沒有調(diào)用 delete方法豆励,心跳超時以后夺荒,過時間過期后,鎖會自動釋放良蒸。

業(yè)務(wù)接入

JDK 7 及以上
獲取鎖示例

try(zzlock=zzlock.getlock("resource_id",ttl)){
  //jobs
  zzlock.isTrue();
}

//釋放鎖示例
Optional<LockItem> lockItem=getlock("key");

if(lockItem.isPresent()){
   
   System.out.println("獲得鎖技扼,如果進程被終止,鎖會在10s后失效嫩痰!");
   System.out.println("如果進程繼續(xù)剿吻,后臺心跳線程更新3s鎖時間");
   
   releaseLock(lockItem.get());
}else{
   System.out.println("獲取鎖的失敗4摹@雎谩!");
}

獲取鎖平均耗時監(jiān)控

1纺棺、下面是獲取鎖的平均耗時情況
a榄笙、獲取鎖的平均耗時大概是在2.1ms左右
b、由于etcd的強一致性五辽,根據(jù)raft算法办斑,消耗時間稍微長一點

etcd兼容性測試

etcd提供獨有的集群管理模式,方便進行極端case下的測試杆逗,以三個節(jié)點的etcd集群為例
a乡翅、單節(jié)點停機,不影響持續(xù)寫入罪郊,不影響讀蠕蚜,結(jié)果有一致性
b、當只有一個節(jié)點時悔橄,讀會停機靶累,寫入正常
c、理論上只要不是多節(jié)點同時停機癣疟,線上服務(wù)不會受影響

etcd 恢復/版本

1挣柬、etcd 有自有的數(shù)據(jù)恢復方式,如果服務(wù)停機后睛挚,可以將所有數(shù)據(jù)轉(zhuǎn)移重啟
2邪蛔、etcd的增刪節(jié)點,節(jié)點遷移等部署相關(guān)扎狱,均有相關(guān)操作方式
3侧到、etcd 版本選擇勃教,選擇使用etcd 3.2.9 ,但是因為V3 API 暫時還不夠完備匠抗,建議用V2 方式實現(xiàn)
a故源、V3提供gRPC接口
b、天然提供分布式鎖功能汞贸,只需申請鎖绳军,釋放鎖,不用關(guān)注鎖的租期問題著蛙。

分布式鎖特殊場景

1删铃、特殊場景一:分布式鎖只是在同一自然時間的互斥鎖耳贬,本身不解決冪等性問題踏堡;接入業(yè)務(wù)需要完善從獲得鎖到釋放鎖中間的數(shù)據(jù)冪等邏輯。

例如:T1 拿到lock 很快就處理完成了咒劲,T2 也拿到lock做同樣的操作顷蟆,也是可以的。所以它不能解決冪等問題腐魂,只是同一自然時間的互斥鎖帐偎。

T1 拿到訂單了進行業(yè)務(wù)處理,T2也拿到了訂單也進行業(yè)務(wù)處理蛔屹,要做冪等只需要判斷訂單的狀態(tài)削樊,比如這個訂單已經(jīng)支付了,很顯然就不能重復支付兔毒。這個冪等只能業(yè)務(wù)方去處理漫贞,分布式鎖不會幫你去解決這個問題。

2育叁、特殊場景二:鎖沒有按照預期續(xù)租
a迅脐、心跳續(xù)租沒成功
b、馬上啟動GC豪嗽,GC時間夠長

缺點1:etcd的租期為10秒鐘谴蔑,這時候每次心跳3秒去續(xù)租,這時候網(wǎng)絡(luò)異常龟梦,有可能續(xù)租沒有成功隐锭。

缺點2:etcd 租期為10秒,這時候服務(wù)器執(zhí)行FullGC计贰,這個FullGC 是11秒鐘钦睡,當然GC 要11秒鐘,你的服務(wù)器可能要優(yōu)化蹦玫,每3秒的時候就在執(zhí)行續(xù)租的時候赎婚,GC導致業(yè)務(wù)方的請求暫停了刘绣,當你停止以后已經(jīng)11秒過后了,這時候鎖已經(jīng)被釋放掉了挣输。

3纬凤、特殊場景三:etcd內(nèi)部協(xié)調(diào)發(fā)生問題
a、Leader節(jié)點掛了撩嚼,選主中
選主這個過程中停士,是停止響應(yīng)的,是沒辦法拿到鎖的

b完丽、Raft日志數(shù)據(jù)同步發(fā)生錯誤或者不一致問題
當Rfat 發(fā)生同步錯誤恋技,因為它是CP模型,這時候不會讓你寫或者讀逻族。

consul 也是cp模型 consul 生態(tài)沒有etcd 龐大

為什么k8s 選中etcd 作為它的整個的注冊中心蜻底?
k8s 沒有好的選擇,k8s 當你的集群特別大的時候聘鳞,當你的日志就是你的事件需要寫的時候薄辅,etcd 就會成為你的瓶頸,這時候要怎么辦抠璃,要定期清理你的etcd事件的同步站楚。

冪等需要兩個層次,一是不并發(fā)搏嗡;二是重復消費結(jié)果一樣窿春;分布式鎖的作用就是“串行”;

Redission里實現(xiàn)的分布式鎖初始過期時間也是30秒

一臺機器 耗時 2.1ms qps=500

當業(yè)務(wù)線程假死采盒,ttl線程還在跑旧乞,這個只能ttl超時了自動釋放

線上鎖的最長時間是10秒鐘

zk做分布式鎖,因為是CP模型纽甘,當寫入量很大的話會有問題良蛮?其實對鎖還好,無非就是生成一把鎖會寫一次悍赢,心跳更新租約再寫一次决瞳,delete鎖再寫一次;

如果業(yè)務(wù)阻塞了左权,假死了無法釋放鎖皮胡,此時心跳還在,心跳還在就會自動續(xù)租赏迟。
這時候網(wǎng)關(guān)發(fā)現(xiàn)服務(wù)器假死屡贺,觸發(fā)熔斷,會發(fā)送通知給控制中心,控制中心重啟服務(wù)甩栈,這時候心跳檢測程序就沒有了泻仙;
或者提供一個鎖的最長超時時間,定義最大續(xù)約次數(shù)量没。

舉個例子:有兩個進程拿到相同的orderId,進程1拿到了鎖玉转,先處理了訂單,完事之后更新狀態(tài)殴蹄,進程2拿不到鎖究抓,或通過檢測訂單的狀態(tài),來避免重復執(zhí)行相同的操作袭灯。

數(shù)據(jù)一致性定義

任何人
任何時間
任何地點
任何接入方式
任何服務(wù)
數(shù)據(jù)都是一致

數(shù)據(jù)不一致性產(chǎn)生原因

1刺下、數(shù)據(jù)分散在多處
a、多個DB稽荧;b橘茉、DB和緩存
2、電商交易平臺案例
用戶蛤克、商品捺癞、交易等功能

分布式事務(wù)場景

1夷蚊、電商下單場景
a构挤、下單
b、發(fā)送消息到MQ
2惕鼓、一致性保證
a筋现、本地事務(wù)
下單操作
發(fā)送MQ消息操作
放進一個本地事務(wù)
上述做法有什么問題?

java 實例代碼

try{
    stmt=DriverManager.getConnection("jdbc:mysqlxxxx");
    stmt=conn.createStatement();
    
    //數(shù)據(jù)庫生成訂單操作
    stmt.executeUpdate("insert order values(orderId,timestamp,price,state)");
    
    //生成發(fā)送的消息內(nèi)容
    MsgObject MsgContent(orderID);
    
    //發(fā)送消息操作
    MQClient.sendMsg(MsgContent);
    //事務(wù)提交
    conn.commit();  
}catch(Exception e){
   e.printStackTrace();
   
   try{
        //操作不成功則返回退
        conn.rollback();        
   }catch(Exception ex){
      ex.printStackTrace();
   }
}


分布式事務(wù)分類

1箱歧、剛性分布式事務(wù)
a矾飞、強一致性
b、XA 模型
XA模型是完全遵循ACID的高可用事務(wù)
c呀邢、CAP:CP

2洒沦、柔性分布式事務(wù)
a、最終一致性
b价淌、CAP申眼、BASE理論 AP

剛性分布式事務(wù)

1、滿足傳統(tǒng)事務(wù)特性
ACID(Atomicity-原子性蝉衣、Consistency-一致性括尸、Isolation-隔離性、Durability-持久性)

2病毡、XA模型
a濒翻、XA是X/Open CAE Specification(Distributed Transaction Processing )模型定義,XA規(guī)范由AP、RM 有送、TM組成淌喻。
b、其中應(yīng)用程序(Application Program,簡稱AP):AP定義事務(wù)邊界(定義事務(wù)開始和結(jié)束)并訪問事務(wù)邊界內(nèi)的資源雀摘。
c似嗤、資源管理器(Resource Manager,簡稱RM):RM 管理計算機共享的資源,資源即數(shù)據(jù)庫等届宠。
d烁落、事務(wù)管理器(Transaction Manager ,簡稱TM):負責管理全局事務(wù),分配事務(wù)唯一標識豌注,監(jiān)控事務(wù)的執(zhí)行進度伤塌,并負責事務(wù)的提交、會滾轧铁、失敗恢復等每聪。

image.png

剛性分布式事務(wù)

1、案例:組織爬山

2齿风、過程:
a药薯、二階段提交,是XA規(guī)范標準實現(xiàn)
b救斑、TM 發(fā)起prepare投票
c童本、RM 都同意后,TM再發(fā)起commit
d脸候、Commit過程出現(xiàn)宕機等異常穷娱,節(jié)點服務(wù)重啟后,根據(jù)XA recover再次進行commit補償

3运沦、缺點
a泵额、同步阻塞模型
b、數(shù)據(jù)庫資源鎖定時間過長
它的鎖庫時間很長
現(xiàn)在是兩個庫携添,所以同時要鎖定兩個庫嫁盲;
如果是100個庫,那么就要同時鎖定100個庫烈掠;

c羞秤、全局鎖(隔離級別串行化),并發(fā)低向叉。
基于XA的分布式事務(wù)如果要嚴格保證ACID锥腻,實際需要事務(wù)隔離級別為SERLALIZABLE。這時候會鎖表母谎,這個隔離級別是非常粗的瘦黑,所以并發(fā)也低。

d、不適合長事務(wù)場景

長事務(wù)就是一個事務(wù)里面操作很多步驟幸斥,比如大于3匹摇;所以2PC 比較適合短事務(wù)。

image.png

柔性分布式事務(wù)

1甲葬、CAP
分布式環(huán)境下P一定需要廊勃,CA權(quán)衡折中

2、BASE理論
a经窖、Basically Available 基本可用
b坡垫、Soft state-柔性狀態(tài)
c、Eventual consistency 最終一致性

3画侣、架構(gòu)思考
柔性事務(wù)是對XA協(xié)議的妥協(xié)冰悠,它通過降低強一致性要求,從而降低數(shù)據(jù)庫資源鎖定時間配乱,提升可用性

4溉卓、典型架構(gòu)實現(xiàn)
a、TCC模型
b搬泥、Saga模型

TCC模型

1桑寨、Try-Confirm-Cancel
2、TCC模型完全交由業(yè)務(wù)實現(xiàn)忿檩,每個子業(yè)務(wù)都需要實現(xiàn)Try-Confirm-Cancel接口尉尾,對業(yè)務(wù)侵入大

假如:用戶購買流程:下單->減庫存->支付,那么你每一個步驟都要實現(xiàn)一遍Try-Confirm-Cancel
對業(yè)務(wù)侵入很大休溶,在業(yè)務(wù)層實現(xiàn)

a代赁、資源鎖定交由業(yè)務(wù)方
3、Try
嘗試執(zhí)行業(yè)務(wù)兽掰,完成所有業(yè)務(wù)檢查,預留必要的業(yè)務(wù)資源
每次提交之前徒役,都要去判斷是否具備提交的必要條件

4孽尽、Confirm
真正執(zhí)行業(yè)務(wù),不再做業(yè)務(wù)檢查
5忧勿、Cancel
釋放Try階段預留的業(yè)務(wù)資源
6褂策、匯款服務(wù)由捎、收款服務(wù)案例
A用戶向B用戶匯款500元

匯款服務(wù):

a.Try

1、檢查A賬戶有效性,即查看A賬戶的狀態(tài)是否為“轉(zhuǎn)賬中”或者“凍結(jié)”像棘;
2、檢查A賬戶余額是否充足攀甚;
3担忧、從A賬戶中扣減500元,并將狀態(tài)置為“轉(zhuǎn)賬中”;
4哼勇、預留扣減資源都伪,將從A往B賬戶轉(zhuǎn)賬500元這個事件存入消息或者日志中

b.Confirm:

1、不做任何操作

c.Cancel:

1积担、A賬戶增加500元陨晶;
2、從日志或者消息中帝璧,釋放扣減資源先誉;

收款服務(wù)

a.Try:

1.檢查B賬戶賬戶是否有效

b.Confirm:

1.讀取日志或者消息,B賬戶增加500元的烁;
2.從日志或者消息中谆膳,釋放扣減資源;

c.Cancel:

1.不做任何操作撮躁;

柔性分布式事務(wù)--Saga模型

1漱病、起源于1987年Hector & Kenneth 發(fā)表的論文Sagas
2、Saga 模型把一個分布式事務(wù)拆分為多個本地事務(wù)把曼,每個本地事務(wù)都有相應(yīng)的執(zhí)行模塊和補償模塊(對應(yīng)TCC的Confirm和Cancel)

2杨帽、當Saga 事務(wù)中任意一個本地事務(wù)出錯時,可以通過調(diào)用相關(guān)的補償方法恢復之前的事務(wù)嗤军,達到事務(wù)最終一致性注盈。

3、當每個Saga 子事務(wù)T1叙赚、T2老客、...Tn 都有對應(yīng)的補償定義C1、C2震叮,....Cn-1,那么Saga系統(tǒng)可以保證
a.子事務(wù)序列T1,T2,......,Tn得完成(最佳情況)
b.或者序列T1,T2,....Tj,Cj-1,.....C2,C1, 0<j<n得以完成

逆序串行執(zhí)行胧砰,保證有序

Saga隔離性
1、業(yè)務(wù)層控制并發(fā)
a.在應(yīng)用層加鎖
b.應(yīng)用層預先凍結(jié)資源等

Saga恢復方式
1苇瓣、向后恢復:補償所有已經(jīng)完成的事務(wù)尉间,如果任一子事務(wù)失敗击罪;
2哲嘲、向前恢復:重試失敗的事務(wù),假設(shè)每個子事務(wù)最終都會成功媳禁;

剛性分布式事務(wù)VS柔性分布式事務(wù)

剛性事務(wù)(XA) 柔性事務(wù)
業(yè)務(wù)改造 有(需要改造)
回滾 支持 實現(xiàn)補償接口
一致性 強一致 最終一致
隔離性 原生支持 實現(xiàn)資源鎖定接口
并發(fā)性能 嚴重衰退 略微衰退
適合場景 短事務(wù)眠副,并發(fā)較低 長事務(wù),高并發(fā)

解決思路

問題通用解決思路

1竣稽、解決這個問題本身
2囱怕、讓問題本身消失霍弹,圓珠筆筆芯漏油解決

方案一:從業(yè)務(wù)場景消除分布式事務(wù)
1、思路:核心業(yè)務(wù)先處理光涂,其他業(yè)務(wù)異步處理

方案二:柔性分布式事務(wù)

柔性分布式事務(wù)

通用處理思路

1庞萍、本地事務(wù)->短事務(wù)
2、分布式事務(wù)->長事務(wù)
3忘闻、轉(zhuǎn)變成多個短事務(wù)
4钝计、案例
A[下單]->B[減庫存]->C[支付]
A->DB1
B->DB2
C->DB3
A/B/C都成功
A/B 成功,C失敗 補償

業(yè)務(wù)場景

1齐佳、異步場景
基于MQ驅(qū)動分布事務(wù)

2私恬、同步場景
基于異步補償分布

異步場景分布式事務(wù)設(shè)計

異步場景
商品交易
下單、支付

image.png
方案一:業(yè)務(wù)方提供本地操作成功回查功能

1炼吴、事務(wù)消息:MQ提供類似X/Open XA 的分布式事務(wù)功能本鸣,通過MQ事務(wù)消息能達到分布式事務(wù)的最終一致
2、半消息:暫不能投遞的消息硅蹦,發(fā)送方已經(jīng)將消息成功發(fā)送到了MQ服務(wù)端荣德,但是服務(wù)端未收到生產(chǎn)者對該消息的二次確認,此時該消息被標記成“暫不投遞”狀態(tài)童芹,處于該種狀態(tài)下的消息即半消息

3涮瞻、消息回查:由于網(wǎng)絡(luò)閃斷、生產(chǎn)者應(yīng)用重啟等原因假褪,導致某條事務(wù)消息二次確認丟失署咽,MQ服務(wù)端通過掃描發(fā)現(xiàn)某條消息長期處于“半消息”時,需要主動向消息生產(chǎn)者詢問該消息的最終狀態(tài)(Coommit或者是Rollback)生音,即消息回查

MQ分布式事務(wù)設(shè)計方案圖:

image.png

異步場景分布式事務(wù)設(shè)計

方案一:業(yè)務(wù)方提供本地操作成功回查功能

MQ分布式事務(wù)消息設(shè)計

a宁否、MQ事務(wù)消息設(shè)計事務(wù)消息作為一種異步確保型事務(wù),將兩個事務(wù)分支通過MQ進行異步解耦缀遍,MQ事務(wù)消息的設(shè)計流程同樣借鑒了兩階段提交理論慕匠,整體交互流程如下圖所示:


image.png

1、事務(wù)發(fā)起方首先發(fā)送prepare消息到MQ瑟由;
2絮重、在發(fā)送prepare消息成功后執(zhí)行本地事務(wù);
3歹苦、根據(jù)本地事務(wù)執(zhí)行結(jié)果返回commit或者是rollback;
4、如果消息是rollback,MQ將刪除該prepare消息不進行下發(fā)督怜,如果是commit消息殴瘦,MQ將會消息發(fā)送給consumer端;
5号杠、如果執(zhí)行本地事務(wù)過程中蚪腋,執(zhí)行端掛掉丰歌,或者超時,MQ服務(wù)器端將不停的詢問producer來獲取事務(wù)狀態(tài)屉凯;
6立帖、Consumer端的消費成功機制有MQ保證;

該方案的優(yōu)缺點:

優(yōu)點:通用
缺點:
1悠砚、業(yè)務(wù)方需提供回查接口晓勇,對業(yè)務(wù)侵入大;
2灌旧、發(fā)送消息非冪等绑咱;
3、消費端需要處理冪等枢泰;

消息不冪等的意思就是:
1描融、發(fā)送Half消息到MQ Server 成功;
2衡蚂、第二步的時候Half 消息 ack MQ 發(fā)送方失斄恕! 此時生產(chǎn)者會重復第一步毛甲,再次發(fā)送Half消息到MQ Server;

3年叮、發(fā)送多次就會處理多次,所以存在消息不冪等的問題丽啡。

方案二

本地操作和發(fā)送消息通過本地事務(wù)強一致性

1谋右、本地事務(wù)操作表
2、本地事務(wù)消息表
mqMessages(msgid,content,topic,status);

操作表和消息表放在同一個庫补箍,所以是Local Transaction 事務(wù)

image.png

比如:下訂單流程改执,我們將下訂單和下訂單產(chǎn)生的消息放到同一個本地事務(wù)里面執(zhí)行。

方案二優(yōu)缺點:
1坑雅、發(fā)送端消息不冪等
At least once (至少一次,肯定都是這個辈挂,下面兩個不要用)
Only once(只有一次)
At more once (最多一次)

2、消費端處理消息冪等
a裹粤、分布式鎖

3终蒂、A->B->C
3.1、A/B成功遥诉,C失斈雌;

比如: A->DB1 并寫MQ矮锈;然后 MQ->B->DB2; MQ->C->DB3;
1霉翔、如果很幸運,B成功了苞笨,C也成功了债朵,事務(wù)就成功了子眶。
2、如果B成功了序芦,C失敗了臭杰,這時候C發(fā)一條會滾消息MQ;
3谚中、然后這個補償消息MQ要被A和B消費渴杆,這時候又回到了1的步驟。這樣就會出現(xiàn)死循環(huán)藏杖。如下圖所示


image.png

a将塑、記錄錯誤日志
b、報警
c蝌麸、人工介入

4点寥、優(yōu)點:
業(yè)務(wù)侵入小来吩;

其實現(xiàn)在大部分走的是這種模式敢辩。

實際異步場景使用較多的是方案二:本地事務(wù)消息表

基于半消息實現(xiàn)的“方案一”使用的比較少,現(xiàn)在開源的RockectMQ就是半消息的實現(xiàn)方案弟疆。

會滾MQ需要串行嗎戚长?
如果MQ的處理結(jié)果要告訴別人就要串行,否則無需串行怠苔,可以同時處理多個MQ會滾同廉。

轉(zhuǎn)錢有凍結(jié)狀態(tài),所以不一定最后一步做轉(zhuǎn)錢動作柑司,轉(zhuǎn)錢凍結(jié)狀態(tài)是無法提現(xiàn)的迫肖。

如果用戶將平臺的庫存占住而不支付,怎么處理攒驰?
不支付是有時間限制的蟆湖,比如30分鐘,或者2個小時玻粪,這時候可以發(fā)送一個延遲消息隅津,如果不支付就會被清空掉。
或者定時作業(yè)劲室,定時掃描未支付的訂單伦仍。

對于分布式事務(wù),要盡可能得減少網(wǎng)絡(luò)交互很洋,網(wǎng)絡(luò)交互越多呢铆,發(fā)生事務(wù)處理失敗或者事務(wù)會滾的概率越大。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蹲缠,一起剝皮案震驚了整個濱河市棺克,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌线定,老刑警劉巖娜谊,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異斤讥,居然都是意外死亡纱皆,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門芭商,熙熙樓的掌柜王于貴愁眉苦臉地迎上來派草,“玉大人,你說我怎么就攤上這事铛楣〗ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵簸州,是天一觀的道長鉴竭。 經(jīng)常有香客問我,道長岸浑,這世上最難降的妖魔是什么搏存? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮矢洲,結(jié)果婚禮上璧眠,老公的妹妹穿的比我還像新娘。我一直安慰自己读虏,他們只是感情好责静,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著掘譬,像睡著了一般泰演。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上葱轩,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天睦焕,我揣著相機與錄音,去河邊找鬼靴拱。 笑死垃喊,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的袜炕。 我是一名探鬼主播本谜,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼偎窘!你這毒婦竟也來了乌助?” 一聲冷哼從身側(cè)響起溜在,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎他托,沒想到半個月后掖肋,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡赏参,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年志笼,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片把篓。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡纫溃,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出韧掩,到底是詐尸還是另有隱情紊浩,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布揍很,位于F島的核電站郎楼,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏窒悔。R本人自食惡果不足惜呜袁,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望简珠。 院中可真熱鬧阶界,春花似錦、人聲如沸聋庵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祭玉。三九已至氧映,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間脱货,已是汗流浹背岛都。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留振峻,地道東北人臼疫。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像扣孟,于是被迫代替她去往敵國和親烫堤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

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

  • 在很多環(huán)境下,多個不同的進程需要以排他的形式使用共享資源鸽斟,這是使用分布式鎖機制是一種傳統(tǒng)但有效的方案拔创。 有很多的庫...
    BigFish__閱讀 1,538評論 0 0
  • 定義 正常的單機狀態(tài)的,共享資源都是在通過一個數(shù)據(jù)庫下的湾盗,可以在單機中進行加鎖伏蚊,保證共享數(shù)據(jù)的線程安全,分布式環(huán)境...
    先生zeng閱讀 1,065評論 0 14
  • 最近看了極客時間左耳聽風的專欄格粪,對于分布式系統(tǒng)的設(shè)計有了更深的認識,準備結(jié)合陳皓的總結(jié)加上自己看過的資料對于分布式...
    仰泳的雙魚閱讀 3,676評論 0 23
  • 1 打開Settings… Ctrl+Alt+S2 關(guān)閉一個標簽 ctril+f4關(guān)閉所有標簽Ctrl+Shif...
    6cc89d7ec09f閱讀 243評論 0 0
  • 其實一直覺得自己是個很三分鐘熱度的人氛改,無論對物帐萎、對事,甚至有時對人亦是如此胜卤。記得小的時候媽媽讓去學鋼琴疆导,剛開始興致...
    暖暖暖暖暖鹿_閱讀 104評論 0 1