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