← 返回题目列表

分布式任务为什么必须做幂等?如何保证任务幂等?

高频 中等 第 9 / 25 题 更新于 2026/07/28
任务幂等重复执行去重

简化版

分布式任务必须做幂等,因为任务可能因超时、重试、调度中心故障、执行器重启等原因被重复触发。保证幂等的常见方式有唯一约束、业务状态机、去重表、执行流水号、乐观锁和先查后写。

详细版

任务调度系统很难保证业务层绝对只执行一次。即使调度中心只触发一次,也可能出现执行成功但回调失败,调度中心误以为失败后重试。

幂等设计方法:

  1. 唯一约束:例如 user_id + coupon_id + activity_id 防止重复发券。
  2. 状态机:只有特定状态才能流转,已处理状态直接跳过。
  3. 去重表:记录 task_id + biz_id,重复插入失败则跳过。
  4. 业务流水号:同一业务请求只处理一次。
  5. 乐观锁:更新时带版本号或状态条件。
  6. 分布式锁:用于减少并发重复,但不能替代幂等。

面试重点:锁只能降低重复并发概率,幂等才是重复执行后的正确性保障。

完整版教学

一、为什么任务会重复执行

很多人以为“调度中心控制一下,不重复调度就行”。现实里重复执行非常常见。

典型场景包括:

  1. 执行器已经执行成功,但回调调度中心时网络超时。
  2. 调度中心没有收到成功结果,于是触发失败重试。
  3. 执行器执行到一半重启,任务被其他节点接管。
  4. 运维人员看到任务失败,手动点了重跑。
  5. 分片任务重新分配时,某个分片被再次执行。

这些场景都不是异常设计,而是分布式系统的常态。任务幂等就是为了接受这种不确定性。

二、什么叫任务幂等

幂等的意思是:同一个业务动作执行一次和执行多次,最终结果一致。

比如“给用户发一张活动券”,重复执行不能变成发两张。正确结果应该是:第一次发成功,第二次发现已发过,直接跳过或返回成功。

伪代码可以这样写:

if exists_coupon(user_id, activity_id):
    return success
insert coupon(user_id, activity_id)

但仅靠先查后写在并发下不安全,最好加数据库唯一约束:

unique(user_id, activity_id)

这样即使两个任务同时执行,也只有一个能插入成功。

三、状态机如何保证幂等

很多任务适合用状态机控制。例如超时关闭订单:

待支付 -> 已关闭
已支付 -> 不允许关闭
已关闭 -> 重复关闭直接跳过

SQL 可以带状态条件:

update orders
set status = 'CLOSED'
where id = ? and status = 'WAIT_PAY';

如果影响行数是 1,说明本次关闭成功;如果是 0,说明订单可能已支付或已关闭,任务不应继续重复处理副作用。

四、去重表适合什么场景

去重表适合外部副作用明显、需要记录处理流水的任务。例如同步第三方账单、发送通知、发放奖励。

可以设计:

task_name
biz_id
execute_date
status

执行前先插入去重记录,唯一键是 task_name + biz_id + execute_date。插入成功才处理,插入失败说明已经处理过或正在处理。

这种方式的好处是可追踪,坏处是表可能很大,需要归档和清理。

五、分布式锁为什么不能替代幂等

分布式锁只能让同一时刻尽量只有一个执行者,但不能覆盖所有异常。

例如任务拿到锁后执行成功,释放锁前进程崩溃;或者锁过期后另一个节点进来执行;或者人工重跑任务。只靠锁无法证明业务没有重复产生副作用。

更稳的设计是:锁用于减少并发冲突,幂等用于保证重复发生后结果仍正确。

六、常见误区与追问

这道题要紧扣「任务幂等」本身回答,不能把它混成泛泛的分布式任务调度套话。面试官通常会沿着“为什么需要、流程怎么走、失败怎么兜、代价是什么”继续追问,所以回答要覆盖调度触发、分片分配、抢占锁、失败重试、超时控制、幂等和高可用。

回答层次要讲清的内容容易漏掉的边界
核心结论任务幂等保证同一任务因重试、抢占或重复触发执行多次时,业务结果仍只生效一次不要停在名词解释
流程机制生成任务唯一键 -> 检查处理状态 -> 加锁或乐观更新 -> 执行业务动作 -> 记录成功结果 -> 重复请求直接返回要说清触发点、状态变化、确认点和失败兜底
工程取舍扣款任务如果重试 3 次,必须通过业务唯一键或状态机保证只扣一次任务调度提升自动化和吞吐,但必须处理重复执行、漏执行、积压、超时和故障恢复
任务幂等 面试拆解:
1. 生成任务唯一键
2. 检查处理状态
3. 加锁或乐观更新
4. 执行业务动作
5. 记录成功结果
6. 重复请求直接返回

记忆钩子:先给结论,再拆流程,再讲数字例子和失败边界;回答「任务幂等」时要围绕题目问法收束,不要把相邻概念堆成一段没有重点的名词清单。

  • 误区:调度框架能完全避免重复执行。 网络抖动、超时重试和故障切换都可能导致重复,业务必须幂等。
  • 误区:只靠分布式锁就够了。 锁过期、释放失败或任务超时仍可能重复,最终要靠业务状态兜底。
  • 误区:读任务不需要幂等。 读任务若会写进度、发通知或导出文件,也可能产生副作用。
  • 追问:常见幂等手段? 唯一键、状态机、去重表、乐观锁、版本号和幂等 token。
  • 追问:任务超时后如何处理? 不要盲目重跑,先判断上次是否已部分成功,再补偿。
  • 追问:如何设计去重表? 用业务唯一键记录执行状态和结果,重复执行先查表。

七、加强记忆

任务调度一定要默认“可能重复执行”。调度系统负责尽量少重复,业务幂等负责重复后不出错;唯一约束、状态机、去重表、流水号和乐观锁,是任务幂等最常用的护城河。