跳到正文

原子性

Atomicity

高级通用

原子性(Atomicity)指一组操作在约定范围内要么全部生效,要么全部不生效。它解决的是操作做到一半就失败时留下不完整数据的问题,例如创建订单和扣减库存不能只完成其中一步。

你可能会说:「帮我把创建订单和扣库存绑在一起,别出现订单建好了、库存却没扣的情况。」

读之前建议先了解(这是一个高级概念)

动手看看

开始下单订单服务数据库事务数据库
1

用户下单后,订单服务开启一个事务,把创建订单和扣减库存放进同一次提交里。

要点

  1. 1

    先划定哪些操作算一组

    你得先说清楚哪些变化必须一起成功。比如下单时创建订单、扣减库存都写在同一个数据库里,就可以把这两步放进一个事务;其中一步失败,整组数据库修改就回滚。

  2. 2

    以提交作为生效的分界

    事务提交前,系统还可以放弃这一组修改;提交成功后,这组修改才算完成。这样做的好处是,代码执行到第二步时报错,不会把第一步留下来当作一笔完成的业务。

  3. 3

    看清事务管不到的地方

    数据库事务不会顺手撤销已经发出的邮件或第三方支付请求。如果流程还涉及这些动作,我们就得另外设计失败后的处理方式,而不是以为包上一层事务就能全部回滚。

容易混淆的地方

原子性关心的是一组操作会不会只生效一部分;幂等关心的是同一个请求重复执行会不会产生额外结果。它们能一起用于下单,但解决的问题不同。原子性也不等于“绝不会同时出错”:两个人同时抢最后一件库存,还得考虑并发控制,才能判断谁可以下单。

什么时候用

适合用

  • 做电商下单时,创建订单和扣减同库库存必须一起成功,否则会出现卖出数量与库存记录对不上的情况。
  • 在后台转移账户余额时,转出方扣款和转入方加款都写入同一数据库,需要避免只完成一边。
  • 用户兑换积分奖励时,扣积分和生成兑换记录属于同一笔操作,需要避免扣了积分却没有记录。

不适合用

  • 用户在设置页单独修改头像昵称,没有必须一起完成的其他写入;做普通的数据更新就够了。
  • 批量导入商品时,产品允许有效行先入库、错误行单独报告;逐行处理并返回结果,比整批失败更合适。
  • 订单完成后给用户发邮件,邮件服务不受数据库事务控制;用可靠的异步任务处理发送,不把它当成同一组可回滚操作。

练一练

你在做下单接口:订单记录和库存记录在同一个数据库,还要发送确认邮件。怎样设计,才能避免留下有订单却没扣库存的数据?

让 AI 帮你做

请为下单接口实现原子性:创建订单和扣减库存位于同一数据库事务中,任一步失败都不留下部分写入。确认邮件不纳入事务;请说明提交后如何安排发送,以及发送失败时如何处理。

接下来学什么