RabbitMQ(六)消息的持久化

目录

    • 一、简介
      • 1.1 定义
      • 1.2 消息丢失的场景
    • 二、交换机的持久化
      • 方式一:直接 new
      • 方式二:channel.exchangeDeclare()
      • 方式三:ExchangeBuilder【推荐】
    • 三、队列的持久化
      • 方式一:直接 new
      • 方式二:channel.queueDeclare()
      • 方式三:QueueBuilder【推荐】
    • 四、消息的持久化
      • 方式一:channel.basicPublish()
      • 方式二:rabbitTemplate.convertAndSend()【推荐】
    • 五、持久化问题

在这里插入图片描述

一、简介

1.1 定义

  • 持久化: 是为了提高 RabbitMQ 消息的可靠性,防止在异常情况(重启宕机)下数据的丢失。
  • RabbitMQ 持久化分为三部分:交换机的持久化队列的持久化消息的持久化

1.2 消息丢失的场景

出现消息丢失的场景有:

  • 生产者发送消息丢失:发送消息到 RabbitMQ Server 异常。 可能因为网络问题造成 RabbitMQ 服务端无法收到消息。——解决方案:ConfirmCallback
  • 生产者发送消息丢失:消息无法路由到指定队列。 可能由于代码层面或配置层面错误导致消息路由到指定队列失败。——解决方案:ReturnCallback
  • RabbitMQ Server 存储消息丢失:消息未完全持久化到磁盘。 可能因为 RabbitMQ 宕机导致消息未完全持久化,或队列丢失从而导致消息丢失等持久化问题。——解决方案:集群部署,实现高可用
  • 消费者消费消息丢失:消费者消费消息异常。 可能在消费者接收消息后,还没来得及消费消息,消费者就发生宕机、故障等问题。——解决方案:消费端手动确认消息

二、交换机的持久化

方式一:直接 new

直接实例化对应的 Exchange 实现类即可,默认:持久化的、非自动删除的

@Bean
public DirectExchange directExchange() {return new DirectExchange(directExchange);
}

Exchange 源码:

package org.springframework.amqp.core;public abstract class AbstractExchange extends AbstractDeclarable implements Exchange {...public AbstractExchange(String name) {// 默认是持久化的、非自动删除的。this(name, true, false);}...
}

方式二:channel.exchangeDeclare()

在 RabbitMQ 的原生 API 中,例如:Java 客户端 API,声明持久化交换机时,需要将 durable 参数设置为 true

// 声明交换机:(交换机名称,交换机类型,持久化)
channel.exchangeDeclare("myExchange", "direct", true);

方式三:ExchangeBuilder【推荐】

在 Spring AMQP 中,我们可以使用 ExchangeBuilder 来创建持久化的交换机:

import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.ExchangeBuilder;Exchange exchange = ExchangeBuilder.directExchange("myExchange").durable(true) // 交换机持久化.build();

三、队列的持久化

方式一:直接 new

直接实例化 Queue 类即可,默认:持久化的、非独占的、非自动删除的

@Bean
public Queue myQueue() {return new Queue("myQueue");
}

Queue 源码:

package org.springframework.amqp.core;public Queue(String name) {// 默认是持久化的、非独占的、非自动删除的。this(name, true, false, false);
}

方式二:channel.queueDeclare()

在原生 RabbitMQ API 中,例如 Java 客户端 API,声明持久化队列时,需要将 durable 参数设置为 true

// 声明队列:(队列名称,持久化,非独占,非自动删除,可选队列参数)
channel.queueDeclare("myQueue", true, false, false, null);

方式三:QueueBuilder【推荐】

在 Spring AMQP 中,可以使用 QueueBuilder 来创建持久化的队列:

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;Queue queue = QueueBuilder.durable("myQueue").build();

四、消息的持久化

即使队列时持久化的,发送到队列中的消息默认情况下 可能仍然是非持久化的。要使消息持久化,需要在发送消息时设置消息属性为持久化。

方式一:channel.basicPublish()

在原生 RabbitMQ API 中,例如 Java 客户端 API,声明持久化消息时,需要将 deliveryMode 参数设置为 2

import com.rabbitmq.client.AMQP;AMQP.BasicProperties props = new AMQP.BasicProperties.Builder().deliveryMode(2) // 这里2对应MessageDeliveryMode.PERSISTENT.build();// 参数:(交换机,路由键,消息的其他参数,消息体)
channel.basicPublish("myExchange", "myRoutingKey", props. messageBytes);

或者,我们可以直接使用 MessageProperties.PERSISTENT_TEXT_PLAIN 来进行指定消息的持久化:

import com.rabbitmq.client.MessageProperties;// 参数:(交换机,路由键,消息的其他参数,消息体)
channel.basicPublish("myExchange", "myRoutingKey", MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());

方式二:rabbitTemplate.convertAndSend()【推荐】

在 Spring AMQP 中,可以使用 rabbitTemplate.convertAndSend() 来创建持久化的消息:

rabbitTemplate.convertAndSend("myQueue", body, message -> {message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);return message;
});

通过上述步骤,消息会被持久化存储,只要队列也被正确配置为持久化,即使 RabbitMQ 服务器重启,消息也将被保留下来。

补充:

然而,即使队列和消息都是持久化的,也不能完全保证消息的 100% 不丢失。例如:在消息尚未被刷写到磁盘时,RabbitMQ 服务器突然崩溃,这种情况下的消息仍然可能会丢失。此外,RabbitMQ 不保证消息的立即持久化,而是尽可能快地将消息保存到磁盘


五、持久化问题

思考:将交换机、队列、消息都设置持久化之后就能保证数据不会丢失吗?

答:当然不能,需要从多方面考虑:

  • 场景1: 如果消费者订阅队列的时候将 autoAck(自动确认)设置为 true,虽然消费者接收到了消息,但是没有来得及处理就宕机了,那消息也会丢失。

    解决方案: 将消费者的消息确认机制改为手动确认,带处理完消息之后,手动删除消息。

  • 场景2: 在 RabbitMQ 服务器,如果消息正确被发送,但是 RabbitMQ 服务器中的消息还没来得及持久化,即没有将数据写入磁盘时,如果服务器发生异常,消息也会丢失。

    解决方案: 可以 通过 RabbitMQ 集群的方式实现消息中间件的高可用

因此,还需要做好生产者和消费者的 消息确认机制 以及通过 集群 的方式来实现 RabbitMQ 的高可用。

整理完毕,完结撒花~ 🌻





参考地址:

1.RabbitMQ保证消息可靠性,https://www.cnblogs.com/auguse/articles/17712620.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/613815.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎么样检查自己系统上的Python环境中是否有某个包(扩展库)?

比如我们这里想看下有没有库pytz 很简单,进入Python的命令行,然后输入下面的命令: import pytz如果有这个库,则不会报错,否则会报错。 Windows的测试结果如下: Centos的测试结果如下:

Hive分区表实战 - 多分区字段

文章目录 一、实战概述二、实战步骤(一)创建学校数据库(二)创建省市分区的大学表(三)在本地创建数据文件1、创建四川成都学校数据文件2、创建四川泸州学校数据文件3、创建江苏南京学校数据文件4、创建江苏苏…

字节8年经验之谈!一文从0到1带你入门接口测试【建议收藏】

扫盲内容: 1.为什么要做接口测试? 2.怎样做接口测试? 3.接口测测试点是什么? 4.接口测试都要掌握哪些知识? 5.其他相关知识? 一.为什么要做接口测试? ①.越底层发现bug,它的修…

5G之味,在烟火长沙

今年夏天,有一部电影叫做《长沙夜生活》。影片讲述了长沙大排档中的一些故事。网红大排档的老板娘、厨师、顾客,他们的邂逅、热爱、留下、离开、和解、团圆,都发生在一段夜色里,发生在充满烟火气的长沙城。 有没有想过这样一个问题…

线性表入门

王有志,一个分享硬核Java技术的互金摸鱼侠加入Java人的提桶跑路群:共同富裕的Java人 从今天开始就进入到数据结构的部分了,整体分为3个部分:线性表,树和图,从认识每种数据结构到它们的高级应用。今天我们先…

C# Linq+ValueTuple(元祖),成为Linq高手!

文章目录 前言简单使用:能被2整除ValueTuple使用:两数相加等于4不使用元祖使用元祖排序 基于类的LinqGroupByJoinDistinct去重普通去重选择去重 集合去重ExceptIntersectUnion 总结 前言 Linq是C# 最强语法之一,和委托,get set并列(在我的心中)。我很早就听说了Lin…

基于JavaWeb+BS架构+SpringBoot+Vue智能停车计费系统的设计和实现

基于JavaWebBS架构SpringBootVue智能停车计费系统的设计和实现 文末获取源码Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 文末获取源码 Lun文目录 1 绪 论 1 1.1 研究背景 1 1.2 研究意义 1 1.3 系统主要功能 1 1.4 拟解决…

【HDFS】想不到NameNode的异步EditLog竟然这么多细节

文末会总结异步edit log实现里的细节: 1、Edit对象什么时候为RpcEdit?什么时候为SyncEdit? 2、enqueueEdit里,阻塞队列满导致插入失败进行限流时,针对线程是否持有当前对象锁做了不同处理,那么什么时候持有锁?什么时候没持有锁呢? 3、SyncEdit的生成 4、怎么启动FSEdit…

Blazor快速开发框架Known-V2.0.0

Known2.0 Known是基于Blazor的企业级快速开发框架,低代码,跨平台,开箱即用,一处代码,多处运行。 官网:http://known.pumantech.comGitee: https://gitee.com/known/KnownGithub:ht…

Ubuntu22.04开机左上角下划线闪烁不开机

按下CtrlAltF2,打开TTY系统,然后通过用户名和密码登录,随后使用 sudo apt --fix-broken install 根据提示排除错误信息,然后使用apt安装lightdm安装就行。 tips:当使用EasyConnect的时候,你可能参考了下面这篇文章知…

130基于MATLAB并结合IBD算法的盲迭代反卷积法进行图像复原

基于MATLAB并结合IBD算法的盲迭代反卷积法进行图像复原 ,输出复原前后图像,PSF频谱结果。程序已调通,可直接运行。 130 matlab盲迭代反卷积IBD (xiaohongshu.com)

面试经典题---68.文本左右对齐

68.文本左右对齐 我的解法: 两层while循环嵌套,外层循环用于处理不同行,内层while循环计算出每行应有的单词个数。 使用left和right记录一行中应有的单词下标,即当前行应包含从words[left]到words[right-1]这count个单词&#xf…

C端接口安全性设计

针对C端接口,app未登录也可以查询数据的需求点;从安全角度上仍然需要进行校验: 方案一: 后期http 修改为 https; 方案二: Aop切面需要的接口;客户端和后端都执行以下规则: 1.客…

第28关 k8s监控实战之Prometheus(七)

大家好,我是博哥爱运维。 今天继续Prometheus的课程,在之前的几节课里面,我带大家认识并部署了prometheus服务,并将一些服务做好了监控,同时通过grafana展示监控数据图表出来。对于怎么使用promql语法,也教…

XML的用途之一:XML把数据从HTML分离

XML 应用于 web 开发的许多方面,常用于简化数据的存储和共享。 XML 把数据从 HTML 分离 如果你需要在 HTML 文档中显示动态数据,那么每当数据改变时将花费大量的时间来编辑 HTML。 通过 XML,数据能够存储在独立的 XML 文件中。这样你就可以…

【Kafka-3.x-教程】-【三】Kafka-Broker、Kafka-Kraft

【Kafka-3.x-教程】专栏: 【Kafka-3.x-教程】-【一】Kafka 概述、Kafka 快速入门 【Kafka-3.x-教程】-【二】Kafka-生产者-Producer 【Kafka-3.x-教程】-【三】Kafka-Broker、Kafka-Kraft 【Kafka-3.x-教程】-【四】Kafka-消费者-Consumer 【Kafka-3.x-教程】-【五…

【Redis】Redis持久化方式

Redis 中有两种持久化方式,分别为 RDB 和 AOF。 RDB RDB 全称 Redis Database Backup file,也叫做 Redis 数据快照。简单来说就是把 Redis 中的数据记录到磁盘中。当 Redis 实例故障重启后,从磁盘读取快照文件,恢复数据。 RDB有…

2024.1.11力扣每日一题——构造有效字符串的最少插入数

2024.1.11 题目来源我的题解方法一 暴力模拟方法二 动态规划方法三 直接拼接方法四 计算组数 题目来源 力扣每日一题;题序:2645 我的题解 方法一 暴力模拟 直接模拟,根据题意可知 若是abc则不用插入,若是ab,ac,bc这需要 插入一…

ESP32S3+HX8347+RGB运行LVGL例程

之前用3线SPI驱动的HX8347屏其实是一个RGB屏,SPI只是用来给RGB屏幕的做配置的,当然也可以用来驱动屏幕,但是3线SPI驱动能力终究有限。本文谈一下用RGB方式来驱动。 RGB接线比较多,为此做了个转接板: 一、源码 1、scre…

油烟净化器餐饮油烟污染“克星”

我最近分析了餐饮市场的油烟净化器等产品报告,解决了餐饮业厨房油腻的难题,更加方便了在餐饮业和商业场所有需求的小伙伴们。 随着人们生活水平的提高,餐饮业也得到了快速发展。然而,餐饮油烟污染也成为了人们关注的焦点。 油烟…