为什么不建议让主系统与提成小账长期双向联动?
结论:主系统负责订单、回款和人员归属等业务事实,提成小账负责规则、计算与结算;默认只把事实单向送入小账,纠错用新事件、冲正和对账完成。只有每个字段的唯一写入方、幂等规则和冲突处理都已明确时,才考虑有限双向联动。
问题不在于“两个系统能不能互调接口”,而在于同一个事实能否被两边同时改写。主系统把订单金额改为 9 万元,小账又因人工补差回写 10 万元;下一次同步究竟覆盖哪一个值?退款、拆单、跨月回款和员工调岗叠加后,系统可能技术上都成功,财务却无法说明某笔提成按哪个时点、哪版规则得出。滚水科技因此先划分数据所有权,再决定接口方向。
在约定交付物、接管方式与责任边界时,还可以对照 提成或佣金数据如何做到仅特定账号可见? 和 如何约定交付文档与交接,避免只给源码就走?;这些内容补充了需要放在同一项决策中考虑的上下文。
三种架构的长期差异如下:
| 联动方式 | 数据写入规则 | 优点 | 长期风险 | 适用结论 |
|---|---|---|---|---|
| 共享数据库或互相改表 | 两边都可能直接改同一记录 | 初期开发快 | 强耦合、无法审计、升级互相影响 | 不建议用于正式结算 |
| 全量双向 API 同步 | 两边按时间覆盖或合并 | 表面上数据一致 | 循环更新、冲突覆盖、失败重试产生重复 | 仅适合字段边界极清楚的有限场景 |
| 事实单向进入小账 | 主系统写业务事实,小账写计算与结算结果 | 责任清楚,可重放、可追溯 | 需要事件、快照和对账机制 | 佣金核算优先采用 |
建议先制作字段级责任表。订单号、成交金额、退款、回款时间、客户归属来自主系统;提成规则版本、计提基数、计算明细、审批状态、发放批次由小账维护。小账可以把“已结算批次号”或汇总状态提供给主系统展示,但主系统不应反向改动结算流水。所谓单向不是只允许一条网络连接,而是每项业务事实只有一个权威写入方。
同步消息要包含全局事件 ID、业务单号、事实版本、发生时间和来源。小账以事件 ID 去重,按版本处理乱序;同一消息因超时重试十次,也只能产生一次业务影响。订单退款不删除原订单事件,而是新增退款事实;提成小账据此生成负向调整或冲正。AWS 对 事件溯源模式 的说明强调不可变事件历史带来的审计和状态重建能力,同时也指出复杂度、最终一致性等代价,因此小规模业务不必盲目建设完整事件平台,但不可变流水与幂等仍值得保留。
每次正式结算应形成快照:锁定纳入的事实版本、规则版本、员工组织关系和人工调整,保存计算明细与审批人。结算后的业务事实发生变化,进入下一批次补差,不回写覆盖已发放记录。这样月末可以把主系统事实汇总、小账计提汇总、实际付款汇总三者对账,差异按“未同步、规则排除、人工调整、付款未完成”等原因分类,而不是笼统标记为不一致。
如果报表查询压力大,可参考 AWS 的 CQRS 模式说明,把写入模型与查询模型分开,但必须接受读模型可能短暂滞后。页面上应展示数据截止时间或同步状态,不能把“最终一致”包装成实时。接口合同则应明确字段含义、金额单位、时区、空值、错误码和版本策略,可用 OpenAPI 规范 固化,避免双方对同名字段作不同解释。
有限双向联动并非绝对禁止。例如小账完成审批后,把“本批次已结算”状态同步回主系统用于只读展示是合理的,因为该状态只由小账产生。允许这种联动的前提是:字段有唯一所有者,请求有幂等键,失败有重试和死信处理,冲突有人工处理入口,权限不会把敏感金额扩散到无关角色。任何无法回答“谁最终说了算”的字段,都不应双向同步。
验收应模拟重复消息、乱序、网络中断、跨月退款、员工调岗、规则变更和人工冲正,检查结果是否重复计提、历史是否被覆盖、差异能否定位。滚水科技把对账报表与故障演练列为上线条件,而不以“接口返回 200”作为完成标准。