跳到正文

竞态条件

Race Condition

高级通用

竞态条件(Race Condition)是多个操作交错执行时,结果取决于谁先读、谁先写的问题。理解它能帮你发现并发请求下偶发的数据错误,例如两人同时抢到最后一张优惠券。

你可能会说:「帮我检查多人同时操作时,会不会都以为自己成功了,最后把数据弄错。」

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

动手看看

A领取A查询领取用户领取服务优惠券库剩余1张
1

库里只剩一张券。A点了领取,服务先去查余量,准备确认还有没有券可发。

要点

  1. 1

    问题藏在读写之间

    你先读取库存、判断还有货,再扣减库存,看起来是连贯的一步,实际可能包含多次操作。另一个请求如果在判断和扣减之间读到旧库存,两边就都可能认为自己能下单。

  2. 2

    请求顺序改变结果

    竞态条件不要求两个操作在同一瞬间执行,只要执行过程交错,结果就可能不同。所以它常常在本地测试时不出现,却在用户集中操作或任务并行运行时暴露。

  3. 3

    保护关键的共享状态

    我们先找出多个请求会共同读写的状态,再让关键判断和修改以可靠的方式完成。比如用数据库的条件更新扣减库存,并检查实际更新了几行,这样做的好处是只有成功扣减的请求会得到成功结果。

容易混淆的地方

并发是多个任务在一段时间内推进,本身不是错误;竞态条件是这些任务的执行顺序影响了本该一致的结果。幂等解决的是同一操作重复执行时如何避免重复产生效果,不会自动阻止两个不同请求争用同一份库存。事务也不是万能开关:保护范围和隔离方式仍要符合具体的读写逻辑。

什么时候用

适合用

  • 做限量商品下单时,检查多人同时看到最后一件商品,会不会都提交成功。
  • 做账户余额扣减时,检查两个并发请求会不会都按同一笔旧余额计算。
  • 做后台任务时,检查多个消费者同时处理同一条待处理记录会不会产生冲突。

不适合用

  • 只是把静态页面从一个地址跳到另一个地址,没有共享状态要争用;直接处理路由即可。
  • 只是校验单次提交的邮箱格式,结果不依赖其他请求的先后;用数据校验解决。
  • 只是网络重试让同一笔支付请求重复到达,先排查重复执行,并用幂等键约束结果。

练一练

限量优惠券只剩一张,两名用户几乎同时点击领取。你希望最终只有一人成功,哪种处理最可靠?

让 AI 帮你做

请检查领取优惠券接口是否存在竞态条件:重点看并发请求读取剩余数量、扣减数量和写入领取记录的过程。给出能保证仅一人成功的实现方案,并补充并发测试;说明方案在多实例部署下是否成立。

接下来学什么