为卖家账单建立镜像表时,如何保证买家表和卖家表双写一致?

考查重点:可靠投影与双表收敛。权威事务写 outbox,可靠投影卖家表,按版本幂等更新并对账

本题目录

参考答案

核心回答

若卖家账单表是订单权威数据的查询投影,我会用“本地事务记录订单与待发送事件,可靠投递后幂等更新投影,再持续对账”的方案实现最终一致。只在业务代码里先写买家表、再写卖家表,两次独立提交之间总有一边成功、另一边失败的窗口。

若两表确实在同一数据库事务内,可直接用本地事务原子提交;跨库且要求立即强一致,则需要评估分布式事务及其延迟、可用性成本。不能把异步投影说成两表任何时刻都完全相同。

Outbox 怎样补上可靠交接

  1. 在买家订单所在数据库的同一个本地事务中,更新订单并写入 outbox,保存事件标识、订单标识、业务版本与变更内容。
  2. 投递进程或 CDC 从已提交事件中发送消息,投递失败可重试;发送后标记也可能丢失,因此按至少一次交付设计消费者。
  3. 卖家库在同一事务中完成去重记录和账单更新。使用事件唯一约束防重复,按订单业务版本阻止旧事件覆盖新状态,提交后再确认消息。
  4. 监控投影延迟、失败与死信,并按订单版本或校验摘要对账修复。
flowchart TD
  subgraph T["买家订单库:同一本地事务"]
    B["更新权威订单"] --- O["写入 outbox 事件"]
  end
  O -->|"仅投递已提交事件"| R["投递进程或 CDC"]
  R -->|"可重试,可能重复"| M["消息队列"]
  M --> C["卖家库事务:事件去重、版本检查、更新账单"]
  C -->|"事务提交后"| A["确认消息"]

图中的两个本地事务各自原子提交;消息传递期间允许投影暂时落后,失败后通过重试和对账收敛。

事件只包含增量时,不能随意跳过中间版本,否则可能漏算。若采用“只接受更高版本”的覆盖策略,事件应包含足以重建该行的完整状态,或检测版本缺口并回查权威数据。

订单查询还要考虑哪些边界

镜像表保留卖家查询需要的字段和索引,明确一次订单是否包含多个卖家、拆单后使用哪个业务标识。删除和撤销也要携带版本或保留墓碑,避免旧消息将已撤销记录重新创建。

首次构建需要一致的全量基线与增量衔接,再切换查询流量。投影落后时可以展示更新时间、稍后重试,或对少量关键记录回查权威订单;读取哪种结果是产品契约的一部分。

MQ、CDC 和重试都不能单独保证业务一致性。权威事务、可靠事件、投影幂等、乱序处理和对账共同形成完整链路。

参考资料

相关面经

1 篇

阿里巴巴

AI 全栈开发工程师
一面
查看原面经 →
项目追问
深分页与卖家账单查询深分页和卖家账单查询的场景,你觉得有哪些要优化的?给订单系统做商家纬度账单查询,order 表分库分表,用卖家来查,近三个月或近六个月,很多条件。首先有深分页问题,深分页怎么优化?第二是这种卖家纬度的查询怎么去支持?(追问·深分页·游标)游标跳页的查询也支持吗?从第一页跳到第五页。(追问·深分页·跳页)账单查询并不像刷抖音一样,有一到十可以选择中间任何一页,你觉得这个方法能用吗?(追问·深分页)跳页怎么办呢?(追问·卖家表)你说卖家表,下单时把买家表落了以后,单独搞一个卖家表落买卖家 id 和买家表业务单号,查的时候查那个卖家表?(追问·卖家表)分页时每页查 200 条,卖家表查 200 个 id,再散到买家库查 n 个库,查 200 次,再聚合?(追问·卖家表)买家的所有字段你都落吗?相当于镜像表一模一样的字段,分表键换了一个?(追问·卖家表)两张表是双写吗?下达时都写上是吧?(追问·卖家表)写入开销小的话,怎么保证事务?A 成功 B 失败怎么办?(分布式事务)

相关题目

4 题