如何基于Lambda、SQS和DDB实现幂等性避免重复工单?
解决SQS-Lambda流程中的工单创建幂等性问题
针对你遇到的重复工单问题,这里有几个可落地的幂等性实现方案,按优先级和可行性排序:
方案1:用DDB条件写入做前置校验(最推荐,无需依赖外部API修改)
核心思路是用DDB的原子操作,先锁定请求ID的处理状态,避免重复执行创建工单的步骤:
- Lambda接收到SQS消息里的请求ID后,先执行DDB的条件写入操作:
# 示例代码(Python) ddb_client.put_item( TableName='你的表名', Item={ 'requestId': {'S': 请求ID}, 'status': {'S': 'PROCESSING'}, 'ticketId': {'S': ''} }, ConditionExpression='attribute_not_exists(requestId)' ) - 如果写入成功:说明是第一次处理这个请求ID,正常调用外部API创建工单,拿到工单ID后更新DDB的
status为COMPLETED,并填充ticketId字段。 - 如果写入失败(抛出
ConditionalCheckFailedException):- 立即查询该请求ID在DDB中的记录
- 如果
status是COMPLETED:直接返回成功,无需再处理 - 如果
status是PROCESSING:说明之前的Lambda实例可能还在处理,或者处理到一半挂了。可以等待几秒后重试查询,或者直接返回成功(后续SQS重试会自动处理);如果外部API支持根据请求ID查询工单,也可以主动去查询工单ID,再更新到DDB。
这个方案的关键是利用DDB的条件表达式实现原子性,确保同一个请求ID只会触发一次工单创建。
方案2:给外部API请求添加幂等键(如果API支持)
如果外部API支持自定义幂等标识(很多成熟API都会提供这个能力,比如通过请求头Idempotency-Key或者请求参数):
- Lambda调用外部API时,直接把请求ID作为幂等键传递给API
- 外部API会根据这个键记录请求的处理结果,重复收到相同幂等键的请求时,会直接返回之前生成的工单ID,而不会创建新工单
- 后续不管Lambda重试多少次,都只会拿到同一个工单ID,更新DDB即可
这个方案最简洁,但前提是外部API支持幂等键机制。
方案3:用Step Functions编排流程(适合复杂场景)
如果你的流程后续可能扩展,或者需要更精细的错误处理,可以用AWS Step Functions把整个流程拆成几个状态:
- 检查DDB状态:查询请求ID是否已处理
- 创建工单:仅当未处理时调用外部API
- 更新DDB:写入工单ID和完成状态
Step Functions会持久化每个步骤的执行状态,某个步骤失败时,会从失败的步骤开始重试,而不是从头执行。比如如果“更新DDB”步骤失败,重试时会直接执行这个步骤,不会重复执行“创建工单”,从根源避免重复工单。
补充注意事项
- 如果外部API不支持根据请求ID查询工单,那方案1中遇到
PROCESSING状态时,建议设置合理的重试间隔,避免短时间内重复调用API - 可以给DDB的
PROCESSING状态设置TTL(生存时间),比如15分钟,避免因Lambda彻底挂掉导致请求ID一直处于处理中状态
内容的提问来源于stack exchange,提问作者Mojo jojo
相关产品推荐
相关产品推荐

