所有栏目 | 云社区 美国云服务器[国内云主机商]
你的位置:首页 > 云社区 » 正文

RabbitMQ如何通过持久化保证消息99.99%不丢失?

发布时间:2020-04-15 16:13:20

资讯分类:rabbitmq  持久化  丢失  保证  消息  持久  丢失
RabbitMQ如何通过持久化保证消息99.99%不丢失?

当下主流的消息系统有RabbitMQ、RocketMQ、ActiveMQ等,而RabbitMQ是基于Erlang开发,无论是并发、延时表现都很好。

RabbitMQ消息可靠性是靠什么实现的?

消息可靠性是RabbitMQ的一大特点,RabbitMQ靠什么实现消息可靠性的呢?其实就是通过消息持久化来实现的,这样就避免了服务异常(重启、宕机)下消息和队列丢失的风险。

消息持久化是指RabbitMQ将内存中的数据(交换器Exchange、队列Queue、消息Message)落地到硬盘中存储,以防止异常情况导致内存中的数据丢失。

RabbitMQ如何实现消息持久化?

RabbitMQ中不同数据持久化方式是不同的,主要有:

1、交换器(Exchange)的持久化

交换器Exchange若丢失会影响后续消息的写入,我们在创建Exchange时需要指定durable为true表示持久化

2、队列(Queue)的持久化

在上面第一步操作中,在创建交换器时即使设置了durable为true后,Exchange不会丢失,但是里面的队列依旧会丢失。如何保证队列持久化呢?同样是在创建队列时指定durable为true即可。

3、消息(Message)的持久化

上面两步操作后,在重启RabbitMQ后,虽然Exchange和Queue不会丢失,但是Queue里的消息是会丢失的,那如何保证消息持久化不丢失呢?我们设置消息投递模式(deliveryMode)为2即代表消息持久化

消息持久化并不能100%保证数据不丢失

当我们将交换器/队列/消息都设置了持久化依旧不能100%保证数据不会丢失。这其实很好理解,内存中的数据写入硬盘是要时间的,突然断电、宕机重启等情况时消息可能没来得及落地,那么这些消息就有丢失的可能。

消息持久化会带来性能问题

我们知道消息持久化是将内存中的数据写入硬盘中,但硬盘的读写速度远不如内存,所以开启消息持久化后会影响RabbitMQ的性能


以上就是我的观点,对于这个问题大家是怎么看待的呢?欢迎在下方评论区交流 ~ 我是科技领域创作者,十年互联网从业经验,欢迎关注我了解更多科技知识!

RabbitMQ如何通过持久化保证消息99.99%不丢失?

在单台服务器的情况下,开启消息的持久化,并且客户端采用confirm模式,还是可能会丢。这是因为master收到消息存储到文件后,就发送ack给客户端了,问题关键是存储到文件,只是写到磁盘缓存,需要执行fsync才会真正的写到磁盘。如果在fsync之前宕机了,消息还是会丢失的。如果设置写文件时马上fsync,就不会丢失消息,但是性能会差很多倍。

那在集群情况下呢,设置ha-mode为all,所有的mirror节点都同步到消息了,master才响应ack给客户端。那么需要所有的节点包括master都在同一瞬间宕机,才有可能丢失消息。所以只存在理论上的丢失消息,可靠性达99.999...

RabbitMQ如何通过持久化保证消息99.99%不丢失?

rabbitmq本身是运行在内存中的,高速的同时,也意味着一旦断电等故障,消息会从内存中丢失,因此,我们需要做持久化,下面说下rabbitmq如何保证消息99.99%

持久化

就像一开始我们介绍的那样,消息队列是在内存中的,因此我们需要将消息持久化到硬盘等存储,再之后,我们再从硬盘恢复数据

ack确认

一条消息发送之后,让消费者发送一个确认信息,如果没有收到确认消息,服务端就保存这条信息,直到收到消费者确认信息之后,才从内存中将数据删除

备份模式

就是对消息队列进行镜像备份,类似于mysql的主从复制,当一个节点出问题了,可以使用备份的节点继续进行消息传输

日志记录

任何消息都会有意外,这时候我们通过日志就可以进行数据分析,补偿之前有问题的消息

多备份,多记录,就像我们平时写日志做的那样,记录的越详细,越能找到问题,当然记录多少要适度。

RabbitMQ如何通过持久化保证消息99.99%不丢失?

1. 前言

如何保证RabbitMQ异常情况(人为重启、异常宕机等)下,队列和消息不丢失?

2. 本篇概要

要解决该问题,就要用到RabbitMQ中持久化的概念,所谓持久化,就是RabbitMQ会将内存中的数据(Exchange 交换器,Queue 队列,Message 消息)固化到磁盘,以防异常情况发生时,数据丢失。

其中,RabblitMQ的持久化分为三个部分:

交换器(Exchange)的持久化

队列(Queue)的持久化

消息(Message)的持久化

3. 交换器(Exchange)的持久化

在上篇博客中,我们声明Exchange的代码是这样的:

private final static String EXCHANGE_NAME = "normal-confirm-exchange";

// 创建一个Exchange

channel.exchangeDeclare(EXCHANGE_NAME, "direct");

这种情况下声明的Exchange是非持久化的,在RabbitMQ出现异常情况(重启,宕机)时,该Exchange会丢失,会影响后续的消息写入该Exchange,那么如何设置Exchange为持久化的呢?答案是设置durable参数。

durable:设置是否持久化。durable设置为true表示持久化,反之是非持久化。

持久化可以将交换器存盘,在服务器重启的时候不会丢失相关信息。

设置Exchange持久化:

channel.exchangeDeclare(EXCHANGE_NAME, "direct RabbitMQ如何通过持久化保证消息99.99%不丢失?

rabbitmq本身会把消息存储在磁盘上,搭建集群即可实现高可用。

留言与评论(共有 0 条评论)
   
验证码:
Top