RabbitMQ之如何保障数据不丢失

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MrLiar17/article/details/86491068

1、费者实例宕机的时候,如何保障数据是不会丢失?

手动ack机制非常的简单,必须要消费者确保自己处理完毕了一个消息,才能手动发送ack给MQ,MQ收到ack之后才会删除这个消息,如果消费者还没发送ack,消费者自己就宕机了,此时MQ感知到它的宕机,就会重新投递这条消息给其他的消费者实例。通过这种机制保证消费者实例宕机的时候,数据是不会丢失的。

如果采用手动ack机制,实际上消费者服务每次消费了一条消息,处理完毕完成消费之后,就会发送一个ack消息给RabbitMQ服务器,这个ack消息是会带上自己本次消息的delivery tag的。

这里大家必须注意的一点,就是delivery tag仅仅在一个channel内部是唯一标识消息投递的。所以说,你ack一条消息的时候,必须是通过接受这条消息的同一个channel来进行。

channel.basicAck(
            delivery.getEnvelope().getDeliveryTag(), 
            false);//表给示消费者成功消费,返回给MQ

2、分析手动ack和默认自动ack区别?

①实际上默认用自动ack,是非常简单的。RabbitMQ只要投递一个消息出去给仓储服务,那么他立马就把这个消息给标记为删除,因为他是不管消费者服务到底接收到没有,或者处理完没有。所以这种情况下,性能很好,但是数据容易丢失

②如果手动ack,那么就是必须等消费者服务完成消费以后,才会手动发送ack给RabbitMQ,此时RabbitMQ才会认为消息处理完毕,然后才会标记消息为删除。这样在发送ack之前,消费者服务宕机,RabbitMQ会重发消息给另外一个消费者服务实例,保证数据不丢

3、如何保证生产者投递到消息中间件(MQ)的消息不丢失?

问题:如果投递出去的消息在网络传输过程中丢失,或者在RabbitMQ的内存中还没写入磁盘的时候宕机,都会导致生产端投递到MQ的数据丢失。而且丢失之后,生产者自己还感知不到,同时还没办法来补救。

生产者需要开启confirm模式,投递消息到MQ,如果MQ一旦将消息持久化到磁盘之后,必须也要回传一个confirm消息给生产端。这样的话,如果生产端的服务接收到了这个confirm消息,就知道是已经持久化到磁盘了。如果没有接收到confirm消息,那么就说明这条消息半路可能丢失了,此时你就可以重新投递消息到MQ去,确保消息不要丢失。

而且一旦你开启了confirm模式之后,每次消息投递也同样是有一个delivery tag的,也是起到唯一标识一次消息投递的作用。这样,MQ回传ack给生产端的时候,会带上这个delivery tag。你就知道具体对应着哪一次消息投递了,可以删除这条消息。

此外,如果RabbitMQ接收到一条消息之后,结果内部出错发现无法处理这条消息,那么MQ会回传一个nack消息给生产者。此时生产者就会感知到这条消息可能处理有问题,你可以选择重新再次投递这条消息到MQ去。

或者另一种情况,如果某条消息很长时间都没给你回传ack/nack,那可能是极端意外情况发生了,数据也丢了,你也可以自己重新投递消息到MQ去。

4、confirm机制投递消息的高延迟性

一旦启用了confirm机制投递消息到MQ之后,MQ是不保证什么时候会给你一个ack或者nack的。

因为RabbitMQ自己内部将消息持久化到磁盘,本身就是通过异步批量的方式来进行的。正常情况下,你投递到RabbitMQ的消息都会先驻留在内存里,然后过了几百毫秒的延迟时间之后,再一次性批量把多条消息持久化到磁盘里去。这样做,是为了兼顾高并发写入的吞吐量和性能的,因为要是你来一条消息就写一次磁盘,那么性能会很差,每次写磁盘都是一次fsync强制刷入磁盘的操作,是很耗时的。

那如何解决呢?

绝对不能以同步写消息 + 等待ack的方式来投递消息,用来临时存放未ack消息的存储需要承载高并发写入,而且我们不需要什么复杂的运算操作,这种存储首选绝对不是MySQL之类的关系数据库,而建议采用kv存储。kv存储承载高并发能力极强,而且kv操作性能很高。

生产者消息投递出去之后并且在kv存储器存储,这个投递的线程其实就可以返回了,至于每个消息的异步回调,是通过在channel注册一个confirm监听器实现的。生产者收到一个消息ack之后,就从kv存储中删除这条临时消息;收到一个消息nack之后,就从kv存储提取这条消息然后重新投递一次即可;也可以自己对kv存储里的消息做监控,如果超过一定时长没收到ack,就主动重发消息。

猜你喜欢

转载自blog.csdn.net/MrLiar17/article/details/86491068
今日推荐