S3批量上传时AWS Lambda触发CloudFront一次性缓存失效实现问询
实现批量CloudFront缓存失效的几种方案
针对你同时上传10-50个文件、避免多次触发缓存失效的需求,我整理了几个生产环境中常用的实现思路,核心都是先收集上传事件,等待所有文件上传完成后再执行一次通配符失效:
方案一:SQS延迟队列 + 去重机制
这是最容易上手的方案,利用SQS的延迟发送和去重特性,确保同一批次的上传只触发一次失效:
第一步:配置S3触发与SQS队列
- 创建一个SQS标准队列,设置默认延迟发送时间(比如60秒,根据你的上传速度调整,确保所有文件能在这个时间内传完)。
- 给S3桶配置对象创建/更新事件,触发第一个Lambda函数(比如叫
S3EventForwarder)。这个Lambda不用做复杂逻辑,只需要把S3事件里的桶名、文件前缀提取出来,发送到SQS队列,同时给消息设置去重ID(比如用{桶名}-{前缀}-{当前分钟时间戳}),这样同一分钟内同前缀的上传事件会被SQS自动去重。
第二步:编写失效执行Lambda
创建第二个Lambda函数(CloudFrontInvalidator)作为SQS队列的消费者,逻辑如下:- 从SQS消息中拿到桶名和前缀。
- 用DynamoDB维护一份最近的失效记录(主键用
{桶名}-{前缀},值存上次失效的时间戳),查询当前前缀是否在最近的延迟时间内已经执行过失效。 - 如果没有执行过,调用CloudFront的
CreateInvalidationAPI,使用通配符(比如/{前缀}/*,如果是根目录上传就用/*)。 - 把这次失效的时间戳写入DynamoDB,避免重复执行。
方案二:DynamoDB计数 + 延迟检查
这个方案通过记录上传文件的数量和最后上传时间,判断批次是否完成:
第一步:准备DynamoDB表
创建一张DynamoDB表,主键设为batchId(可以用{前缀}-{当前小时时间戳},把同一小时内同前缀的上传归为一个批次),表中包含fileCount(已上传文件数)和lastUpdated(最后上传时间)两个属性。第二步:编写计数Lambda
S3触发的Lambda(BatchCounter)逻辑:- 从S3事件中提取文件前缀,生成对应的
batchId。 - 调用DynamoDB的
UpdateItem操作,递增fileCount,同时更新lastUpdated为当前时间。 - 异步调用另一台Lambda(
InvalidationChecker),设置延迟时间(比如60秒),并传递batchId。
- 从S3事件中提取文件前缀,生成对应的
第三步:编写检查与失效Lambda
InvalidationChecker的逻辑:- 根据
batchId查询DynamoDB中的lastUpdated时间。 - 如果当前时间和
lastUpdated的差值大于等于延迟时间(说明这段时间没有新文件上传,批次已完成),就执行CloudFront通配符失效。 - 执行完失效后,可以给这条DynamoDB记录设置TTL自动过期,避免数据堆积。
- 根据
方案三:Step Functions工作流(适合复杂场景)
如果你的上传流程有更多定制需求(比如动态调整等待时间),可以用Step Functions来编排工作流:
第一步:创建状态机
状态机包含两个核心状态:- 等待状态:设置初始等待时间(比如60秒),支持接收外部信号延长等待时间。
- 失效执行状态:调用Lambda执行CloudFront缓存失效操作。
第二步:编写事件触发Lambda
S3触发的Lambda逻辑:- 根据上传前缀查询是否有正在运行的状态机实例。
- 如果有,向状态机发送信号,延长等待时间(比如再加30秒);如果没有,启动一个新的状态机实例,传入前缀信息,进入等待状态。
第三步:自动执行失效
当等待状态结束后,状态机会自动触发失效Lambda,执行一次通配符缓存失效。
关键注意事项
- 通配符选择:尽量用精准的通配符(比如
/images/*)代替全局/*,减少不必要的缓存失效范围,降低CloudFront的费用。 - 延迟时间调整:根据实际上传速度设置,比如上传50个文件需要2分钟,就把延迟时间设为120秒,确保所有文件都能在等待期内上传完成。
- 权限配置:确保Lambda拥有SQS读写、DynamoDB读写、CloudFront失效操作的权限,同时S3有权限触发Lambda。
内容的提问来源于stack exchange,提问作者Chris F.
相关产品推荐
相关产品推荐

