如何保证RDS MySQL与SQS队列调用操作同时成功或失败?
RDS MySQL写入与SQS发送操作原子性实现方案
下面是3种落地性强的可行方案,可根据你的业务场景选择:
方案1:MySQL本地消息表(改造成本最低,优先推荐)
这个方案利用MySQL本地事务保证业务数据写入和消息记录写入的原子性,是分布式场景下保证双写一致性最常用的实现方式:
- 首先在你的RDS MySQL业务库中新增
pending_sqs_messages消息表,核心字段包括:自增ID、SQS消息体内容、发送状态(0=待发送、1=已发送)、创建时间、重试次数。 - 处理用户请求的Lambda开启数据库事务,先写入业务数据,再往上述消息表插入一条状态为待发送的SQS消息记录,两个操作在同一个事务内提交,要么同时成功要么同时失败,从根源避免数据写入成功但消息未记录的问题。
- 事务提交成功后,立即调用SQS接口发送对应消息,发送完成后将消息表对应记录状态更新为已发送,或直接删除记录。
- 新增一个定时触发的Lambda(建议触发间隔1~5分钟,可根据业务容忍的同步延迟调整),扫描消息表中创建时间超过阈值(比如30秒)且仍为待发送状态的记录,重试发送SQS消息,重试次数达到上限后触发告警通知人工处理。
方案2:CDC binlog监听(业务侵入性最低)
这个方案完全解耦业务逻辑和SQS发送逻辑,不需要修改现有业务Lambda的核心流程:
- 原有业务Lambda只需要负责写入RDS MySQL,不需要处理SQS发送逻辑。
- 开通RDS的binlog订阅,使用AWS DMS服务或者开源工具Debezium监听业务表的插入事件,监听到新数据写入时自动生成SQS消息发送到指定队列。
- 原有消费SQS同步ES的Lambda逻辑保持不变。
这个方案的优势是只要数据成功写入RDS,就一定会生成对应的SQS消息,可靠性非常高,缺点是需要额外维护CDC链路,适合业务逻辑已经定型,不方便修改核心代码的场景。
方案3:Step Functions分布式编排+回滚
这个方案不需要修改数据库结构,适合不允许新增业务表的场景:
- 将「写入RDS」「发送SQS」两个操作编排到AWS Step Functions工作流中,配置错误回滚逻辑:如果SQS发送失败,自动执行回滚步骤,删除/软标记之前写入RDS的业务数据。
- 给Step Functions配置失败告警,出现回滚失败的异常场景时通知人工介入处理。
要注意这个方案需要你的业务支持幂等回滚操作,避免回滚过程中出现异常导致数据不一致。
通用注意事项
- 所有消费SQS的逻辑必须做幂等校验,建议使用业务数据的唯一主键作为幂等Key,写入ES前先判断数据是否已存在,避免SQS重复投递导致ES出现脏数据。
- 给SQS配置死信队列(DLQ),超过最大重试次数的消息自动转入死信队列存储,定期巡检死信队列避免数据丢失。
内容的提问来源于stack exchange,提问作者Ahmad Nabil
相关产品推荐
相关产品推荐

