国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【分布式】java實(shí)現(xiàn)分布式事務(wù)的五種方案

這篇具有很好參考價(jià)值的文章主要介紹了【分布式】java實(shí)現(xiàn)分布式事務(wù)的五種方案。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

背景

用戶支付完成會(huì)將支付狀態(tài)及訂單狀態(tài)保存在訂單數(shù)據(jù)庫(kù)中,由訂單服務(wù)去維護(hù)訂單數(shù)據(jù)庫(kù)。由庫(kù)存服務(wù)去維護(hù)庫(kù)存數(shù)據(jù)庫(kù)的信息。下圖是系統(tǒng)結(jié)構(gòu)圖:
java分布式事務(wù),分布式,java,分布式,數(shù)據(jù)庫(kù)
如何實(shí)現(xiàn)兩個(gè)分布式服務(wù)(訂單服務(wù)、庫(kù)存服務(wù))共同完成一件事即訂單支付成功自動(dòng)減庫(kù)存,這里的關(guān)鍵是如何保證兩個(gè)分布式服務(wù)的事務(wù)的一致性。
嘗試解決上邊的需求,在訂單服務(wù)中遠(yuǎn)程調(diào)用減庫(kù)存接口,偽代碼如下:

訂單支付結(jié)果通知方法{

? 更新支付表中支付狀態(tài)為“成功”。
? 遠(yuǎn)程調(diào)用減庫(kù)存接口減庫(kù)存。
}

上邊的邏輯說(shuō)明:

  1. 更新支付表狀態(tài)為本地?cái)?shù)據(jù)庫(kù)操作。
  2. 遠(yuǎn)程調(diào)用減庫(kù)存接口為網(wǎng)絡(luò)遠(yuǎn)程調(diào)用請(qǐng)求。
  3. 為保存事務(wù)上邊兩步操作由spring控制事務(wù),當(dāng)遇到Exception異常則回滾本地?cái)?shù)據(jù)庫(kù)操作。
    問(wèn)題如下:
  4. 如果更新支付表失敗則拋出異常,不再執(zhí)行遠(yuǎn)程調(diào)用,此設(shè)想沒(méi)有問(wèn)題。
  5. 如果更新支付表成功,網(wǎng)絡(luò)遠(yuǎn)程調(diào)用超時(shí)會(huì)拉長(zhǎng)本地?cái)?shù)據(jù)庫(kù)事務(wù)時(shí)間,影響數(shù)據(jù)庫(kù)性能。
  6. 如果更新支付表成功,遠(yuǎn)程調(diào)用減庫(kù)存成功(減庫(kù)存數(shù)據(jù)庫(kù)commit成功),最后更新支付表commit失敗,此時(shí)出現(xiàn)操作不一致。
    上邊的問(wèn)題涉及到分布式事務(wù)控制。

什么是分布式事務(wù)

什么是分布式系統(tǒng):

部署在不同結(jié)點(diǎn)上的系統(tǒng)通過(guò)網(wǎng)絡(luò)交互來(lái)完成協(xié)同工作的系統(tǒng)。

比如:充值加積分的業(yè)務(wù),用戶在充值系統(tǒng)向自己的賬戶充錢,在積分系統(tǒng)中自己積分相應(yīng)的增加。充值系統(tǒng)和積分系統(tǒng)是兩個(gè)不同的系統(tǒng),一次充值加積分的業(yè)務(wù)就需要這兩個(gè)系統(tǒng)協(xié)同工作來(lái)完成。

什么是事務(wù):

事務(wù)是指由一組操作組成的一個(gè)工作單元,這個(gè)工作單元具有原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持久性(durability)。

  • 原子性:執(zhí)行單元中的操作要么全部執(zhí)行成功,要么全部失敗。如果有一部分成功一部分失敗那么成功的操作要全部回滾到執(zhí)行前的狀態(tài)。

  • 一致性:執(zhí)行一次事務(wù)會(huì)使用數(shù)據(jù)從一個(gè)正確的狀態(tài)轉(zhuǎn)換到另一個(gè)正確的狀態(tài),執(zhí)行前后數(shù)據(jù)都是完整的。

  • 隔離性:在該事務(wù)執(zhí)行的過(guò)程中,任何數(shù)據(jù)的改變只存在于該事務(wù)之中,對(duì)外界沒(méi)有影響,事務(wù)與事務(wù)之間是完全的隔離的。只有事務(wù)提交后其它事務(wù)才可以查詢到最新的數(shù)據(jù)。

  • 持久性:事務(wù)完成后對(duì)數(shù)據(jù)的改變會(huì)永久性的存儲(chǔ)起來(lái),即使發(fā)生斷電宕機(jī)數(shù)據(jù)依然在。

什么是本地事務(wù):

本地事務(wù)就是用關(guān)系數(shù)據(jù)庫(kù)來(lái)控制事務(wù),關(guān)系數(shù)據(jù)庫(kù)通常都具有ACID特性,傳統(tǒng)的單體應(yīng)用通常會(huì)將數(shù)據(jù)全部存儲(chǔ)在一個(gè)數(shù)據(jù)庫(kù)中,會(huì)借助關(guān)系數(shù)據(jù)庫(kù)來(lái)完成事務(wù)控制。

什么是分布式事務(wù):

在分布式系統(tǒng)中一次操作由多個(gè)系統(tǒng)協(xié)同完成,這種一次事務(wù)操作涉及多個(gè)系統(tǒng)通過(guò)網(wǎng)絡(luò)協(xié)同完成的過(guò)程稱為分布式事務(wù)。這里強(qiáng)調(diào)的是多個(gè)系統(tǒng)通過(guò)網(wǎng)絡(luò)協(xié)同完成一個(gè)事務(wù)的過(guò)程,并不強(qiáng)調(diào)多個(gè)系統(tǒng)訪問(wèn)了不同的數(shù)據(jù)庫(kù),即使多個(gè)系統(tǒng)訪問(wèn)的是同一個(gè)數(shù)據(jù)庫(kù)也是分布式事務(wù),如下圖:

java分布式事務(wù),分布式,java,分布式,數(shù)據(jù)庫(kù)

另外一種分布式事務(wù)的表現(xiàn)是,一個(gè)應(yīng)用程序使用了多個(gè)數(shù)據(jù)源連接了不同的數(shù)據(jù)庫(kù),當(dāng)一次事務(wù)需要操作多個(gè)數(shù)據(jù)源,此時(shí)也屬于分布式事務(wù),當(dāng)系統(tǒng)作了數(shù)據(jù)庫(kù)拆分后會(huì)出現(xiàn)此種情況。

java分布式事務(wù),分布式,java,分布式,數(shù)據(jù)庫(kù)

分布式事務(wù)有哪些應(yīng)用場(chǎng)景:

  1. 電商系統(tǒng)中的下單扣庫(kù)存
    電商系統(tǒng)中,訂單系統(tǒng)和庫(kù)存系統(tǒng)是兩個(gè)系統(tǒng),一次下單的操作由兩個(gè)系統(tǒng)協(xié)同完成
  2. 金融系統(tǒng)中的銀行卡充值
    在金融系統(tǒng)中通過(guò)銀行卡向平臺(tái)充值需要通過(guò)銀行系統(tǒng)和金融系統(tǒng)協(xié)同完成。
  3. 教育系統(tǒng)中下單選課業(yè)務(wù)
    在線教育系統(tǒng)中,用戶購(gòu)買課程,下單支付成功后學(xué)生選課成功,此事務(wù)由訂單系統(tǒng)和選課系統(tǒng)協(xié)同完成。
  4. SNS系統(tǒng)的消息發(fā)送
    在社交系統(tǒng)中發(fā)送站內(nèi)消息同時(shí)發(fā)送手機(jī)短信,一次消息發(fā)送由站內(nèi)消息系統(tǒng)和手機(jī)通信系統(tǒng)協(xié)同完成。

如何進(jìn)行分布式事務(wù)控制

CAP理論

CAP理論是分布式事務(wù)處理的理論基礎(chǔ):分布式系統(tǒng)在設(shè)計(jì)時(shí)只能在一致性(Consistency)、可用性(Availability)、分區(qū)容忍性(PartitionTolerance)中滿足兩種,無(wú)法兼顧三種。
java分布式事務(wù),分布式,java,分布式,數(shù)據(jù)庫(kù)

  • 一致性(Consistency):服務(wù)A、B、C三個(gè)結(jié)點(diǎn)都存儲(chǔ)了用戶數(shù)據(jù), 三個(gè)結(jié)點(diǎn)的數(shù)據(jù)需要保持同一時(shí)刻數(shù)據(jù)一致性。
  • 可用性(Availability):服務(wù)A、B、C三個(gè)結(jié)點(diǎn),其中一個(gè)結(jié)點(diǎn)宕機(jī)不影響整個(gè)集群對(duì)外提供服務(wù),如果只有服務(wù)A結(jié)點(diǎn),當(dāng)服務(wù)A宕機(jī)整個(gè)系統(tǒng)將無(wú)法提供服務(wù),增加服務(wù)B、C是為了保證系統(tǒng)的可用性。
  • 分區(qū)容忍性(Partition Tolerance):分區(qū)容忍性就是允許系統(tǒng)通過(guò)網(wǎng)絡(luò)協(xié)同工作,分區(qū)容忍性要解決由于網(wǎng)絡(luò)分區(qū)導(dǎo)致數(shù)據(jù)的不完整及無(wú)法訪問(wèn)等問(wèn)題。

分布式系統(tǒng)不可避免的出現(xiàn)了多個(gè)系統(tǒng)通過(guò)網(wǎng)絡(luò)協(xié)同工作的場(chǎng)景,結(jié)點(diǎn)之間難免會(huì)出現(xiàn)網(wǎng)絡(luò)中斷、網(wǎng)延延遲等現(xiàn)象,這種現(xiàn)象一旦出現(xiàn)就導(dǎo)致數(shù)據(jù)被分散在不同的結(jié)點(diǎn)上,這就是網(wǎng)絡(luò)分區(qū)。

分布式系統(tǒng)如何兼顧C(jī)AP?

在保證分區(qū)容忍性的前提下一致性和可用性無(wú)法兼顧,如果要提高系統(tǒng)的可用性就要增加多個(gè)結(jié)點(diǎn),如果要保證數(shù)據(jù)的一致性就要實(shí)現(xiàn)每個(gè)結(jié)點(diǎn)的數(shù)據(jù)一致,結(jié)點(diǎn)越多可用性越好,但是數(shù)據(jù)一致性越差。所以,在進(jìn)行分布式系統(tǒng)設(shè)計(jì)時(shí),同時(shí)滿足“一致性”、“可用性”和“分區(qū)容忍性”三者是幾乎不可能的。

CAP有哪些組合方式?

  • CA:放棄分區(qū)容忍性,加強(qiáng)一致性和可用性,關(guān)系數(shù)據(jù)庫(kù)按照CA進(jìn)行設(shè)計(jì)。
  • AP:放棄一致性,加強(qiáng)可用性和分區(qū)容忍性,追求最終一致性,很多NoSQL數(shù)據(jù)庫(kù)按照AP進(jìn)行設(shè)計(jì)。
    說(shuō)明:這里放棄一致性是指放棄強(qiáng)一致性,強(qiáng)一致性就是寫入成功立刻要查詢出最新數(shù)據(jù)。追求最終一致性是指允許暫時(shí)的數(shù)據(jù)不一致,只要最終在用戶接受的時(shí)間內(nèi)數(shù)據(jù) 一致即可。
  • CP:放棄可用性,加強(qiáng)一致性和分區(qū)容忍性,一些強(qiáng)一致性要求的系統(tǒng)按CP進(jìn)行設(shè)計(jì),比如跨行轉(zhuǎn)賬,一次轉(zhuǎn)賬請(qǐng)求要等待雙方銀行系統(tǒng)都完成整個(gè)事務(wù)才算完成。說(shuō)明:由于網(wǎng)絡(luò)問(wèn)題的存在CP系統(tǒng)可能會(huì)出現(xiàn)待等待超時(shí),如果沒(méi)有處理超時(shí)問(wèn)題則整理系統(tǒng)會(huì)出現(xiàn)阻塞。

BASE 理論

  1. 強(qiáng)一致性和最終一致性
    CAP 理論告訴我們一個(gè)分布式系統(tǒng)最多只能同時(shí)滿足一致性(Consistency)、可用性(Availability)和分區(qū)容忍性(Partition tolerance)這三項(xiàng)中的兩項(xiàng),其中AP在實(shí)際應(yīng)用中較多,AP 即舍棄一致性,保證可用性和分區(qū)容忍性,但是在實(shí)際生產(chǎn)中很多場(chǎng)景都要實(shí)現(xiàn)一致性,比如主數(shù)據(jù)庫(kù)向從數(shù)據(jù)庫(kù)同步數(shù)據(jù),即使不要一致性,但是最終也要將數(shù)據(jù)同步成功來(lái)保證數(shù)據(jù)一致,這種一致性和 CAP 中的一致性不同,CAP 中的一致性要求 在任何時(shí)間查詢每個(gè)結(jié)點(diǎn)數(shù)據(jù)都必須一致,它強(qiáng)調(diào)的是強(qiáng)一致性,但是最終一致性是允許可以在一段時(shí)間內(nèi)每個(gè)結(jié)點(diǎn)的數(shù)據(jù)不一致,但是經(jīng)過(guò)一段時(shí)間每個(gè)結(jié)點(diǎn)的數(shù)據(jù)必須一致,它強(qiáng)調(diào)的是最終數(shù)據(jù)的一致性。

  2. Base 理論介紹
    BASE 是 Basically Available(基本可用)、Soft state(軟狀態(tài))和 Eventually consistent (最終一致性)三個(gè)短語(yǔ)的縮寫。
    BASE 理論是對(duì) CAP 中 AP 的一個(gè)擴(kuò)展,通過(guò)犧牲強(qiáng)一致性來(lái)獲得可用性,當(dāng)出現(xiàn)故障允許部分不可用但要保證核心功能可用,允許數(shù)據(jù)在一段時(shí)間內(nèi)是不一致的,但最終達(dá)到一致?tīng)顟B(tài)。滿足BASE理論的事務(wù),我們稱之為“柔性事務(wù)”。

  3. 基本可用:分布式系統(tǒng)在出現(xiàn)故障時(shí),允許損失部分可用功能,保證核心功能可用。如電商網(wǎng)站交易付款出現(xiàn)問(wèn)題了,商品依然可以正常瀏覽。

  4. 軟狀態(tài):由于不要求強(qiáng)一致性,所以BASE允許系統(tǒng)中存在中間狀態(tài)(也叫軟狀態(tài)),這個(gè)狀態(tài)不影響系統(tǒng)可用性,如訂單的"支付中"、“數(shù)據(jù)同步中”等狀態(tài),待數(shù)據(jù)最終一致后狀態(tài)改為“成功”狀態(tài)。

  5. 最終一致:最終一致是指經(jīng)過(guò)一段時(shí)間后,所有節(jié)點(diǎn)數(shù)據(jù)都將會(huì)達(dá)到一致。如訂單的"支付中"狀態(tài),最終會(huì)變 為“支付成功”或者"支付失敗",使訂單狀態(tài)與實(shí)際交易結(jié)果達(dá)成一致,但需要一定時(shí)間的延遲、等待。

小結(jié)

?在分布式系統(tǒng)設(shè)計(jì)中AP的應(yīng)用較多,即保證分區(qū)容忍性和可用性,犧牲數(shù)據(jù)的強(qiáng)一致性(寫操作后立刻讀取到最新數(shù)據(jù)),保證數(shù)據(jù)最終一致性。比如:訂單退款,今日退款成功,明日賬戶到賬,只要在預(yù)定的用戶可以接受的時(shí)間內(nèi)退款事務(wù)走完即可。

分布式事務(wù)一致性解決方案

兩階段提交協(xié)議(2PC)

? 為解決分布式系統(tǒng)的數(shù)據(jù)一致性問(wèn)題出現(xiàn)了兩階段提交協(xié)議(2 Phase Commitment Protocol),兩階段提交由協(xié)調(diào)者和參與者組成,共經(jīng)過(guò)兩個(gè)階段和三個(gè)操作,部分關(guān)系數(shù)據(jù)庫(kù)如Oracle、MySQL支持兩階段提交協(xié)議,本節(jié)講解關(guān)系數(shù)據(jù)庫(kù)兩階段提交協(xié)議。

2PC協(xié)議流程圖

java分布式事務(wù),分布式,java,分布式,數(shù)據(jù)庫(kù)

  1. 第一階段:準(zhǔn)備階段(prepare)
    協(xié)調(diào)者通知參與者準(zhǔn)備提交訂單,參與者開(kāi)始投票。
    參與者完成準(zhǔn)備工作向協(xié)調(diào)者回應(yīng)Yes|NO。

  2. 第二階段:提交(commit)/回滾(rollback)階段
    協(xié)調(diào)者根據(jù)參與者的投票結(jié)果發(fā)起最終的提交指令。
    如果有參與者沒(méi)有準(zhǔn)備好則發(fā)起回滾指令。

應(yīng)用實(shí)例

一個(gè)下單減庫(kù)存的例子:
java分布式事務(wù),分布式,java,分布式,數(shù)據(jù)庫(kù)

  1. 應(yīng)用程序連接兩個(gè)數(shù)據(jù)源。
  2. 應(yīng)用程序通過(guò)事務(wù)協(xié)調(diào)器向兩個(gè)庫(kù)發(fā)起prepare,兩個(gè)數(shù)據(jù)庫(kù)收到消息分別執(zhí)行本地事務(wù)(記錄日志),但不提交,如果執(zhí)行成功則回復(fù)yes,否則回復(fù)no。
  3. 事務(wù)協(xié)調(diào)器收到回復(fù),只要有一方回復(fù)no則分別向參與者發(fā)起回滾事務(wù),參與者開(kāi)始回滾事務(wù)。
  4. 事務(wù)協(xié)調(diào)器收到回復(fù),全部回復(fù)yes,此時(shí)向參與者發(fā)起提交事務(wù)。如果參與者有一方提交事務(wù)失敗則由事務(wù)協(xié)調(diào)器發(fā)起回滾事務(wù)。

2PC的優(yōu)缺點(diǎn)

2PC的優(yōu)點(diǎn):實(shí)現(xiàn)強(qiáng)一致性,部分關(guān)系數(shù)據(jù)庫(kù)支持(Oracle、MySQL等)。

缺點(diǎn):整個(gè)事務(wù)的執(zhí)行需要由協(xié)調(diào)者在多個(gè)節(jié)點(diǎn)之間去協(xié)調(diào),增加了事務(wù)的執(zhí)行時(shí)間,性能低下。

解決方案有:springboot+Atomikos or Bitronix

3PC主要是解決協(xié)調(diào)者與參與者通信阻塞問(wèn)題而產(chǎn)生的,它比2PC傳遞的消息還要多,性能不高。

XA 方案

2PC的傳統(tǒng)方案是在數(shù)據(jù)庫(kù)層面實(shí)現(xiàn)的,如 Oracle、MySQL 都支持 2PC 協(xié)議,為了統(tǒng)一標(biāo)準(zhǔn)減少行業(yè)內(nèi)不必要的對(duì)接成本,需要制定標(biāo)準(zhǔn)化的處理模型及接口標(biāo)準(zhǔn),國(guó)際開(kāi)放標(biāo)準(zhǔn)組織 Open Group 定義了分布式事務(wù)處理模型DTP(Distributed Transaction Processing Reference Model)。

為了讓大家更明確 XA 方案的內(nèi)容,下面以新用戶注冊(cè)送積分為例來(lái)說(shuō)明:

java分布式事務(wù),分布式,java,分布式,數(shù)據(jù)庫(kù)

執(zhí)行流程如下:

  1. 應(yīng)用程序(AP)持有用戶庫(kù)和積分庫(kù)兩個(gè)數(shù)據(jù)源。
  2. 應(yīng)用程序(AP)通過(guò) TM 通知用戶庫(kù) RM 新增用戶,同時(shí)通知積分庫(kù)RM為該用戶新增積分,RM 此時(shí)并未提交事務(wù),此時(shí)用戶和積分資源鎖定。
  3. TM 收到執(zhí)行回復(fù),只要有一方失敗則分別向其他 RM 發(fā)起回滾事務(wù),回滾完畢,資源鎖釋放。
  4. TM 收到執(zhí)行回復(fù),全部成功,此時(shí)向所有 RM 發(fā)起提交事務(wù),提交完畢,資源鎖釋放。

DTP 模型定義如下角色:

  • AP(Application Program):即應(yīng)用程序,可以理解為使用 DTP 分布式事務(wù)的程序。
  • RM(Resource Manager):即資源管理器,可以理解為事務(wù)的參與者,一般情況下是指一個(gè)數(shù)據(jù)庫(kù)實(shí)例,通過(guò)資源管理器對(duì)該數(shù)據(jù)庫(kù)進(jìn)行控制,資源管理器控制著分支事務(wù)。
  • TM(Transaction Manager):事務(wù)管理器,負(fù)責(zé)協(xié)調(diào)和管理事務(wù),事務(wù)管理器控制著全局事務(wù),管理事務(wù)生命周期,并協(xié)調(diào)各個(gè) RM。全局事務(wù)是指分布式事務(wù)處理環(huán)境中,需要操作多個(gè)數(shù)據(jù)庫(kù)共同完成一個(gè)工作,這個(gè)工作即是一個(gè)全局事務(wù)。
  • DTP 模型定義TM和RM之間通訊的接口規(guī)范叫 XA,簡(jiǎn)單理解為數(shù)據(jù)庫(kù)提供的 2PC 接口協(xié)議,基于數(shù)據(jù)庫(kù)的 XA 協(xié)議來(lái)實(shí)現(xiàn) 2PC 又稱為 XA 方案

以上三個(gè)角色之間的交互方式如下:

  1. TM 向 AP 提供 應(yīng)用程序編程接口,AP 通過(guò) TM 提交及回滾事務(wù)。
  2. TM 交易中間件通過(guò) XA 接口來(lái)通知 RM 數(shù)據(jù)庫(kù)事務(wù)的開(kāi)始、結(jié)束以及提交、回滾等。

小結(jié)

整個(gè) 2PC 的事務(wù)流程涉及到三個(gè)角色 AP、RM、TM。AP 指的是使用 2PC 分布式事務(wù)的應(yīng)用程序;RM 指的是資源管理器,它控制著分支事務(wù);TM 指的是事務(wù)管理器,它控制著整個(gè)全局事務(wù)。

(1)在準(zhǔn)備階段 RM 執(zhí)行實(shí)際的業(yè)務(wù)操作,但不提交事務(wù),資源鎖定

(2)在提交階段 TM 會(huì)接受 RM 在準(zhǔn)備階段的執(zhí)行回復(fù),只要有任一個(gè)RM執(zhí)行失敗,TM 會(huì)通知所有 RM 執(zhí)行回滾操作,否則,TM 將會(huì)通知所有 RM 提交該事務(wù)。提交階段結(jié)束資源鎖釋放。

XA方案的問(wèn)題

需要本地?cái)?shù)據(jù)庫(kù)支持XA協(xié)議。
資源鎖需要等到兩個(gè)階段結(jié)束才釋放,性能較差。

事務(wù)補(bǔ)償 TCC

TCC事務(wù)補(bǔ)償是基于2PC實(shí)現(xiàn)的業(yè)務(wù)層事務(wù)控制方案,它是Try、Confirm和Cancel三個(gè)單詞的首字母,

含義如下

  1. Try 檢查及預(yù)留業(yè)務(wù)資源完成提交事務(wù)前的檢查,并預(yù)留好資源。
  2. Confirm確定執(zhí)行業(yè)務(wù)操作對(duì)try階段預(yù)留的資源正式執(zhí)行。
  3. Cancel取消執(zhí)行業(yè)務(wù)操作對(duì)try階段預(yù)留的資源釋放。

應(yīng)用實(shí)例

下邊用一個(gè)下單減庫(kù)存的業(yè)務(wù)為例來(lái)說(shuō)明:
java分布式事務(wù),分布式,java,分布式,數(shù)據(jù)庫(kù)

1、Try

  • 下單業(yè)務(wù)由訂單服務(wù)和庫(kù)存服務(wù)協(xié)同完成,在try階段訂單服務(wù)和庫(kù)存服務(wù)完成檢查和預(yù)留資源。
  • 訂單服務(wù)檢查當(dāng)前是否滿足提交訂單的條件(比如:當(dāng)前存在未完成訂單的不允許提交新訂單)。
  • 庫(kù)存服務(wù)檢查當(dāng)前是否有充足的庫(kù)存,并鎖定資源。

2、Confirm

  • 訂單服務(wù)和庫(kù)存服務(wù)成功完成Try后開(kāi)始正式執(zhí)行資源操作。
  • 訂單服務(wù)向訂單寫一條訂單信息。
  • 庫(kù)存服務(wù)減去庫(kù)存。

3、Cancel

  • 如果訂單服務(wù)和庫(kù)存服務(wù)有一方出現(xiàn)失敗則全部取消操作。
  • 訂單服務(wù)需要?jiǎng)h除新增的訂單信息。
  • 庫(kù)存服務(wù)將減去的庫(kù)存再還原。

TCC優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):最終保證數(shù)據(jù)的一致性,在業(yè)務(wù)層實(shí)現(xiàn)事務(wù)控制,靈活性好。
  • 缺點(diǎn):開(kāi)發(fā)成本高,每個(gè)事務(wù)操作每個(gè)參與者都需要實(shí)現(xiàn)try/confirm/cancel三個(gè)接口。

注意:TCC的try/confirm/cancel接口都要實(shí)現(xiàn)冪等性,在為在try、confirm、cancel失敗后要不斷重試。

什么是冪等性? 冪等性是指同一個(gè)操作無(wú)論請(qǐng)求多少次,其結(jié)果都相同。
冪等操作實(shí)現(xiàn)方式有:
1、操作之前在業(yè)務(wù)方法進(jìn)行判斷如果執(zhí)行過(guò)了就不再執(zhí)行。
2、緩存所有請(qǐng)求和處理的結(jié)果,已經(jīng)處理的請(qǐng)求則直接返回結(jié)果。
3、在數(shù)據(jù)庫(kù)表中加一個(gè)狀態(tài)字段(未處理,已處理),數(shù)據(jù)操作時(shí)判斷未處理時(shí)再處理。

可靠消息隊(duì)列實(shí)現(xiàn)最終一致性

本方案是將分布式事務(wù)拆分成多個(gè)本地事務(wù)來(lái)完成,并且由消息隊(duì)列異步協(xié)調(diào)完成,如下圖:
下邊以下單減少庫(kù)存為例來(lái)說(shuō)明:
java分布式事務(wù),分布式,java,分布式,數(shù)據(jù)庫(kù)

可以把MQ去掉不使用MQ

1、訂單服務(wù)和庫(kù)存服務(wù)完成檢查和預(yù)留資源。
2、訂單服務(wù)在本地事務(wù)中完成添加訂單表記錄和添加“減少庫(kù)存任務(wù)消息”。
3、由定時(shí)任務(wù)根據(jù)消息表的記錄發(fā)送給MQ通知庫(kù)存服務(wù)執(zhí)行減庫(kù)存操作。
4、庫(kù)存服務(wù)執(zhí)行減少庫(kù)存,并且記錄執(zhí)行消息狀態(tài)(為避免重復(fù)執(zhí)行消息,在執(zhí)行減庫(kù)存之前查詢是否執(zhí)行過(guò)此消息)。
5、庫(kù)存服務(wù)向MQ發(fā)送完成減少庫(kù)存的消息。
6、訂單服務(wù)接收到完成庫(kù)存減少的消息后刪除原來(lái)添加的“減少庫(kù)存任務(wù)消息”。

實(shí)現(xiàn)最終事務(wù)一致要求:預(yù)留資源成功理論上要求正式執(zhí)行成功,如果執(zhí)行失敗會(huì)進(jìn)行重試,要求業(yè)務(wù)執(zhí)行方法實(shí)現(xiàn)冪等。

優(yōu)缺點(diǎn)

優(yōu)點(diǎn) :
由MQ按異步的方式協(xié)調(diào)完成事務(wù),性能較高。
不用實(shí)現(xiàn)try/confirm/cancel接口,開(kāi)發(fā)成本比TCC低。

缺點(diǎn):
此方式基于關(guān)系數(shù)據(jù)庫(kù)本地事務(wù)來(lái)實(shí)現(xiàn),會(huì)出現(xiàn)頻繁讀寫數(shù)據(jù)庫(kù)記錄,浪費(fèi)數(shù)據(jù)庫(kù)資源,另外對(duì)于高并發(fā)操作不是最佳方案。

分布式事務(wù)解決方案之最大努力通知

什么是最大努力通知

最大努力通知也是一種解決分布式事務(wù)的方案,下邊是一個(gè)是充值的例子:
java分布式事務(wù),分布式,java,分布式,數(shù)據(jù)庫(kù)
交互流程:

  1. 賬戶系統(tǒng)調(diào)用充值系統(tǒng)接口
  2. 充值系統(tǒng)完成支付處理向賬戶發(fā)起充值結(jié)果通知,若通知失敗,則充值系統(tǒng)按策略進(jìn)行重復(fù)通知
  3. 賬戶系統(tǒng)接收到充值結(jié)果通知修改充值狀態(tài)
  4. 賬戶系統(tǒng)未接收到通知會(huì)主動(dòng)調(diào)用充值系統(tǒng)的接口查詢充值結(jié)果

通過(guò)上邊的例子我們總結(jié)最大努力通知方案的目標(biāo):發(fā)起通知方通過(guò)一定的機(jī)制最大努力將業(yè)務(wù)處理結(jié)果通知到接收方。

具體包括:

  1. 有一定的消息重復(fù)通知機(jī)制。因?yàn)榻邮胀ㄖ娇赡軟](méi)有接收到通知,此時(shí)要有一定的機(jī)制對(duì)消息重復(fù)通知
  2. 消息校對(duì)機(jī)制。如果盡最大努力也沒(méi)有通知到接收方,或者接收方消費(fèi)消息后要再次消費(fèi),此時(shí)可由接收方主動(dòng)向通知方查詢消息信息來(lái)滿足需求。

最大努力通知與可靠消息一致性有什么不同?

解決方案思想不同

可靠消息一致性,發(fā)起通知方需要保證將消息發(fā)出去,并且將消息發(fā)到接收通知方,消息的可靠性關(guān)鍵由發(fā)起通知方來(lái)保證。最大努力通知,發(fā)起通知方盡最大的努力將業(yè)務(wù)處理結(jié)果通知為接收通知方,但是可能消息接收不到,此時(shí)需要接收通知方主動(dòng)調(diào)用發(fā)起通知方的接口查詢業(yè)務(wù)處理結(jié)果,通知的可靠性關(guān)鍵在接收通知方。

兩者的業(yè)務(wù)應(yīng)用場(chǎng)景不同

可靠消息一致性關(guān)注的是交易過(guò)程的事務(wù)一致,以異步的方式完成交易。最大努力通知關(guān)注的是交易后的通知事務(wù),即將交易結(jié)果可靠的通知出去。

技術(shù)解決方向不同

可靠消息一致性要解決消息從發(fā)出到接收的一致性,即消息發(fā)出并且被接收到。最大努力通知無(wú)法保證消息從發(fā)出到接收的一致性,只提供消息接收的可靠性機(jī)制。可靠機(jī)制是,最大努力的將消息通知給接收方,當(dāng)消息無(wú)法被接收方接收時(shí),由接收方主動(dòng)查詢消息(業(yè)務(wù)處理結(jié)果)

解決方案

通過(guò)對(duì)最大努力通知的理解,采用 MQ 的 ack 機(jī)制就可以實(shí)現(xiàn)最大努力通知。

方案1:
java分布式事務(wù),分布式,java,分布式,數(shù)據(jù)庫(kù)
本方案是利用 MQ 的 ack 機(jī)制由 MQ 向接收通知方發(fā)送通知,流程如下:

  • 發(fā)起通知方將通知發(fā)給 MQ。使用普通消息機(jī)制將通知發(fā)給MQ。
    注意:如果消息沒(méi)有發(fā)出去可由接收通知方主動(dòng)請(qǐng)求發(fā)起通知方查詢業(yè)務(wù)執(zhí)行結(jié)果。(后邊會(huì)講)

  • 接收通知方監(jiān)聽(tīng) MQ。

  • 接收通知方接收消息,業(yè)務(wù)處理完成回應(yīng) ack。

  • 接收通知方若沒(méi)有回應(yīng) ack 則 MQ 會(huì)重復(fù)通知。
    MQ會(huì)按照間隔 1min、5min、10min、30min、1h、2h、5h、10h的方式,逐步拉大通知間隔,直到達(dá)到通知要求的時(shí)間窗口上限。

  • 接收通知方可通過(guò)消息校對(duì)接口來(lái)校對(duì)消息的一致性。
    方案 2:
    java分布式事務(wù),分布式,java,分布式,數(shù)據(jù)庫(kù)
    交互流程如下:

  • 發(fā)起通知方將消息發(fā)給 MQ。
    使用可靠消息一致方案中的事務(wù)消息保證本地事務(wù)和消息的原子性,最終將通知先發(fā)給 MQ。

  • 通知程序監(jiān)聽(tīng) MQ,接收 MQ 的消息。
    方案 1 中接收通知方直接監(jiān)聽(tīng) MQ,方案 2 中由通知程序監(jiān)聽(tīng) MQ。

  • 通知程序若沒(méi)有回應(yīng) ack 則 MQ 會(huì)重復(fù)通知。
    通知程序通過(guò)互聯(lián)網(wǎng)接口協(xié)議(如 http、webservice)調(diào)用接收通知方案接口,完成通知。
    通知程序調(diào)用接收通知方案接口成功就表示通知成功,即消費(fèi) MQ 消息成功,MQ 將不再向通知程序投遞通知消息。

  • 接收通知方可通過(guò)消息校對(duì)接口來(lái)校對(duì)消息的一致性。

方案1和方案2的不同點(diǎn):

  • 方案 1 中接收通知方與 MQ 接口,即接收通知方案監(jiān)聽(tīng) MQ,此方案主要應(yīng)用與內(nèi)部應(yīng)用之間的通知。
  • 方案 2 中由通知程序與 MQ 接口,通知程序監(jiān)聽(tīng) MQ,收到 MQ 的消息后由通知程序通過(guò)互聯(lián)網(wǎng)接口協(xié)議調(diào)用接收通知方。此方案主要應(yīng)用于外部應(yīng)用之間的通知,例如支付寶、微信的支付結(jié)果通知。

小結(jié)

最大努力通知方案是分布式事務(wù)中對(duì)一致性要求最低的一種,適用于一些最終一致性時(shí)間敏感度低的業(yè)務(wù);最大努力通知方案需要實(shí)現(xiàn)如下功能:

  • 消息重復(fù)通知機(jī)制
  • 消息校對(duì)機(jī)制

分布式事務(wù)對(duì)比分析

2PC 最大的詬病是一個(gè)阻塞協(xié)議。RM 在執(zhí)行分支事務(wù)后需要等待 TM 的決定,此時(shí)服務(wù)會(huì)阻塞并鎖定資源。由于其阻塞機(jī)制和最差時(shí)間復(fù)雜度高,因此,這種設(shè)計(jì)不能適應(yīng)隨著事務(wù)涉及的服務(wù)數(shù)量增加而擴(kuò)展的需要,很難用于并發(fā)較高以及子事務(wù)生命周期較長(zhǎng)(long-running transactions) 的分布式服務(wù)中。

如果拿TCC事務(wù)的處理流程與2PC兩階段提交做比較,2PC 通常都是在跨庫(kù)的 DB 層面,而 TCC 則在應(yīng)用層面的處理,需要通過(guò)業(yè)務(wù)邏輯來(lái)實(shí)現(xiàn)。這種分布式事務(wù)的實(shí)現(xiàn)方式的優(yōu)勢(shì)在于,可以讓應(yīng)用自己定義數(shù)據(jù)操作的粒度,使得降低鎖沖突、提高吞吐量成為可能。而不足之處則在于對(duì)應(yīng)用的侵入性非常強(qiáng),業(yè)務(wù)邏輯的每個(gè)分支都需要實(shí)現(xiàn) Try、Con?rm、Cancel 三個(gè)操作。此外,其實(shí)現(xiàn)難度也比較大,需要按照網(wǎng)絡(luò)狀態(tài)、系統(tǒng)故障等不同的失敗原因?qū)?現(xiàn)不同的回滾策略。典型的使用場(chǎng)景:滿減,登錄送優(yōu)惠券等。

可靠消息最終一致性事務(wù)適合執(zhí)行周期長(zhǎng)且實(shí)時(shí)性要求不高的場(chǎng)景。引入消息機(jī)制后,同步的事務(wù)操作變?yōu)榛谙?zhí)行的異步操作, 避免了分布式事務(wù)中的同步阻塞操作的影響,并實(shí)現(xiàn)了兩個(gè)服務(wù)的解耦。典型的使用場(chǎng)景:注冊(cè)送積分,登錄送優(yōu)惠券等。

最大努力通知是分布式事務(wù)中要求最低的一種,適用于一些最終一致性時(shí)間敏感度低的業(yè)務(wù);允許發(fā)起通知方處理業(yè)務(wù)失敗,在接收通知方收到通知后積極進(jìn)行失敗處理,無(wú)論發(fā)起通知方如何處理結(jié)果都會(huì)不影響到接收通知方的后續(xù)處理;發(fā)起通知方需提供查詢執(zhí)行情況接口,用于接收通知方校對(duì)結(jié)果。典型的使用場(chǎng)景:銀行通知、支付結(jié)果通知等。

2PC TCC 可靠消息 最大努力通知
一致性 強(qiáng)一致性 最終一致性 最終一致性 最終一致性
吞吐量
實(shí)現(xiàn)復(fù)雜度

總結(jié)

以上講了什么是分布式事務(wù)以及它的應(yīng)用場(chǎng)景、如何進(jìn)行分布式控制最后講了分布式事務(wù)一致性的四種種解決方案以及對(duì)比分析。

在條件允許的情況下,我們盡可能選擇本地事務(wù)單數(shù)據(jù)源,因?yàn)樗鼫p少了網(wǎng)絡(luò)交互帶來(lái)的性能損耗,且避免了數(shù)據(jù)弱一致性帶來(lái)的種種問(wèn)題。若某系統(tǒng)頻繁且不合理的使用分布式事務(wù),應(yīng)首先從整體設(shè)計(jì)角度觀察服務(wù)的拆分是否合理,是否高內(nèi)聚低耦合?是否粒度太?。糠植际绞聞?wù)一直是業(yè)界難題,因?yàn)榫W(wǎng)絡(luò)的不確定性,而且我們習(xí)慣于拿分布式事務(wù)與單機(jī)事務(wù) ACID 做對(duì)比。

無(wú)論是數(shù)據(jù)庫(kù)層的 XA、還是應(yīng)用層 TCC、可靠消息、最大努力通知等方案,都沒(méi)有完美解決分布式事務(wù)問(wèn)題,它們不過(guò)是各自在性能、一致性、可用性等方面做取舍,尋求某些場(chǎng)景偏好下的權(quán)衡。

分布式事務(wù)框架,在這些理論基礎(chǔ)上,都進(jìn)行了或多或少的修訂,也有不少創(chuàng)新。比如LCN框架(lock,confirm,notify),就抽象出了控制方和發(fā)起方的概念,感興趣的可以自行了解。

在互聯(lián)網(wǎng)公司中,由于高并發(fā)量的訴求,在實(shí)際應(yīng)用中,相對(duì)于強(qiáng)事務(wù),大家普遍選用軟事務(wù)進(jìn)行業(yè)務(wù)處理。使用最多的,就是TCC、SAGA、本地消息表等解決方案。SAGA應(yīng)對(duì)長(zhǎng)事務(wù)特別拿手,但隔離性稍差;TCC一直型好并發(fā)高,但需要較多編碼;本地消息表應(yīng)用場(chǎng)景有限,耦合業(yè)務(wù)不能復(fù)用。各種解決方案都有它的利弊,一定要結(jié)合使用場(chǎng)景進(jìn)行選擇。

在框架方面,阿里的seata(早些年叫fescar),已經(jīng)得到了廣泛應(yīng)用,XA、TCC、SAGA等模式都支持,如果你需要這方面的功能,可以集成嘗試一下??蓞⒖嘉覍懙奈恼拢篠pring Cloud Alibaba 實(shí)戰(zhàn) Seata文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-847902.html

到了這里,關(guān)于【分布式】java實(shí)現(xiàn)分布式事務(wù)的五種方案的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 淺談分布式事務(wù)及解決方案

    在講述分布式事務(wù)的概念之前,我們先來(lái)回顧下事務(wù)相關(guān)的一些概念。 就是一個(gè)程序執(zhí)行單元,里面的操作要么全部執(zhí)行成功,要么全部執(zhí)行失敗,不允許只成功一半另外一半執(zhí)行失敗的事情發(fā)生。例如一段事務(wù)代碼做了兩次數(shù)據(jù)庫(kù)更新操作,那么這兩次數(shù)據(jù)庫(kù)操作要么全部

    2024年02月08日
    瀏覽(21)
  • 【Java】三種方案實(shí)現(xiàn) Redis 分布式鎖

    【Java】三種方案實(shí)現(xiàn) Redis 分布式鎖

    setnx、Redisson、RedLock 都可以實(shí)現(xiàn)分布式鎖,從易到難得排序?yàn)椋簊etnx Redisson RedLock。一般情況下,直接使用 Redisson 就可以啦,有很多邏輯框架的作者都已經(jīng)考慮到了。 1.1、簡(jiǎn)單實(shí)現(xiàn) 下面的鎖實(shí)現(xiàn)可以用在測(cè)試或者簡(jiǎn)單場(chǎng)景,但是它存在以下問(wèn)題,使其不適合用在正式環(huán)境。

    2024年02月05日
    瀏覽(25)
  • Apache Seata -- 一款開(kāi)源的分布式事務(wù)解決方案

    Apache Seata -- 一款開(kāi)源的分布式事務(wù)解決方案

    1.1?分布式事務(wù)簡(jiǎn)介 (1)事務(wù) 事務(wù)可以看做是一次大的活動(dòng),它由不同的小活動(dòng)組成,這些活動(dòng)要么全部成功,要么全部失敗。 (2)本地事務(wù) ? 在計(jì)算機(jī)系統(tǒng)中,更多的是通過(guò)關(guān)系型數(shù)據(jù)庫(kù)來(lái)控制事務(wù),這是利用數(shù)據(jù)庫(kù)本身的事務(wù)特性來(lái)實(shí)現(xiàn)的,因此叫數(shù)據(jù)庫(kù)事務(wù),由于

    2024年03月17日
    瀏覽(20)
  • Java分布式事務(wù)(十二)

    Java分布式事務(wù)(十二)

    創(chuàng)建父工程tx-tcc 設(shè)置邏輯工程 創(chuàng)建公共模塊 創(chuàng)建轉(zhuǎn)出銀行微服務(wù) 創(chuàng)建傳入銀行微服務(wù)

    2023年04月12日
    瀏覽(29)
  • 分布式事務(wù)解決方案Seata(1.6.1)下載與基礎(chǔ)配置

    分布式事務(wù)解決方案Seata(1.6.1)下載與基礎(chǔ)配置

    seata 是一款開(kāi)源的分布式事務(wù)解決方案,致力于提供高性能和簡(jiǎn)單易用的分布式事務(wù)服務(wù)。seata 將為用戶提供了 AT、TCC、SAGA 和 XA 事務(wù)模式,為用戶打造一站式的分布式解決方案。 基于支持本地 ACID 事務(wù)的關(guān)系型數(shù)據(jù)庫(kù)。 Java 應(yīng)用,通過(guò) JDBC 訪問(wèn)數(shù)據(jù)庫(kù)。 兩階段提交協(xié)議的

    2023年04月12日
    瀏覽(24)
  • springcloud3 分布式事務(wù)解決方案seata之AT模式5

    springcloud3 分布式事務(wù)解決方案seata之AT模式5

    1.XA模式一階段不提交事務(wù),鎖定資源;AT模式一階段直接提交,不鎖定資源; 2.XA模式依賴數(shù)據(jù)庫(kù)機(jī)制實(shí)現(xiàn)回滾;AT模式利用數(shù)據(jù)庫(kù)快照實(shí)現(xiàn)數(shù)據(jù)回滾 3.XA模式強(qiáng)一致;AT模式最終一致。 1.2 AT模式原理 一階段: 1.TM發(fā)起并注冊(cè)全局事務(wù)到TC; 2.TM調(diào)用分支事務(wù); 3.RM進(jìn)行注冊(cè)分支

    2024年02月07日
    瀏覽(31)
  • 基于RocketMQ實(shí)現(xiàn)分布式事務(wù)

    基于RocketMQ實(shí)現(xiàn)分布式事務(wù)

    在一個(gè)微服務(wù)架構(gòu)的項(xiàng)目中,一個(gè)業(yè)務(wù)操作可能涉及到多個(gè)服務(wù),這些服務(wù)往往是獨(dú)立部署,構(gòu)成一個(gè)個(gè)獨(dú)立的系統(tǒng)。這種分布式的系統(tǒng)架構(gòu)往往面臨著分布式事務(wù)的問(wèn)題。為了保證系統(tǒng)數(shù)據(jù)的一致性,我們需要確保這些服務(wù)中的操作要么全部成功,要么全部失敗。通過(guò)使用

    2024年03月12日
    瀏覽(20)
  • SpringCloud Alibaba - Seata 四種分布式事務(wù)解決方案(XA、AT)+ 實(shí)踐部署(上)

    SpringCloud Alibaba - Seata 四種分布式事務(wù)解決方案(XA、AT)+ 實(shí)踐部署(上)

    目錄 一、Seata 分布式事務(wù)解決方案 1.1、XA 模式 1.1.1、XA模式理論 第一階段: 第二階段: 1.1.2、Seata 框架中的 XA 模式 第一階段: 第二階段: 1.1.3、XA 模式的優(yōu)缺點(diǎn) 1.2.4、實(shí)現(xiàn)Seata 的?XA 模式 a)修改 application 文件(每一個(gè)參與事務(wù)的微服務(wù)) b)給發(fā)起全局事務(wù)中的入口方法

    2024年04月14日
    瀏覽(19)
  • 【項(xiàng)目亮點(diǎn)】大廠中分布式事務(wù)的最佳實(shí)踐 問(wèn)題產(chǎn)生->難點(diǎn)與權(quán)衡(偏愛(ài)Saga)->解決方案

    【項(xiàng)目亮點(diǎn)】大廠中分布式事務(wù)的最佳實(shí)踐 問(wèn)題產(chǎn)生->難點(diǎn)與權(quán)衡(偏愛(ài)Saga)->解決方案

    不斷有同學(xué)問(wèn)我大廠中實(shí)踐分布式事務(wù)的問(wèn)題,這里從 分布式事務(wù)的產(chǎn)生 ,到 強(qiáng)弱一致性與性能的權(quán)衡 ,再到最終 落地的解決方案 ,再到 實(shí)際的代碼實(shí)現(xiàn) ,再到我工作中實(shí)際 使用SAGA模式的應(yīng)用案例 ,一篇文章講清楚. 83.7%分布式事務(wù)的產(chǎn)生都是因?yàn)椴鸱治⒎?wù)導(dǎo)致 的: 一句話概

    2024年04月27日
    瀏覽(25)
  • RocketMQ分布式事務(wù) -> 最終一致性實(shí)現(xiàn)

    RocketMQ分布式事務(wù) -> 最終一致性實(shí)現(xiàn)

    · 分布式事務(wù)的問(wèn)題常在業(yè)務(wù)與面試中被提及, 近日摸魚看到這篇文章, 闡述的非常通俗易懂, 固持久化下來(lái)我博客中, 也以便于我二刷 轉(zhuǎn)載源 : 基于RocketMQ分布式事務(wù) - 完整示例 本文代碼不只是簡(jiǎn)單的demo,考慮到一些異常情況、冪等性消費(fèi)和死信隊(duì)列等情況,盡量向可靠業(yè)務(wù)

    2024年02月15日
    瀏覽(29)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包