RabbitMQ持久化与高可用
概述
持久化可以提高RabbitMQ的可靠性,RabbitMQ的持久化可以分为三个部分:交换机持久化、队列持久化、消息持久化。高可用通过集群来实现,分为普通集群和镜像集群。
持久化
交换机持久化
通过设置durable
参数为true即可实现交换机持久化。directExchange1
是持久化的,durableExchange2
没有做持久化。
@Bean
public Exchange directExchange1() {
return ExchangeBuilder.directExchange("durableExchange1").durable(true).build();
}
@Bean
public Exchange directExchange2() {
return ExchangeBuilder.directExchange("durableExchange2").durable(false).build();
}
队列持久化
通过设置durable
参数为true即可实现交换机持久化。
/**
* 队列持久化
* @return
*/
@Bean
public Queue AMessage() {
return QueueBuilder.durable("direct.a").build();
}
/**
* 队列没有做持久化
* @return
*/
@Bean
public Queue BMessage() {
return QueueBuilder.nonDurable("direct.b").build();
}
消息持久化
通过MessagePostProcessor
可将消息持久化,代码如下:
MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
// 设置消息持久化
message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
return message;
}
};
注意
可以将所有的消息都设置为持久化,但是这样会严重影响RabbitMQ的性能(随机)。写入磁盘的速度比写入内存的速度慢得不只一点点。对于可靠性不是那么高的消息可以不采用持久化处理以提高整体的吞吐量。在选择是否要将消息持久化时,需要在可靠性和吐吞量之间做一个权衡
高可用
将交换器、队列、消息都设置了持久化之后并不能百分之百保证数据不丢失,从消费者来说,如果在订阅消费队列时将 autoAck
参数设置为true ,那么当消费者接收到相关消息之后,还没来得及处理就看机了,这样也算数据丢失。这种情况很好解决,将autoAck 参数设置为false并进行手动确认。
在持久化的消息正确存入 RabbitMQ 之后,还需要有一段时间(虽然很短,但是不可忽视〉才能存入磁盘之中。 RabbitMQ 并不会为每条消息都进行同步存盘(调用内核的fsync方法)的处理,可能仅仅保存到操作系统缓存之中而不是物理磁盘之中。如果在这段时间内RabbitMQ 服务节点发生了岩机、重启等异常情况,消息保存还没来得及落盘,那么这些消息将丢失。因这个问题需要通过RabbitMQ镜像集群解决。
集群分类
- 标准集群:是一种分布式集群,将队列分散到集群的各个节点,从而提高整个集群的并发能力,消息数据不会在各节点之间同步,某节点挂了后对应的数据将会丢失,一般很少适用。
- 镜像集群:是一种主从集群,标准集群的基础上,添加了主从备份功能(非强一致性),提高集群的数据可用性。
- 仲裁队列:是3.8版本以后才有的新功能,用来替代镜像集群,也是一种主从集群,主从同步基于Raft协议,强一致。
部署可参考:https://www.cnblogs.com/zhouganqing/p/14814362.html
一般生产环境使用镜像集群和仲裁队列更多。