# XaTransactionLab **Repository Path**: ymjake/xa-transaction-lab ## Basic Information - **Project Name**: XaTransactionLab - **Description**: 基于ASP.NET Core的XA/XTA分布式事务实验项目 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-09 - **Last Updated**: 2026-05-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: XA ## README # XaTransactionLab 这是一个围绕中心 `TM` 构建的分布式 XA / 2PC 实验项目,当前包含两个自管理 participant: - `OrdersApi`:管理自己的 MySQL XA branch - `BillingApi`:管理自己的 PostgreSQL prepared transaction branch - `TM Server`:持久化全局决策状态,并在重启后执行 recovery replay 当前实现更接近 `LIXA/XTA` 的 participant 语义: - 每个服务自己管理本地 branch - `BillingApi` 会 self-register 到 `TM` - 业务 SQL 在业务请求阶段执行 - `PrepareBranch` 只负责找回挂起 branch 并执行本地 prepare - 崩溃恢复依赖 RM 原生状态 ## 架构 ```text Client HTTP ↓ OrdersApi HTTP ↓ BillingApi OrdersApi ───────┐ BillingApi ──────┼── gRPC Register / Prepare / Commit / Rollback ↓ TM Server ``` ## 角色说明 - `OrdersApi` - HTTP checkout 入口 - 全局事务发起方 - 本地 MySQL XA participant - `BillingApi` - billing 业务 HTTP 接口 - 本地 PostgreSQL participant - 在业务阶段 self-register 到 `TM` - `TM Server` - 全局事务状态存储 - participant registry - prepare / commit / rollback 编排 - 重启恢复 worker ## 端口 - `TM Server`:`http://localhost:5180` - `OrdersApi` HTTP:`http://localhost:5181` - `OrdersApi` gRPC participant:`http://localhost:5281` - `BillingApi` gRPC participant:`http://localhost:5182` - `BillingApi` HTTP:`http://localhost:5183` ## 当前事务流 ### 正常提交路径 1. `Client -> OrdersApi` - `POST /api/xta/checkout` 2. `OrdersApi -> TM` - `BeginTransaction(rootXid)` 3. `OrdersApi` - 打开 MySQL 连接 - `XA START` - 执行订单业务 SQL - 用显式 `branchXid` 注册 `orders-service` - 将活跃 branch 挂入 pending registry 4. `OrdersApi -> BillingApi` - `POST /api/billing/charge` - 透传 `rootXid` 5. `BillingApi` - 打开 PostgreSQL 连接 - `BEGIN` - 执行 billing 业务 SQL - 用显式 `branchXid` 注册 `billing-service` - 将活跃 branch 挂入 pending registry 6. `OrdersApi -> TM` - `PrepareTransaction(rootXid)` 7. `TM -> OrdersApi participant` - `PrepareBranch(ordersBranchXid)` - `XA END` - `XA PREPARE` 8. `TM -> BillingApi participant` - `PrepareBranch(billingBranchXid)` - `PREPARE TRANSACTION` 9. `TM` - 持久化全局决策,写入 `WillCommit = true` 10. `OrdersApi -> TM` - `CommitTransaction(rootXid)` 11. `TM -> OrdersApi participant` - `XA COMMIT` 12. `TM -> BillingApi participant` - `COMMIT PREPARED` ### 回滚路径 如果任一 participant 在业务阶段或 prepare 阶段失败: - `TM` 持久化 `WillRollback = true` - 尚未 prepare 的 branch 从 pending 内存上下文直接回滚 - 已经 prepare 的 branch 从 RM 原生状态回滚: - MySQL:`XA ROLLBACK` - PostgreSQL:`ROLLBACK PREPARED` ### 恢复路径 `TM` 重启后,recovery worker 会扫描持久化事务状态,并继续回放: - `Prepared` - `Committing` - `RollingBack` - 部分已知 intent 的 `Failed` participant 侧恢复依赖 RM 原生状态: - `OrdersApi`:`XA RECOVER` - `BillingApi`:`pg_prepared_xacts` 这意味着: - `prepare` 前崩溃,只会丢失挂起中的内存 branch - `prepare` 后崩溃,仍然可以依赖 RM 原生状态完成恢复 ## TM 持久化状态 `TM` 的事务状态保存在: - `Xa.Transaction.Manager.Grpc/bin/Debug/net8.0/tm-transactions.json` - `Xa.Transaction.Manager.Grpc/bin/Debug/net8.0/tm-transactions.json.log.jsonl` 当前存储结构包含: - snapshot 文件 - append-only JSONL 日志 - 启动时 replay - checkpoint 压缩 持久化内容包括: - `rootXid` - 事务状态 - `WillCommit / WillRollback` - participant 注册信息 - participant branch XID ## Pending Branch 基础设施 共享的 pending-branch 基础设施现在位于 `Xa.Transaction`: - `PendingXaBranchContext` - `PendingXaBranchRegistry` - `PendingXaBranchOptions` - `PendingXaBranchCleanupWorkerBase` `OrdersApi` 和 `BillingApi` 只保留薄包装,用来处理: - 具体资源类型 - 回滚方式 - worker / service 注入 ## 资源管理器语义 ### MySQL - `XA START` - `XA END` - `XA PREPARE` - `XA COMMIT` - `XA ROLLBACK` - `XA RECOVER` ### PostgreSQL - `BEGIN` - `PREPARE TRANSACTION` - `COMMIT PREPARED` - `ROLLBACK PREPARED` - `pg_prepared_xacts` ## 已验证场景 当前版本已经完成这些验证: 1. happy path - `checkout -> Committed` 2. prepare failure - `failBillingPrepare = true` - 整笔事务回滚 3. 单 participant `prepare` 前崩溃 - 进程重启后挂起 branch 消失 - `TM` prepare 失败并完成回滚 4. 单 participant `prepare` 后崩溃 - PG prepared branch 在崩溃后保留 - `TM recovery worker` 在 participant 重启后完成 rollback 5. 双 participant `prepare` 后崩溃 - `Orders` 先被同步回滚 - `Billing` 保留 `RollbackRequested` 和 PG prepared branch - `BillingApi` 重启后,recovery replay 清理 TM 状态和 RM 状态 6. 共享 pending 基础设施回归 - 将公共抽象提到 `Xa.Transaction` 后 - happy path 仍然正常提交 更完整的验证记录见: - [docs/lixa-xta-refactor-plan.md](./docs/lixa-xta-refactor-plan.md) ## 启动顺序 先启动数据库环境: ```powershell docker compose -f docker/docker-compose.yml up -d ``` 然后按顺序启动服务: ```powershell dotnet run --project .\Xa.Transaction.Manager.Grpc\Xa.Transaction.Manager.Grpc.csproj dotnet run --project .\Xa.Transaction.BillingApi\Xa.Transaction.BillingApi.csproj dotnet run --project .\Xa.Transaction.OrdersApi\Xa.Transaction.OrdersApi.csproj ``` ## 主要接口 ### OrdersApi - `POST /api/xta/checkout` - `GET /api/xta/status?xid=...` - `GET /api/xta/recovery/pending` - `POST /api/xta/recover?xid=...&decision=...` ### BillingApi - `POST /api/billing/charge` ## Docker 测试环境 见: - [docker/README.md](./docker/README.md) 默认连接: - MySQL:`127.0.0.1:3306` - PostgreSQL:`127.0.0.1:5432` ## 说明 - 这个项目仍然是实验 / 演示性质,不是生产级事务管理器。 - `OrdersApi` 目前仍然承担中心式业务入口的角色。 - participant 侧已经明显更接近 `LIXA/XTA`: - self-managed branch lifecycle - 显式 branch XID - prepare 前挂起本地 branch - 重启后基于 RM 原生状态恢复