Saga 分布式事务
monSQLize v1.1.0 引入了 Saga 分布式事务模式,用于协调跨服务的事务操作。
目录
什么是 Saga
Saga 是一种分布式事务模式,通过将长事务分解为多个本地事务,每个本地事务都有对应的补偿操作。当某个步骤失败时,通过逆序执行补偿操作来撤销已完成的步骤。
核心特性
- ✅ 跨服务事务协调:协调多个服务的操作
- ✅ 自动补偿机制:失败时自动逆序执行补偿
- ✅ 无时间限制:突破 MongoDB 60秒事务限制
- ✅ Redis 分布式支持:多进程环境下共享 Saga 定义
- ✅ 详细日志:完整的执行和补偿日志
使用场景
适用场景
-
跨服务事务
A 服务(订单) → B 服务(库存) → C 服务(支付)
-
第三方 API 集成
-
长时间流程
不适用场景
- 单服务单库操作 → 使用
withTransaction
- 外部 API 只读取 → 使用
withTransaction
快速开始
安装
Saga 功能已内置在 monSQLize v1.1.0+,无需额外安装。
npm install monsqlize@^1.1.0
基本使用
import MonSQLize from 'monsqlize';
// 初始化
const msq = new MonSQLize({
type: 'mongodb',
config: { uri: 'mongodb://localhost:27017/mydb' }
});
await msq.connect();
// 定义 Saga
msq.defineSaga({
name: 'create-order-with-payment',
steps: [
{
name: 'create-order',
execute: async (ctx) => {
// 创建订单
const order = await createOrder(ctx.data);
ctx.set('orderId', order.id);
return order;
},
compensate: async (ctx) => {
// 取消订单
const orderId = ctx.get('orderId');
await cancelOrder(orderId);
}
},
{
name: 'charge-payment',
execute: async (ctx) => {
// 扣款
const charge = await stripe.charges.create({
amount: ctx.data.amount,
source: ctx.data.paymentToken
});
ctx.set('chargeId', charge.id);
return charge;
},
compensate: async (ctx) => {
// 退款
const chargeId = ctx.get('chargeId');
await stripe.refunds.create({ charge: chargeId });
}
}
]
});
// 执行 Saga
try {
const result = await msq.executeSaga('create-order-with-payment', {
userId: 'user123',
amount: 9900,
paymentToken: 'tok_visa'
});
console.log('订单创建成功:', result.sagaId);
} catch (error) {
console.error('订单创建失败:', error.message);
}
API 文档
defineSaga(config)
定义一个 Saga。
参数:
config.name (string): Saga 名称,全局唯一
config.steps (Array): 步骤列表
步骤配置:
{
name: 'step-name', // 步骤名称
execute: async (ctx) => { }, // 执行函数
compensate: async (ctx, result) => { } // 补偿函数(可选)
}
返回值:SagaDefinition 实例
示例:
msq.defineSaga({
name: 'my-saga',
steps: [
{
name: 'step1',
execute: async (ctx) => {
// 正向操作
return { success: true };
},
compensate: async (ctx, result) => {
// 补偿操作
}
}
]
});
executeSaga(name, data)
执行 Saga。
参数:
name (string): Saga 名称
data (Object): 执行数据,可通过 ctx.data 访问
返回值:Promise