Order Transactions
- Whether inventory is deducted before or after, it will affect both inventory and orders, so distributed transactions must be used.
- Business (order placed but not paid) business problem.
- Deduct inventory after successful payment (order placed, but out of stock at payment time).
- Order deduction, no payment (order timeout and return) [common method].
Transactions and Distributed Transactions
1. What is a Transaction?
A transaction is an important concept in database management systems. It is a collection of database operations that are either all successfully executed or all rolled back upon failure.
1.1 ACID Properties of Transactions
- Atomicity: All operations within a transaction either succeed completely or fail completely; there is no partial success.
- Consistency: A transaction transforms the database from one consistent state to another consistent state before and after its execution.
- Isolation: Concurrent transactions are isolated from each other; the execution of one transaction should not affect other transactions.
- Durability: Once a transaction is committed, its results are permanently stored in the database.
1.2 Transaction Isolation Levels
- Read Uncommitted: The lowest level, may read dirty data.
- Read Committed: Can only read committed data.
- Repeatable Read: Multiple reads within the same transaction yield consistent results.
- Serializable: The highest level, transactions are executed completely serially.
2. What is a Distributed Transaction?
A distributed transaction refers to transaction operations involving multiple databases or services, requiring data consistency across multiple nodes.
2.1 Challenges of Distributed Transactions
- Network Partition: Network failures lead to communication interruptions between nodes.
- Node Failure: A node crashes or restarts.
- Clock Skew: Inconsistent times across different nodes.
- Data Consistency: How to ensure data consistency across nodes.
2.2 CAP Theorem
- Consistency: All nodes see the same data at the same time (after an update returns to the client).
- Availability: The system remains continuously available and operations do not fail.
- Partition Tolerance: The system can tolerate network partition failures.
CAP Theorem: In a distributed system, it is impossible to simultaneously satisfy all three of Consistency, Availability, and Partition Tolerance.
2.3 BASE Theory (Engineering Trade-offs with CAP)
- Basically Available: In the event of a failure, the system is allowed to degrade and provide limited functionality (e.g., slower response, partial unavailability).
- Soft state: The system state is allowed to exist in an intermediate state for a period of time (not strongly consistent).
- Eventual consistency: Data eventually reaches consistency after a period of time (or through retries/compensations).
In engineering practice: most internet businesses choose AP → guided by BASE theory, sacrificing strong consistency for high availability and scalability, achieving eventual consistency through "compensation, retries, deduplication, and reconciliation".
3. Distributed Transaction Solutions
3.1 Two-Phase Commit (2PC)
Principle:
- Prepare Phase: The coordinator asks all participants if they can commit.
- Commit Phase: Decides to commit or roll back based on participant responses.
Advantages: Strong consistency
Disadvantages: Poor performance, single point of failure, blocking issues
Detailed Process (示意):
- The coordinator sends a
preparerequest to participants. Each participant reserves resources, writes pre-commit logs, and returns yes/no. - The coordinator aggregates: all yes → sends
commit; any no/timeout → sendsrollback. - Participants commit or roll back according to the instruction and acknowledge the coordinator.
Common issues: single point of failure for the coordinator, participant blocking (holding locks for a long time), complex recovery during network partitions.
sequenceDiagram
participant C as 协调者(Coordinator)
participant P1 as 参与者1
participant P2 as 参与者2
C->>P1: prepare
C->>P2: prepare
P1-->>C: yes/预提交成功
P2-->>C: yes/预提交成功
alt 全部yes
C->>P1: commit
C->>P2: commit
P1-->>C: ack
P2-->>C: ack
else 任一no/超时
C->>P1: rollback
C->>P2: rollback
end
3.2 Three-Phase Commit (3PC)
Adds a pre-commit phase on top of 2PC to reduce blocking time, but still suffers from single point of failure issues.
3.3 TCC (Try-Confirm-Cancel)
Principle:
- Try: Attempt to execute business, reserve resources.
- Confirm: Confirm business execution, commit resources.
- Cancel: Cancel business execution, release resources.
Advantages: Good performance, non-blocking
Disadvantages: Complex implementation, requires business compensation
Key Implementation Points (taking order-inventory-payment as an example):
- Try: Create order pre-status, pre-occupy inventory (deduct available inventory, increase pre-occupied inventory), pre-order payment.
- Confirm (payment success callback or asynchronous confirmation): Order status changes to paid, inventory moves from pre-occupied to formally deducted.
- Cancel (payment failure/timeout): Order cancelled, pre-occupied inventory released.
Implementation details: idempotent interfaces (deduplication table/unique business key), handling null rollback/hanging, transaction log recording and retry tasks.
sequenceDiagram
participant Order as 订单服务
participant Inv as 库存服务
participant Pay as 支付服务
rect rgb(230,250,230)
Note over Order,Inv: Try 阶段(预留资源)
Order->>Inv: Try 预占库存
Order->>Pay: Try 预下单/冻结
end
alt 支付成功
rect rgb(230,230,255)
Note over Order,Inv: Confirm 阶段
Pay-->>Order: 支付成功回调
Order->>Inv: Confirm 扣减库存
Order->>Pay: Confirm 确认扣款
end
else 失败/超时
rect rgb(255,230,230)
Note over Order,Inv: Cancel 阶段
Order->>Inv: Cancel 释放预占
Order->>Pay: Cancel 解冻/撤销
end
end
3.4 Message-Based Eventual Consistency
Principle:
- Execute local transaction.
- Send message to message queue.
- Consumer processes message, ensuring eventual consistency.
Advantages: Good performance, relatively simple implementation
Disadvantages: Only guarantees eventual consistency
3.4.1 Local Message Table (Outbox Pattern)
Process: Write business data and outbox message table within the same local transaction → background forwarder polls and delivers to MQ → consumer processes and persists to database → sends confirmation/reconciliation.
Key points:
- Strong consistency on the producer side (business + message in the same database transaction)
- Idempotent forwarding (deliver by message ID, consumer deduplication)
- Failure retry and dead-letter queue, manual reconciliation and repair
flowchart LR
A[应用/业务服务] -->|同库同事务| B[(业务表 + Outbox表)]
B -->|后台转发器扫描/拉取| MQ[消息队列]
MQ --> C[下游服务]
C --> D[(消费落库/去重表)]
subgraph 重试与对账
E[失败重投/死信队列]
F[对账/人工修复]
end
MQ --> E
E --> F
3.4.2 Reliable Message-Based Eventual Consistency (Common)
Process:
- The business requests a "prepare message/half message" from MQ.
- After the local business commit is successful, it calls MQ to confirm (commit), otherwise it rolls back.
- MQ suspends unconfirmed half messages and queries (check) the business's final status to decide whether to commit or discard.
Key points:
- Relies on MQ's transaction message/callback capabilities (RocketMQ, etc.)
- Both producer and consumer sides need idempotent processing.
sequenceDiagram
participant Biz as 业务服务
participant MQ as MQ(事务消息)
participant D as 下游服务
Biz->>MQ: 发送半消息(Prepare)
Biz->>Biz: 执行业务本地事务
alt 成功
Biz->>MQ: Commit 确认
else 失败
Biz->>MQ: Rollback 撤销
end
MQ->>D: 投递正式消息
D-->>MQ: Ack/重试
MQ->>Biz: 事务回查(Check) 未确认半消息
Biz-->>MQ: 返回最终状态(提交/回滚)
3.4.3 Best-Effort Notification
Process: After an event occurs, a notification is sent to downstream systems (HTTP/MQ). If it fails, it retries several times according to a strategy. If the threshold is exceeded, it enters manual processing.
Applicable: Scenarios with relatively relaxed consistency requirements (e.g., SMS, in-app messages, point issuance).
flowchart LR
A[事件源] --> B{通知}
B -->|HTTP/MQ| C[下游]
B --> R1[重试1]
R1 --> R2[重试2]
R2 --> R3[重试N]
R3 --> DLQ[死信/人工补偿]
C --> Idem[去重/幂等处理]
4. Transaction Processing in Order Systems
4.1 Inventory Deduction Issue
In an order system, inventory deduction is a critical operation:
// 库存扣减示例
func (s *InventoryServer) Sell(ctx context.Context, req *proto.SellInfo) (*emptypb.Empty, error) {
// 开启事务
tx := global.DB.Begin()
if tx.Error != nil {
return nil, status.Error(codes.Internal, "开启事务失败")
}
// 遍历所有商品
for _, goodsInfo := range req.GoodsInvInfo {
var inv model.Inventory
// 使用行锁查询
result := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
Where("goods_id = ?", goodsInfo.GoodsId).
First(&inv)
// 检查库存是否充足
if inv.Stock < goodsInfo.Num {
tx.Rollback()
return nil, status.Error(codes.ResourceExhausted, "库存不足")
}
// 使用乐观锁更新库存
updateResult := tx.Model(&model.Inventory{}).
Where("goods_id = ? AND version = ?", goodsInfo.GoodsId, inv.Version).
Updates(map[string]interface{}{
"stock": inv.Stock - goodsInfo.Num,
"version": inv.Version + 1,
})
}
// 提交事务
if err := tx.Commit().Error; err != nil {
return nil, status.Error(codes.Internal, "提交事务失败")
}
return &emptypb.Empty{}, nil
}
4.2 Distributed Locks to Solve Concurrency Issues
// 基于Redis的分布式锁
func (s *InventoryServer) SellWithDistributedLock(ctx context.Context, req *proto.SellInfo) (*emptypb.Empty, error) {
// 获取分布式锁
lockKey := fmt.Sprintf("inventory_lock_%d", req.GoodsInvInfo[0].GoodsId)
lock := s.redisClient.NewMutex(lockKey, time.Second*10)
if err := lock.Lock(); err != nil {
return nil, status.Error(codes.Internal, "获取锁失败")
}
defer lock.Unlock()
// 执行库存扣减逻辑
return s.Sell(ctx, req)
}
5. Business Scenario Analysis
5.1 Order Placement Without Payment Issue
Problem: Users place orders but do not pay, leading to inventory being held.
Solutions:
- Order Timeout Mechanism: Set an order timeout period, after which the order is automatically canceled.
- Inventory Pre-occupation: Pre-occupy inventory when an order is placed, confirm deduction after successful payment.
- Scheduled Task: Periodically clean up timed-out orders and release inventory.
5.2 Insufficient Inventory During Payment Issue
Problem: Inventory is sufficient when the order is placed, but insufficient at the time of payment.
Solutions:
- Inventory Pre-occupation: Pre-occupy inventory when an order is placed to prevent overselling.
- Re-check at Payment: Re-verify inventory before payment.
- Compensation Mechanism: Provide alternative solutions when inventory is insufficient.
6. Best Practices
- Judicious Use of Transactions: Avoid long transactions to reduce lock contention.
- Choose Appropriate Isolation Levels: Select based on business requirements.
- Use Optimistic Locking: Reduce lock contention and improve concurrency performance.
- Implement Retry Mechanisms: Handle transient failures.
- Monitoring and Alerting: Timely detection and handling of issues.
7. Summary
Transactions and distributed transactions are important mechanisms for ensuring data consistency. In a microservice architecture,
主题测试文章,只做测试使用。发布者:Walker,转转请注明出处:https://walker-learn.xyz/archives/4786