双SNS事件同时触发Lambda时的跨账号S3校验及EMR触发方案咨询
问题根因与解决方案
根因
你遇到的是分布式场景下的读写竞态问题:两个并发的Lambda实例同时执行「检查标记是否存在→写入自身标记」的逻辑时,检查步骤都先于对方的写入操作完成,因此双双判定另一文件未到达。
可选落地方案
方案一:基于DynamoDB原子计数实现(生产环境优先推荐)
利用DynamoDB的原子操作天然规避并发冲突,改造成本低、可靠性高:
- 新建DynamoDB表,主键设置为业务批次ID(可使用两个文件的公共业务前缀、或者约定好的批次标识作为主键,保证同批次的两个文件对应同一个主键值),新增
received_file_count数字类型字段,默认值为0 - 每次Lambda收到SNS通知后,调用DynamoDB的原子更新接口,执行
ADD received_file_count 1操作,同时附加条件:仅当更新后的received_file_count≤ 2时允许更新成功 - 读取更新后的返回值,若
received_file_count == 2,则触发EMR集群创建逻辑 - 可选配置:给表开启TTL功能,自动清理超过保留期的历史记录,无需手动维护数据生命周期
该方案完全规避并发竞态,DynamoDB的原子更新保证不管两个事件到达的时间差多小,计数都会准确累加,不会出现漏判。
方案二:调整现有S3标记逻辑,无需新增服务
如果不想引入额外的AWS服务,可修改现有S3标记的执行顺序,适配并发场景:
- 将原有「先查标记→再写标记」的逻辑调整为「先写自身标记→延迟1~2s→再查另一个标记」
- 若查询到另一个标记已存在,再执行EMR创建逻辑,否则直接结束当前Lambda调用
- 必须补充幂等校验:创建EMR前先判断是否已有同批次的EMR创建成功标记(可以存在S3或者DynamoDB里),避免两个Lambda同时查到标记存在,重复创建集群
该方案改造成本极低,适合触发频率不高的业务场景。
方案三:基于SQS FIFO队列做事件聚合
如果你的业务事件量较大、还需要统一的重试机制,可以在SNS和Lambda之间新增SQS FIFO队列做缓冲:
- 将SNS事件先投递到SQS FIFO队列,按业务批次ID设置消息分组,保证同批次的两个消息有序处理
- 配置Lambda批量消费,每次最多拉取2条消息,当拉取到的消息数量等于2时,直接触发EMR创建逻辑
兜底补充
不管采用哪种方案,建议新增一个定时触发的Lambda作为兜底校验:比如每小时执行一次,扫描对端S3桶中已经生成但未触发EMR的批次,补上极端场景下的漏触发情况。
内容的提问来源于stack exchange,提问作者user17146820
相关产品推荐
相关产品推荐

