如何在状态机配置内让同状态机后续调用等待前序执行完成
基于Step Functions状态机配置实现串行执行(无需队列)
可以通过DynamoDB分布式锁+状态机内置重试/等待逻辑实现,完全在状态机配置内完成,无需额外队列服务。核心是让每个状态机执行实例启动时先尝试获取全局锁,只有拿到锁的实例才能执行业务逻辑,未拿到的则循环等待直到锁被释放。
具体实现步骤
1. 准备DynamoDB锁表
创建一个极简的DynamoDB表(推荐表名StateMachineGlobalLock):
- 主键设为
LockKey(字符串类型),固定使用SingleExecutionLock作为键值 - 额外添加
OwnerExecutionId(字符串)和ExpirationTime(数字,存储Unix时间戳)两个字段,前者记录当前持锁的执行ID,后者用于处理执行意外失败的锁过期场景
2. 状态机核心逻辑(ASL配置)
状态机分为四个关键阶段:尝试获取锁、等待重试、执行业务、释放锁,以下是完整示例配置:
{ "Comment": "串行执行状态机,基于DynamoDB锁避免并行", "StartAt": "AcquireGlobalLock", "States": { "AcquireGlobalLock": { "Type": "Task", "Resource": "arn:aws:states:::dynamodb:putItem", "Parameters": { "TableName": "StateMachineGlobalLock", "Item": { "LockKey": {"S": "SingleExecutionLock"}, "OwnerExecutionId": {"S": "$$.Execution.Id"}, "ExpirationTime": {"N": "${Math.floor(Date.now()/1000) + 3600}"} }, "ConditionExpression": "attribute_not_exists(OwnerExecutionId) OR ExpirationTime < :currentTimestamp", "ExpressionAttributeValues": { ":currentTimestamp": {"N": "${Math.floor(Date.now()/1000)}"} } }, "Catch": [ { "ErrorEquals": ["ConditionalCheckFailedException"], "Next": "WaitBeforeRetry" } ], "Next": "ProcessS3Upload" }, "WaitBeforeRetry": { "Type": "Wait", "Seconds": 15, "Next": "AcquireGlobalLock" }, "ProcessS3Upload": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:YourS3FileProcessor", "Next": "ReleaseGlobalLock" }, "ReleaseGlobalLock": { "Type": "Task", "Resource": "arn:aws:states:::dynamodb:updateItem", "Parameters": { "TableName": "StateMachineGlobalLock", "Key": {"LockKey": {"S": "SingleExecutionLock"}}, "UpdateExpression": "REMOVE OwnerExecutionId, ExpirationTime", "ConditionExpression": "OwnerExecutionId = :currentExecutionId", "ExpressionAttributeValues": { ":currentExecutionId": {"S": "$$.Execution.Id"} } }, "End": true } } }
关键细节说明
- 锁的原子性:通过DynamoDB的条件写入(
ConditionExpression)保证同一时间只有一个执行实例能获取锁,彻底避免并行执行 - 锁过期机制:
ExpirationTime字段设置为当前时间+业务最大预估执行时长(示例中为1小时),如果持锁实例意外崩溃,锁会自动过期,后续执行可以正常获取 - 重试策略:
WaitBeforeRetry的等待时长可根据业务调整,平衡重试频率和资源消耗 - 锁释放安全:释放锁时的条件表达式确保只有当前持锁的执行实例能释放锁,防止其他实例误操作
内容的提问来源于stack exchange,提问作者T K R
相关产品推荐
相关产品推荐

