连载中 16/18

对账系统:最终一致的最后防线

2026-06-22 · 6551 阅读 · 0 评论 · 0 赞

防御全做了,差异还是来了

消息表、事务消息、幂等、对账……不对,对账还没做。老王的系统上线半年,防御工事全齐,季度审计却翻出两笔三个月前的差异:一笔支付成功但订单状态停在待支付,一笔退款重复。根因分别是「MQ 集群主备切换丢了一条消息」和「一个从未想到的故障组合」。这两笔教了他最后一课:防御是概率游戏,对账是确定性游戏——无论防御多密,都要假设差异会发生,并有一套独立机制把它们找出来。

对账的本质:不信任自报

对账的核心思想一句话:不拿任何一方的内部状态当真理,用两份独立产生的数据互相印证。我方订单表对渠道方账单文件,渠道账单对银行流水,银行流水对账务总账——链条上每一环都拿「对方独立记录的数据」比「我方记录的数据」。差异必然藏不住:两边数据来源不同、生成路径不同,想两边同时错得互相一致,概率趋近于零。

两级对账:快扫与全量

准实时对账(分钟级):订单落库后几分钟内,把流水发到比对队列与下游回执比对,差异快速浮出。灵敏但可能有盲区(队列丢、延迟乱序),当哨兵用。

日终对账(T+1):金融行业标配。次日拿到对方的账单文件(渠道账单、银行流水),与本系统前一天的流水全量逐笔比对。慢一拍,但全量、确定性、无盲区,是真正的兜底。两级配合:准实时负责「尽快发现」,日终负责「一个不漏」。

对账四步与三种差异

取数:我方流水 + 对方账单(文件/接口)
清洗:统一格式、统一对账键(流水号)、金额规整
比对:按对账键 join,逐笔核对金额与状态
分流:差异进差错处理流程

比对结果分三类,行业黑话要记牢:长款——对方有、我方无(渠道扣了钱,我方没这笔单,多为通知丢失);短款——我方有、对方无(我方记了成功,渠道没扣到,最危险,涉及多发货物或服务);状态/金额不符——两边都有但对不上(金额不一致、我方成功对方失败)。三类差异的处理策略完全不同,不能一锅烩。

差错处理三路分流

处理路径条件例子
自动平账规则明确、风险可控长款补单落库、漏发消息补发
人工差错池可疑、涉及资金决策金额不符、疑似重复支付
挂账短期无法定论进过渡科目,定期清理

分流的红线:自动平账只做「低风险可逆」的动作——补落库、补发消息可以,自动退款、自动扣款不行,钱上的决定必须人工。挂账不是垃圾桶,要有清理 SLA(比如 30 天),挂久了就是审计问题。

系统设计的四个细节

一:对账键要稳——双方约定的唯一流水号,跨系统唯一且永不复用,这是对账的命根子。二:支持重跑——对账任务本身也会挂,同一批数据重跑结果必须一致(对账逻辑做成幂等)。三:容错窗口——对方数据晚到是常态,比对要有时间窗(比如 T+1 比对时容忍 T-1 的尾巴),窗口参数进配置。四:差错率指标化——每日差异笔数 / 总笔数是系统健康度的体温计,趋势恶化比单笔差异更值得警觉。

小结

对账一句话:独立数据源全量比对,准实时当哨兵、日终当兜底;长款短款分流处理,自动只做可逆动作,挂账要有清理期限;差错率是体温计。至此防御与兜底齐活。老王半年攒下的教训远不止这些——那些方案救不了、只能靠纪律防的坑,下一篇集中曝光:踩坑实录。

☕
503

10 年全栈工程师 · 503咖啡馆主理人

#分布式事务#对账#长款#短款#差错处理

评论 (0)

热门推荐

连载中 11/22

主从搭建实操:从零配出一主两从

光讲原理不过瘾?手把手搭一主两从:my.cnf 六个参数、复制账号、GTID、CHANGE REPLICATION SOURCE TO、SHOW REPLICA STATUS 验收,附翻车排查清单。

#MySQL#主从复制#GTID#主从搭建#高可用
2026-05-07 · 10101 阅读 · 0 评论 · 0 赞
连载中 16/22

连接池:HikariCP 参数与连接风暴

连接池不是越大越好:8 核机器配 1000 连接反而更慢的数学原理,HikariCP 四个必调参数,maxLifetime 与 wait_timeout 的隐形陷阱。

#MySQL#连接池#HikariCP#maxLifetime#连接风暴
2026-05-10 · 9873 阅读 · 0 评论 · 0 赞
连载中 4/16

缓存穿透:恶意 ID 打穿 MySQL 的四道防线

请求的数据在缓存和数据库里都不存在时,缓存形同虚设。聊聊参数校验、空值缓存、布隆过滤器、限流熔断四道防线的原理与组合打法。

#Redis#缓存穿透#布隆过滤器#高可用
2026-05-16 · 9294 阅读 · 21 评论 · 287 赞