分散式事務解決方案彙總

威兰达發表於2024-06-13
2階段(2PC)提交方案:
實現原理:基於XA規範搞的一套分散式事務的理論,也可以叫做一套規範,或者是協議。
(1)準備階段(Prepare phase):事務管理器給每個參與者傳送prepare訊息,每個資料庫參與者在本地執行事務,並寫本地的Undo/Redo,此時事務沒有提交。
(2)提交階段(Commit phase):如果事務管理器接收了參與者執行失敗或者超時訊息時,直接給每個參與者傳送回滾訊息,
否則傳送提交訊息;參與者根據事務管理器的指令執行提交或者回滾操作,並釋放事務處理過程中使用的鎖資源。
程式碼實現參考:
public static void main(String[] args) throws SQLException, XAException {

        // 獲得資源管理器操作介面例項 RM1
        Connection conn1 = DriverManager.getConnection("jdbc:mysql://localhost:3306/dev", "root", "123456");
        XAConnection xaConn1 = new MysqlXAConnection((JdbcConnection) conn1, true);
        XAResource db1 = xaConn1.getXAResource();

        // 獲得資源管理器操作介面例項 RM2
        Connection conn2 = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2", "root", "123456");
        XAConnection xaConn2 = new MysqlXAConnection((JdbcConnection) conn2, true);
        XAResource db2 = xaConn2.getXAResource();
        // 應用程式 請求事務管理器 執行一個分散式事務,事務管理器 生成全域性事務id
        byte[] gtrid = "g12345".getBytes();
        Xid id1 = new MysqlXid(gtrid, "b00001".getBytes(), 1); // 事務管理器生成 db1上的事務分支id
        Xid id2 = new MysqlXid(gtrid, "b00002".getBytes(), 1); // 事務管理器生成db2上的事務分支id

        try {
            // 執行db1上的事務分支
            db1.start(id1, XAResource.TMNOFLAGS);
            PreparedStatement ps1 = conn1.prepareStatement("INSERT into user_info(user_id, user_name) VALUES ('5', 'test')");
            ps1.execute();
            db1.end(id1, XAResource.TMSUCCESS);

            // 執行db2上的事務分支
            db2.start(id2, XAResource.TMNOFLAGS);
            PreparedStatement ps2 = conn2.prepareStatement("INSERT into accounts(userId, accountNumber) VALUES (2, 10000)");
            ps2.execute();
            db2.end(id2, XAResource.TMSUCCESS);

            // 準備兩階段提交  phase1:詢問所有的RM 準備提交事務分支
            int rm1Prepare = db1.prepare(id1);
            int rm2Prepare = db2.prepare(id2);

            //提交所有事務分支, TM判斷有2個事務分支,所以不能最佳化為一階段提交
            if (rm1Prepare == XAResource.XA_OK && rm2Prepare == XAResource.XA_OK) {
                db1.commit(id1, false);
                db2.commit(id2, false);
                System.out.println("成功");
            } else {
                System.out.println("如果有事務分支沒有成功,則回滾");
                db1.rollback(id1);
                db2.rollback(id2);
            }
            int a = 1/0;
        } catch (Exception e) {
            e.printStackTrace();
            db1.rollback(id1);
            db2.rollback(id2);
            System.out.println("異常error");
        }
    }
1.最好pom引入開源的分散式事務管理器,如Atomikos作為本地事務管理器。如:Spring Boot整合atomikos快速入門Demo
2.在分散式環境中,每個服務配置 Atomikos 作為本地事務管理器,但是全域性事務的管理和協調是由一個獨立的分散式事務協調器(DTC)來完成。
3.在分散式環境中,獨立的分散式事務協調器(DTC)通常是一個單獨的服務或元件。通常情況下,專案除了引入 Atomikos 作為本地事務管理器之外,還需要考慮如何部署和配置這個分散式事務協調器。
4.在分散式環境中,確保分散式事務的一致性和可靠性需要配合使用本地事務管理器(如 Atomikos)和一個獨立的分散式事務協調器(DTC)。

相關文章