rabbitmq持久化,防止在异常情况(重启,关闭,宕机)下数据的丢失

本文详细介绍了RabbitMQ中的消息持久化,包括交换器、队列和消息的持久化设置,以及如何通过设置autoAck和使用Confirm机制来增强数据可靠性。同时提到了镜像队列和事务机制作为进一步的数据安全保障策略。
摘要由CSDN通过智能技术生成

rabbitmq持久化:持久化是为提高rabbitmq消息的可靠性,防止在异常情况(重启,关闭,宕机)下数据的丢失

1.交换器(exchange)的持久化
上面阐述了队列的持久化和消息的持久化,如果不设置exchange的持久化对消息的可靠性来说没有什么影响,但是同样如果exchange不设置持久化,
那么当broker服务重启之后,exchange将不复存在,那么既而发送方rabbitmq producer就无法正常发送消息。这里博主建议,同样设置exchange的持久化。
exchange的持久化设置也特别简单,方法如下:

xchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable) throws IOException;
Exchange.DeclareOk exchangeDeclare(String exchange, String type, boolean durable, boolean autoDelete,
                                   Map<String, Object> arguments) throws IOException;
Exchange.DeclareOk exchangeDeclare(String exchange, String type) throws IOException;
Exchange.DeclareOk exchangeDeclare(String exchange,
                                          String type,
                                          boolean durable,
                                          boolean autoDelete,
                                          boolean internal,
                                          Map<String, Object> arguments) throws IOException;
void exchangeDeclareNoWait(String exchange,
                           String type,
                           boolean durable,
                           boolean autoDelete,
                           boolean internal,
                           Map<String, Object> arguments) throws IOException;
Exchange.DeclareOk exchangeDeclarePassive(String name) throws IOException;

一般只需要:channel.exchangeDeclare(exchangeName, “direct/topic/header/fanout”, true);即在声明的时候讲durable字段设置为true即可。

2.队列对持久化:
在声明队列名称时,持久化队列,生产端和消费端都要
 

channel.queue_declare(queue='hello', durable=True)

3.消息的持久化
我们刚才实现了在rabbitmq崩溃的情况下,就队列本身保存下来,重启后队列还在。接下来我们要将消息也保存下来,即消息的持久化

channel.basic_publish(exchange='',
                      routing_key='hello',
                      body='hello',
                      properties=pika.BasicProperties(
                          delivery_mode=2,  # make message persistent
                      ))
 

# 增加properties,这个properties 就是消费端 callback函数中的properties
# delivery_mode = 2  持久化消息
  生产端生成一个消息,并重启rabbitmq
    经过队列和消息持久化后的hello, 在重启的情况下,队列和消息都存在,没有消失。
  消费端再重启后也能正常接收

特别注意:

将queue,exchange, message等都设置了持久化之后并不能保证100%保证数据不丢失,因为这只是保证了消息可以不丢失且发送给消费者,但是万一消费者才拿到消息服务就挂掉了尼?
1.首先,从consumer端来说,如果这时autoAck=true,那么当consumer接收到相关消息之后,还没来得及处理就crash掉了,那么这样也算数据丢失,
这种情况也好处理,只需将autoAck设置为false(方法定义如下),然后在正确处理完消息之后进行手动ack(channel.basicAck).String basicConsume(String queue, boolean autoAck, Consumer callback) throws IOException;

2. 其次,关键的问题是消息在正确存入RabbitMQ之后,还需要有一段时间(这个时间很短,但不可忽视)才能存入磁盘之中,RabbitMQ并不是为每条消息都做fsync的处理,
可能仅仅保存到cache中而不是物理磁盘上,在这段时间内RabbitMQ broker发生crash, 消息保存到cache但是还没来得及落盘,那么这些消息将会丢失。
那么这个怎么解决呢?首先可以引入RabbitMQ的mirrored-queue即镜像队列,这个相当于配置了副本,当master在此特殊时间内crash掉,可以自动切换到slave,
这样有效的保障了HA, 除非整个集群都挂掉,这样也不能完全的100%保障RabbitMQ不丢消息,但比没有mirrored-queue的要好很多,很多现实生产环境下
都是配置了mirrored-queue的。

3.还有要在producer引入事务机制或者Confirm机制来确保消息已经正确的发送至broker端,有关RabbitMQ的事务机制或者Confirm机制

此处建议去看看另一篇,rabbitMQ的应答模式:https://blog.csdn.net/u013232219/article/details/109385386

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值