mq消息积压中，突然mq挂了，或者mysql挂了，或者两个都挂了怎么处理？
我们小伙伴应该都听说够消息中间件MQ，如：RabbitMQ，RocketMQ，Kafka等。引入中间件的好处可以起到抗高并发，削峰，业务解耦的作用。 如上图： 我们这篇文章讨论一下，如何保障订单服务把消息成功投递给MQ中间件，以RabbitMQ举例。 PS: 如果是RocketMQ到底该如何保证消息幂性？如何保证消息不被重复消费？参考：https://zhuanlan.zhihu.com/p/409652956 小伙伴们对此会有些疑问，订单服务发起消息服务，返回成功不就成功了吗？如下面的伪代码   上面代码中，一般发送消息就是这么写的，小伙伴们觉得有什么问题吗？ 老顾说一个场景，如果MQ服务器突然宕机了会出现什么情况？是不是我们订单服务发过去的消息全部没有了吗？是的，一般MQ中间件为了提高系统的吞吐量会把消息保存在内存中，如果不作其他处理，MQ服务器一旦宕机，消息将全部丢失。这个是业务不允许的，造成很大的影响。 有经验的小伙伴会说，我知道一个方法就是把消息持久化，RabbitMQ中发消息的时候会有个durable参数可以设置，设置为true，就会持久化。  这样的话MQ服务器即使宕机，重启后磁盘文件中有消息的存储，这样就不会丢失了吧。是的这样就一定概率的保障了消息不丢失。 但还会有个场景，就是消息刚刚保存到MQ内存中，但还没有来得及更新到磁盘文件中，突然宕机了。（我靠，这个时间这么短，也会出现，概率太低了吧），这个场景在持续的大量消息投递的过程中，会很常见。 那怎么办？我们如何作才能保障一定会持久化到磁盘上面呢？ 上面问题出现在，没有人告诉我们持久化是否成功。好在很多MQ有回调通知的特性，RabbitMQ就有confirm机制来通知我们是否持久化成功？   confirm机制的原理：  上面的伪代码，有两个处理消息方式，就是ack回调和nack回调。 这样是不是就可以保障100%消息不丢失了呢？ 我们看一下confirm的机制，试想一下，如果我们生产者每发一条消息，都要MQ持久化到磁盘中，然后再发起ack或nack的回调。这样的话是不是我们MQ的吞吐量很不高，因为每次都要把消息持久化到磁盘中。写入磁盘这个动作是很慢的。这个在高并发场景下是不能够接受的，吞吐量太低了。 所以MQ持久化磁盘真实的实现，是通过异步调用处理的，他是有一定的机制，如：等到有几千条消息的时候，会一次性的刷盘到磁盘上面。而不是每来一条消息，就刷盘一次。 所以comfirm机制其实是一个异步监听的机制，是为了保证系统的高吞吐量，这样就导致了还是不能够100%保障消息不丢失，因为即使加上了confirm机制，消息在MQ内存中还没有刷盘到磁盘就宕机了，还是没法处理。 说了这么多，还是没法确保，那怎么办呢？？？ RabbitMQ到底是保证消息可靠性投递和消费的？ 其实本质的原因是无法确定是否持久化？那我们是不是可以自己让消息持久化呢？答案是可以的，我们的方案再一步的演化。  上图流程： 这样的机制其实就是一个补偿机制，我不管MQ有没有真正的接收到，只要我的redis中的消息状态也是为【发送中】，就表示此消息没有正确成功投递。再启动定时任务去监控，发起补偿投递。 当然定时任务那边我们还可以加上一个补偿的次数，如果大于3次，还是没有收到ack消息，那就直接把消息的状态设置为【失败】，由人工去排查到底是为什么？ 这样的话方案就比较完美了，保障了100%的消息不丢失（当然不包含磁盘也坏了，可以做主从方案）。 不过这样的方案，就会有可能发送多次相同的消息，很有可能MQ已经收到了消息，就是ack消息回调时出现网络故障，没有让生产者收到。那就要要求消费者一定在消费的时候保障幂等性。至于什么是幂等性，如何设计幂等？ 如果你的Rabbitmq 消息发送是失败了，如何解决——100%投递的解决方案:https://zhuanlan.zhihu.com/p/364418823 PS：如果想学习技术，或者在学习技术的过程中有疑问，对编程方向的选择，可以来这里找小于哥，一个有思想有规划，被代码延误的心灵导师，可咨询offer的选择，职业规划，学习路线，技术开发中的问题 我是终端研发部的小于哥 @终端研发部 每天专注技术开发小技巧，技术教程进阶，职场经验，面试的分享，希望我的回答能够帮助到你哈，笔芯~