自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

詳細講解一下分布式事務(wù)-兩階段提交的實現(xiàn)原理

云計算 分布式
Seata(Simple Extensible Autonomous Transaction Architecture)是一款開源的分布式事務(wù)解決方案,提供了AT、TCC、SAGA和XA四種事務(wù)模式。其中,AT(Auto Transaction)模式是基于兩階段提交協(xié)議改進而來,通過數(shù)據(jù)源代理和全局鎖機制實現(xiàn)了對業(yè)務(wù)代碼幾乎零侵入的分布式事務(wù)支持。

一、為什么需要分布式事務(wù)

隨著微服務(wù)架構(gòu)和分布式系統(tǒng)的普及,一個業(yè)務(wù)操作往往需要調(diào)用多個服務(wù),修改多個數(shù)據(jù)源的數(shù)據(jù)。例如:

  • 電商系統(tǒng)中的下單操作:需要扣減庫存、創(chuàng)建訂單、支付等多個操作
  • 銀行轉(zhuǎn)賬操作:需要從一個賬戶扣款,另一個賬戶加款

這些操作需要作為一個整體要么全部成功,要么全部失敗,這就需要分布式事務(wù)來保證。

二、兩階段提交(2PC) 原理

兩階段提交(Two-Phase Commit,簡稱2PC)是分布式系統(tǒng)中實現(xiàn)分布式事務(wù)的經(jīng)典算法。它將事務(wù)的提交過程分為兩個階段:

  1. 準備階段(Prepare Phase):協(xié)調(diào)者詢問所有參與者是否可以提交
  2. 提交/回滾階段(Commit/Rollback Phase):根據(jù)準備階段的結(jié)果決定提交或回滾

角色劃分:

  • 協(xié)調(diào)者(Coordinator):事務(wù)的發(fā)起者,負責協(xié)調(diào)所有參與者
  • 參與者(Participant/Cohort):事務(wù)的實際執(zhí)行者,負責本地事務(wù)的執(zhí)行

兩階段提交流程:

(1)準備階段

  • 協(xié)調(diào)者向所有參與者發(fā)送prepare請求
  • 參與者執(zhí)行本地事務(wù)但不提交,記錄undo/redo日志
  • 參與者向協(xié)調(diào)者反饋響應(yīng):

成功:返回"同意"

失敗:返回"中止"

(2)提交/回滾階段

情況1:所有參與者都返回"同意"

  • 協(xié)調(diào)者向所有參與者發(fā)送commit請求
  • 參與者完成本地事務(wù)提交
  • 參與者向協(xié)調(diào)者發(fā)送ack響應(yīng)
  • 協(xié)調(diào)者收到所有ack后完成事務(wù)

情況2:任一參與者返回"中止"或超時

  • 協(xié)調(diào)者向所有參與者發(fā)送rollback請求
  • 參與者利用undo日志回滾本地事務(wù)
  • 參與者向協(xié)調(diào)者發(fā)送ack響應(yīng)
  • 協(xié)調(diào)者收到所有ack后中斷事務(wù)

三、基本實現(xiàn)示例

首先定義協(xié)調(diào)者和參與者的接口:

public interface Coordinator {
    void startTransaction(List<Participant> participants);
    boolean prepare();
    void commit();
    void rollback();
}


public interface Participant {
    boolean prepare();
    void commit();
    void rollback();
}

參與都實現(xiàn)代碼:

public class DatabaseParticipant implements Participant {
    private Connection connection;
    private String transactionId;


    public DatabaseParticipant(Connection connection, String transactionId) {
        this.connection = connection;
        this.transactionId = transactionId;
    }


    @Override
    public boolean prepare() {
        try {
            // 設(shè)置不自動提交
            connection.setAutoCommit(false);


            // 執(zhí)行SQL但不提交
            // 這里應(yīng)該有實際的業(yè)務(wù)SQL,如:
            // PreparedStatement ps = connection.prepareStatement("UPDATE account SET balance = balance - 100 WHERE user_id = 1");
            // ps.executeUpdate();


            // 記錄redo/undo日志
            logRedoUndo();


            return true;
        } catch (SQLException e) {
            return false;
        }
    }


    @Override
    public void commit() {
        try {
            connection.commit();
            cleanRedoUndo();
        } catch (SQLException e) {
            // 處理異常
        }
    }


    @Override
    public void rollback() {
        try {
            connection.rollback();
            cleanRedoUndo();
        } catch (SQLException e) {
            // 處理異常
        }
    }


    private void logRedoUndo() {
        // 實現(xiàn)記錄redo/undo日志的邏輯
    }


    private void cleanRedoUndo() {
        // 清理日志
    }
}

協(xié)調(diào)者實現(xiàn)代碼:

public class TwoPhaseCommitCoordinator implements Coordinator {
    private List<Participant> participants;
    private String transactionId;


    public TwoPhaseCommitCoordinator(String transactionId) {
        this.transactionId = transactionId;
    }


    @Override
    public void startTransaction(List<Participant> participants) {
        this.participants = participants;
    }


    @Override
    public boolean prepare() {
        for (Participant participant : participants) {
            if (!participant.prepare()) {
                return false;
            }
        }
        return true;
    }


    @Override
    public void commit() {
        if (prepare()) {
            for (Participant participant : participants) {
                participant.commit();
            }
        } else {
            rollback();
        }
    }


    @Override
    public void rollback() {
        for (Participant participant : participants) {
            try {
                participant.rollback();
            } catch (Exception e) {
                // 記錄日志,繼續(xù)回滾其他參與者
            }
        }
    }
}

使用示例:

public class TwoPhaseCommitExample {
    public static void main(String[] args) {
        // 模擬兩個數(shù)據(jù)庫參與者
        Connection conn1 = getConnection(); // 獲取第一個數(shù)據(jù)庫連接
        Connection conn2 = getConnection(); // 獲取第二個數(shù)據(jù)庫連接


        Participant participant1 = new DatabaseParticipant(conn1, "tx123");
        Participant participant2 = new DatabaseParticipant(conn2, "tx123");


        Coordinator coordinator = new TwoPhaseCommitCoordinator("tx123");
        coordinator.startTransaction(Arrays.asList(participant1, participant2));


        try {
            coordinator.commit();
            System.out.println("事務(wù)提交成功");
        } catch (Exception e) {
            coordinator.rollback();
            System.out.println("事務(wù)回滾");
        }
    }


    private static Connection getConnection() {
        // 實際應(yīng)用中應(yīng)該從數(shù)據(jù)源獲取連接
        return null;
    }
}

四、Seata AT模式

Seata(Simple Extensible Autonomous Transaction Architecture)是一款開源的分布式事務(wù)解決方案,提供了AT、TCC、SAGA和XA四種事務(wù)模式。其中,AT(Auto Transaction)模式是基于兩階段提交協(xié)議改進而來,通過數(shù)據(jù)源代理和全局鎖機制實現(xiàn)了對業(yè)務(wù)代碼幾乎零侵入的分布式事務(wù)支持。

包含組件:

Transaction Coordinator (TC,事務(wù)協(xié)調(diào)器)

  • 獨立部署的服務(wù),維護全局事務(wù)和分支事務(wù)的狀態(tài)
  • 負責協(xié)調(diào)全局事務(wù)的提交或回滾
  • 管理全局鎖的獲取與釋放

Transaction Manager (TM,事務(wù)管理器)

  • 嵌入在應(yīng)用中,負責定義全局事務(wù)邊界
  • 通過@GlobalTransactional注解標記分布式事務(wù)方法
  • 向TC發(fā)起全局事務(wù)的開始、提交或回滾指令

Resource Manager (RM,資源管理器)

  • 管理分支事務(wù)上的資源
  • 向TC注冊分支事務(wù)并報告狀態(tài)
  • 驅(qū)動分支事務(wù)的提交或回滾
  • 負責生成和操作undo log

AT模式的整體流程:

(1)業(yè)務(wù)執(zhí)行與本地提交

  • 解析SQL:攔截業(yè)務(wù)SQL,解析SQL類型(INSERT/UPDATE/DELETE)、表、條件等信息
  • 查詢前鏡像:根據(jù)SQL條件查詢修改前的數(shù)據(jù)快照(before image)
  • 執(zhí)行業(yè)務(wù)SQL:執(zhí)行用戶的實際業(yè)務(wù)SQL
  • 查詢后鏡像:根據(jù)主鍵查詢修改后的數(shù)據(jù)快照(after image)
  • 插入回滾日志:將前后鏡像和業(yè)務(wù)SQL信息組成undo log記錄,插入到undo_log表
  • 注冊分支事務(wù):向TC注冊分支事務(wù)并獲取全局鎖
  • 提交本地事務(wù):業(yè)務(wù)SQL和undo log在同一個本地事務(wù)中提交
  • 上報執(zhí)行結(jié)果:將本地事務(wù)執(zhí)行結(jié)果上報給TC

(2)全局提交或回滾

全局提交:

  • TC異步通知各分支事務(wù)提交
  • RM異步刪除對應(yīng)的undo log記錄
  • 釋放全局鎖

全局回滾:

  • TC通知各分支事務(wù)回滾
  • RM根據(jù)undo log中的before image生成補償SQL并執(zhí)行
  • 校驗數(shù)據(jù)一致性(對比after image與當前數(shù)據(jù))
  • 刪除undo log記錄
  • 釋放全局鎖

Seata的詳細信息,請查看官網(wǎng):https://seata.apache.org/zh-cn/docs/dev/mode/at-mode

五、兩階段提交的問題

(1)協(xié)調(diào)者單點故障

如果在第二階段協(xié)調(diào)者宕機,部分參與者收到commit而部分沒收到,系統(tǒng)將處于不一致狀態(tài)。

解決方法:記錄事務(wù)日志,協(xié)調(diào)者恢復(fù)后能繼續(xù)處理。

(2)網(wǎng)絡(luò)分區(qū)

網(wǎng)絡(luò)分區(qū)可能導(dǎo)致部分參與者無法收到協(xié)調(diào)者的指令。

為了解決2PC的網(wǎng)絡(luò)阻塞問題,引入了3PC:

  • CanCommit階段:詢問參與者是否可以提交
  • PreCommit階段:預(yù)提交,執(zhí)行事務(wù)但不提交
  • DoCommit階段:實際提交

3PC通過引入超時機制減少了阻塞,但增加了復(fù)雜度。

責任編輯:武曉燕 來源: 全棧程序員老馬
相關(guān)推薦

2023-07-26 09:24:03

分布式事務(wù)分布式系統(tǒng)

2024-01-26 08:18:03

2018-10-29 08:44:29

分布式兩階段提交事務(wù)

2024-05-21 14:12:07

2022-12-21 19:04:35

InnoDBMySQL

2010-04-22 15:11:14

2024-03-26 16:24:46

分布式事務(wù)2PC3PC

2023-12-05 09:33:08

分布式事務(wù)

2022-06-21 08:27:22

Seata分布式事務(wù)

2022-06-27 08:21:05

Seata分布式事務(wù)微服務(wù)

2023-11-29 07:47:58

DDIA兩階段提交

2022-03-28 10:44:51

MySQL日志存儲

2023-12-26 08:59:52

分布式場景事務(wù)機制

2019-08-19 10:24:33

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

2023-10-24 08:25:20

TCC模式事務(wù)

2024-11-28 15:11:28

2021-03-17 00:05:50

分布式事務(wù)提交

2022-07-10 20:24:48

Seata分布式事務(wù)

2024-01-26 13:17:00

rollbackMQ訂單系統(tǒng)

2025-01-06 09:32:26

點贊
收藏

51CTO技術(shù)棧公眾號