如何搭建Lambda与SQS系统实现S3存储桶所有文件的数字总和计算
AWS Lambda + SQS 实现S3全桶文件数字求和方案
思路评估
- 思路1属于串行接力方案,完全不推荐:串行执行本质没有利用Lambda的并行能力,总耗时和单Lambda循环拉取没有本质差异,且接力过程中状态传递容错性极低,任意环节出错就会导致整个计算中断,还要额外开发索引、状态续传逻辑,冗余度很高。
- 思路2是标准无服务Map-Reduce架构实现,合理性极高,也是AWS官方推荐的批量处理类场景最优架构,下面是可直接落地的完整实现方案:
具体实现步骤
1. 前置资源准备
提前创建以下资源并配置对应IAM权限:
- 2个Lambda函数:
s3-sum-splitter(任务拆分用)、s3-sum-processor(单文件计算用) - 1个标准SQS队列:
s3-file-processing-queue,用于存放待处理的S3文件路径 - 1个DynamoDB表:
s3-sum-result,用于存储中间计数和求和结果,表主键设为job_id(任务唯一标识),额外保留total_files(总文件数)、processed_files(已处理文件数)、current_sum(当前累计和)三个字段 - IAM权限配置:给两个Lambda开通S3只读权限、SQS读写权限、DynamoDB读写权限,同时给SQS配置触发
s3-sum-processor的调用权限。
2. 任务拆分逻辑(s3-sum-splitter 实现)
函数执行逻辑:
- 调用S3的
list_objects_v2接口遍历目标桶所有文件,统计总文件数total_files,生成唯一job_id - 将
total_files、初始值processed_files=0、current_sum=0写入DynamoDB的s3-sum-result表 - 遍历所有文件的key,每个文件生成一条SQS消息,消息体包含
job_id、s3_bucket、file_key三个字段,批量发送到s3-file-processing-queue队列
提示:如果桶内文件超过10万条,可对
list_objects_v2的结果做分页发送,避免单函数超时,Lambda最大运行时长可配置到15分钟,足够处理百万级以下的文件列表遍历。
3. 并行处理逻辑(s3-sum-processor 实现)
给该函数配置SQS触发器,批量处理大小建议设为10,可进一步降低调用次数、减少开销:
函数执行逻辑:
- 批量读取SQS消息,每条消息对应一个待处理的S3文件
- 单文件处理:调用S3的
get_object接口拉取文件内容,提取文件内所有数字,计算当前文件的数字和file_sum - 调用DynamoDB的原子更新接口,对对应
job_id的两个字段做原子累加:processed_files +1、current_sum + file_sum - 原子更新完成后删除当前SQS消息,避免重复处理
- 每次更新后校验
processed_files是否等于total_files,如果相等说明所有文件处理完成,此时可将current_sum作为最终结果输出(可写入S3、发送SNS通知或调用其他业务接口)
4. 容错与优化配置
- SQS配置消息可见性超时:设置为Lambda超时时间的2倍,避免函数处理超时导致同一条消息被重复消费
- Lambda并发数配置:可给
s3-sum-processor设置预留并发,避免账号下其他函数占用资源导致处理延迟,6000个文件的场景下设置100并发的话,一分钟以内即可处理完成 - 幂等性保证:如果怕重复计算,可给每个文件key增加处理标记,或开启SQS的消息去重功能,避免重复累加
方案优势
- 完全利用无服务的并行能力,总耗时只和单文件处理时长、Lambda并发数有关,和总文件数无关
- 不需要自行处理状态接力、任务调度逻辑,所有调度逻辑都由SQS触发器托管,出错自动重试
- 容错性高,任意一个Lambda处理失败,SQS会自动重试,不会影响整体任务执行
内容的提问来源于stack exchange,提问作者Oren Sayag
相关产品推荐
相关产品推荐

