开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第24天,点击查看活动详情
RabbitMQ应用问题:消息可靠性保障
消息补偿机制
需求:100%确保消息发送成功
简单回答就是:把消息写到数据库里
2 消息幂等性保证
什么是幂等性
幂等性指一次和多次请求某一个资源,对于资源本身应该具有同样的效果,也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同
在MQ中指,消费多条相同的消息,得到与消费该消息一次相同的结果
比如我话费100元给mq记录,由于网络问题发送了10次,那么最终mq应该只记录一次100元,而不是10次1000元
数据库乐观锁解决方案
1.业务数据入库
在发送消息前,先将消息入库
2.发送消息 发送消息m到消息队列Q1,Consumer监听到Q1的消息m后,消费消息m,并将消息m入库。然后发送确认消息给Q2,回调检查服务监听到Consumer反馈的确认消息后,也将消息写入数据库MDB。这是消息发送成功的正常情况。
倘若:发送消息失败,那么Consumer消费不到消息,Consumer的消息入库操作也失败了。这时也不用担心,因为在我们发送消息m后,过了几分钟后也会进行延迟发送消息m的副本给Q3,回调检查服务监听到延迟消息后,与MDB中的进行比对,MDB中没有消息m的记录,这说明Consumer消费消息m失败,那么回调检查服务就远程调用Producer跟它说一下再重发消息m,又重新进行上面消息发送的步骤。
几率很小的发送消息失败情况:
发送消息失败,延迟发送消息也失败。。。 这时定时检查服务会将消息数据库MDB中与业务数据库DB进行比对,然后让producer重发缺失的消息。
解决接口幂等性
全局唯一ID + Redis
生产者在发送消息时,为每条消息设置一个全局唯一的messageId,消费者拿到消息后,使用setnx命令,将messageId作为key放到redis中:setnx(messageId,1),若返回1,说明之前没有消费过,正常消费;若返回0,说明这条消息之前已消费过,抛弃。
※ setnx命令,若给定的key不存在,执行set操作,返回1,若给定的Key已存在,不做任何操作,返回0。