最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
解决Golang微服务中的分布式事务问题
时间:2026-07-08 11:27:46 编辑:袖梨 来源:一聚教程网
Go微服务中无法用database/sql的tx.Commit()实现跨服务事务,因其仅作用于本地数据库,对HTTP/gRPC调用无效;正确方案是本地消息表或Saga模式,需状态持久化、幂等控制与补偿可重入。
Go 微服务里没有“提交就能跨服务生效”的分布式事务。database/sql 的 tx.Commit() 只作用于本机数据库连接,对 HTTP/gRPC 调用的库存、支付等服务完全无效——这是绝大多数人踩坑的起点。
为什么不能用 database/sql 的 tx.Commit() 跨服务
常见错误是写个 tx, _ := db.Begin(),然后串行调 http.Post("/inventory/deduct") 和 http.Post("/payment/charge"),最后 tx.Commit()。这根本不是分布式事务:
- 订单创建成功、库存扣减失败、支付却已发起 → 数据永久不一致
-
context.WithValue(ctx, "xid", ...)只是标记,不是控制;Go 标准库不传播事务上下文到 HTTP header 或 gRPC metadata - 所谓“手动两阶段提交”若没持久化状态、没重启恢复能力,就是伪协议,服务一重启就卡死在中间态
本地消息表(Outbox)是最可控的落地方式
核心是把“改业务数据”和“发消息”塞进同一个数据库事务,靠定时任务异步投递,状态可查、可重试、可人工干预。
- outbox 表必须和业务表同库同实例,否则无法保证原子写入
- INSERT 必须紧跟在业务 SQL 后面,不能用 goroutine 异步包裹
- 轮询 goroutine 读
outbox时,要用SELECT ... FOR UPDATE SKIP LOCKED避免重复处理 - 下游接口必须幂等:用
Idempotency-Keyheader、DB 唯一键或 Redis SETNX 去重 - 轮询间隔建议 1–5 秒:太短压 DB,太长影响延迟
Saga 模式里补偿函数怎么写才不翻车
Compensate 不是反向操作,而是基于当前状态做安全修正。直接 DELETE FROM orders 或 UPDATE stock SET qty = qty + 10 是高危操作。
立即学习“go语言免费学习笔记(深入)”;
- 补偿前必须查状态:例如
UPDATE payments SET status = 'refunded' WHERE id = ? AND status = 'paid' - 补偿函数签名要带原始请求快照(如
*CreateOrderRequest),不能只传 ID - 补偿里避免远程调用;超时设为 ≤3s,失败必须写入
saga_dead_letter表并告警 - Do 接口要支持空重试:
UPDATE stock SET frozen = frozen + ? WHERE sku_id = ? AND frozen <= ?,而不是先 SELECT 再 UPDATE
DTM 或 Seata-Go 接入前必须确认的三件事
框架只管协调,不替你写业务逻辑。掉坑往往发生在初始化和重试环节。
- dtmcli 客户端默认 1 秒超时,而 DTM server 启动慢或 Docker DNS 解析延迟会导致 panic;务必显式设置
Timeout: 5 * time.Second - Confirm/Cancel 接口被重复调用是常态,每个 handler 开头必须查 DB 判断是否已执行:
if exists, _ := s.db.IsStepDone(ctx, gid, "deduct_stock"); exists { return nil } - Seata-Go 启动失败常见报错是
no available service或failed to register branch,本质是注册中心未通或service.vgroupMapping配置不匹配
最易被忽略的是状态持久化位置:Saga 实例状态绝不能存在内存 map 或 Redis 中——服务重启就丢,整个事务链直接卡死。必须落库,且字段至少包含 gid、status、current_step、data(JSON)。这不是可选项,是保命线。
相关文章
- 《Disney Lorcana: Wilds Unknown》预购开启 首批《Toy Story》及皮克斯卡牌购买指南 07-29
- 车来了赶车闹钟如何设置 07-29
- 崩坏星穹铁道余晖残卷巨剑守护打法攻略 07-29
- 崩坏星穹铁道砂金角色部分背景介绍 07-29
- 崩坏3雷电芽衣什么时候上线 07-29
- 玩具熊的五夜后宫4代噩梦气球男孩Nightmare Balloon Boy介绍 07-29