对账 / 差错
When to Invoke
支付、退款、分佣、核销、券、库存跨系统;事务消息/最终一致上线后。高级面试常追问「不一致了怎么办」——答案是对账,不是再上 2PC。
When NOT
单表本地事务且无外部资金。不要用对账替代唯一键和幂等。
风险(面试考点)
最终一致系统 一定会 短暂不一致。没有对账 = 线上默默错账。对账要有:数据源、粒度、窗口、差错单、人工/自动平账、幂等。
两边都成功、一边成功、金额不等、重复入账、漏单,分类不同,处理不同。
方案选型(轻量优先)
| 通道 | 对账双方 | 默认节奏 |
|---|---|---|
| 支付 | 本地支付单 vs 渠道对账单 | T+1 文件 + 当日准实时抽查 |
| 分佣 | 订单已支付 vs 分佣流水 | 日批 + 关键单实时 |
| 库存 | Redis 预扣 vs DB | 定时对齐,以 DB 为准 |
| 核销 | 券状态 vs 订单核销记录 | 日批 |
默认方案
- 每笔资金有 唯一流水号(与
idempotent同一键)。 - 对账任务按日:拉渠道文件,按流水号 full outer join。
- 差错写入
t_recon_diff,状态NEW/HANDLED,处理动作幂等。 - 自动平:漏单补记账;重复跳过;金额不等告警人工。
UNIQUE KEY uk_recon (biz_date, channel, trade_no)
禁止对账程序直接 UPDATE 余额两遍。只插「补账流水」,再走原来的入账逻辑。
反例
错误:有 Seata 就不用对账。 正确:AT/TCC 仍会悬挂、空回滚,资金必须对账。
错误:对账发现少了一笔就再调一次支付接口。 正确:查单,按本地状态机补,不新开支付。
验证
- 故意丢掉一条 MQ,日对账能检出并补平一次。
- 重复补账不增加金额。
- 渠道文件晚到有重跑,不重复处理已 HANDLED。
评审清单
- 有流水号和对账表
- 平账走原入账幂等逻辑
- 未用「上分布式事务」代替对账