RabbitMQ 消息持久化

news2024/11/25 20:51:48

RabbitMQ 消息持久化

持久化是为提高rabbitmq消息的可靠性,防止在异常情况(重启,关闭,宕机)下数据的丢失。设置完队列和消息的持久化,并不能完全保证消息不会丢失。尽管它告诉 RabbitMQ 将消息保存到磁盘,但当 RabbitMQ 接受消息但尚未保存消息时,仍有一个较短的时间窗口。另外, RabbitMQ 不会对每条消息都执行 fsync(2) – 它可能只是保存到缓存中,而不是真正写入磁盘。持久性保证并不强,但对于我们的简单任务队列来说已经足够了。如果您需要更强的保证,则可以使用发布者确认(RabbitMQ 消息确认机制)。

首先定义好获取RabbitMQ连接的工具类

/**
 * 类描述:
 * 连接工具类
 * @author cfl
 * @version 1.0
 * @date 2022/10/10 13:49
 */
public class ConnectionUtil {

    /**
     * 获取MQ的连接
     * @return
     */
    public static Connection getConnection() throws IOException, TimeoutException {
        // 定义一个连接工厂
        ConnectionFactory factory = new ConnectionFactory();

        // 设置服务地址
        factory.setHost("localhost");

        // AMQP 5672
        factory.setPort(5672);

        // vhost
        factory.setVirtualHost("/vhost01");

        // 用户名
        factory.setUsername("admin");

        // 密码
        factory.setPassword("123456");

        return factory.newConnection();
    }

}

重启RabbitMQ服务

下面介绍几种重启RabbitMQ的方法:

  1. 使用 rabbitmq-service(前提是使用rabbitmq-service install安装RabbitMQ服务)
D:\application\rabbitmq\rabbitmq_server-3.10.8\sbin>rabbitmq-service stop
RabbitMQ 服务正在停止...
RabbitMQ 服务已成功停止。


D:\application\rabbitmq\rabbitmq_server-3.10.8\sbin>rabbitmq-service start
RabbitMQ 服务正在启动 .
RabbitMQ 服务已经启动成功。
  1. net命令
D:\application\rabbitmq\rabbitmq_server-3.10.8\sbin>sc query RabbitMQ

SERVICE_NAME: RabbitMQ
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0

D:\application\rabbitmq\rabbitmq_server-3.10.8\sbin>net stop RabbitMQ
RabbitMQ 服务正在停止...
RabbitMQ 服务已成功停止。


D:\application\rabbitmq\rabbitmq_server-3.10.8\sbin>net start RabbitMQ
RabbitMQ 服务正在启动 .
RabbitMQ 服务已经启动成功。
  1. 使用 rabbitmq-server(前提RabbitMQ是以rabbitmq-server -detached启动)
    启动服务:rabbitmq-server -detached
    重启服务:rabbitmq-server restart
    关闭服务:rabbitmqctl stop
    查看状态:rabbitmqctl status

交换机开启持久化

RabbitMQ只有队列才有存储消息的能力,也就是说只要队列和消息开启了持久化,那么交换机开不开都不影响,但是为了统一规则,也可以将交换机申明成持久化:

// true申明为持久化的交换机
channel.exchangeDeclare("test_durable_exchange", BuiltinExchangeType.DIRECT, true);

如果交换机不申明持久化,那么当RabbitMQ重启的时候,交换机会丢失(不会影响队列和消息)。

队列关闭持久化

总结:如果生产者在定义队列时将其设置关闭持久化,那么在RabbitMQ重启服务时,队列和消息都会丢失。

示例:

/**
 * 类描述:
 * 队列不持久化
 * @author cfl
 * @version 1.0
 * @date 2022/10/13 21:55
 */
public class Send1 {
    //~fields
    //==================================================================================================================
    public static final String QUEUE_NAME = "test_durable_queue";
    //~methods
    //==================================================================================================================
    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = ConnectionUtil.getConnection();

        Channel channel = connection.createChannel();
        // 申明队列,关闭持久化(durable=false)
        boolean durable = false;
        channel.queueDeclare(QUEUE_NAME, durable, false, false, null);

        for (int i = 0; i < 50; i++) {
            String message = "hello durable " + i;
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
        }

        System.out.println("send durable end");

        channel.close();
        connection.close();
    }
}

运行上面代码,运行完成后查看RabbitMQ的队列信息:

在这里插入图片描述

可以看到,队列被创建了,并且有50条消息

重启RabbitMQ服务后,可以看到刚刚创建的队列,消息都不存在了。

在这里插入图片描述

队列开启持久化

总结:如果生产者在定义队列时将其设置开启持久化,那么在RabbitMQ重启服务时,队列依然存在,但是消息全都丢失了。

示例:

/**
 * 类描述:
 * 队列持久化
 * @author cfl
 * @version 1.0
 * @date 2022/10/13 21:55
 */
public class Send2 {
    //~fields
    //==================================================================================================================
    public static final String QUEUE_NAME = "test_durable_1_queue";
    //~methods
    //==================================================================================================================
    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = ConnectionUtil.getConnection();

        Channel channel = connection.createChannel();
        // 申明队列,开启持久化(durable=true)
        boolean durable = true;
        channel.queueDeclare(QUEUE_NAME, durable, false, false, null);

        for (int i = 0; i < 50; i++) {
            String message = "hello durable " + i;
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
        }

        System.out.println("send durable end");

        channel.close();
        connection.close();
    }
}

运行上面代码,运行完成后查看RabbitMQ的队列信息:

在这里插入图片描述

重启RabbitMQ服务后,可以看到队列依然存在,但是队列中的消息已经丢失了

在这里插入图片描述

如果RabbitMQ已经对队列进行申明,如果我们再次申明队列时,修改了申明队列的参数,那么会出现错误。

队列开启持久化 - 消息开启持久化

总结:队列和消息都开启了持久化,RabbitMQ服务重启后,队列和消息都会恢复。

队列持久化参考上面的代码,首先我们先查看发送消息的源码的常用API(一共有三个):

/**
  * Publish a message. 发布消息
  *
  * Publishing to a non-existent exchange will result in a channel-level
  * protocol exception 发布到不存在的交换器会导致通道级协议异常,从而关闭通道, which closes the channel.
  *
  * Invocations of <code>Channel#basicPublish</code> will eventually block if a
  * <a href="https://www.rabbitmq.com/alarms.html">resource-driven alarm</a> is in effect. 如果资源驱动的警报 生效, Channel#basicPublish的调用最终将被阻塞。
  *
  * @see com.rabbitmq.client.AMQP.Basic.Publish
  * @see <a href="https://www.rabbitmq.com/alarms.html">Resource-driven alarms</a>
  * @param exchange the exchange to publish the message to  将消息发布到的交换机
  * @param routingKey the routing key  路由键
  * @param props other properties for the message - routing headers etc 消息的其他属性 - 路由标头等
  * @param body the message body 消息正文
  * @throws java.io.IOException if an error is encountered
  */
void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException;

创建 BasicProperties对象props:
方式一:
自己创建BasicProperties对象

AMQP.BasicProperties basicProperties = new AMQP.BasicProperties()
                // deliveryMode=1表明不持久化消息;deliveryMode=2表明持久化消息
                .builder().deliveryMode(2)
                .build();

方式二:
使用com.rabbitmq.client.MessageProperties类中定义的6个静态成员变量:

/**
 * Constant holder class with useful static instances of {@link AMQContentHeader}.
 * These are intended for use with {@link Channel#basicPublish} and other Channel methods.
 */
public class MessageProperties {

    /** Empty basic properties, with no fields set 空的基本属性,没有设置字段*/
    public static final BasicProperties MINIMAL_BASIC =
        new BasicProperties(null, null, null, null,
                            null, null, null, null,
                            null, null, null, null,
                            null, null);
    /** Empty basic properties, with only deliveryMode set to 2 (persistent) 空的基本属性,只有 deliveryMode 设置为 2(持久)*/
    public static final BasicProperties MINIMAL_PERSISTENT_BASIC =
        new BasicProperties(null, null, null, 2,
                            null, null, null, null,
                            null, null, null, null,
                            null, null);

    /** Content-type "application/octet-stream", deliveryMode 1 (nonpersistent), priority zero 内容类型“application/octet-stream”,deliveryMode 1(非持久),优先级为零*/
    public static final BasicProperties BASIC =
        new BasicProperties("application/octet-stream",
                            null,
                            null,
                            1,
                            0, null, null, null,
                            null, null, null, null,
                            null, null);

    /** Content-type "application/octet-stream", deliveryMode 2 (persistent), priority zero 内容类型“application/octet-stream”,deliveryMode 2(持久),优先级为零*/
    public static final BasicProperties PERSISTENT_BASIC =
        new BasicProperties("application/octet-stream",
                            null,
                            null,
                            2,
                            0, null, null, null,
                            null, null, null, null,
                            null, null);

    /** Content-type "text/plain", deliveryMode 1 (nonpersistent), priority zero 内容类型“text/plain”,deliveryMode 1(非持久),优先级为零*/
    public static final BasicProperties TEXT_PLAIN =
        new BasicProperties("text/plain",
                            null,
                            null,
                            1,
                            0, null, null, null,
                            null, null, null, null,
                            null, null);

    /** Content-type "text/plain", deliveryMode 2 (persistent), priority zero 内容类型“text/plain”,deliveryMode 2(持久),优先级为零*/
    public static final BasicProperties PERSISTENT_TEXT_PLAIN =
        new BasicProperties("text/plain",
                            null,
                            null,
                            2,
                            0, null, null, null,
                            null, null, null, null,
                            null, null);
}

生产者代码:

/**
 * 类描述:
 * 队列持久化,消息持久化
 * @author cfl
 * @version 1.0
 * @date 2022/10/13 21:55
 */
public class Send3 {
    //~fields
    //==================================================================================================================
    public static final String QUEUE_NAME = "test_durable_3_queue";
    //~methods
    //==================================================================================================================
    public static void main(String[] args) throws IOException, TimeoutException {
        Connection connection = ConnectionUtil.getConnection();

        Channel channel = connection.createChannel();
        // 申明队列,开启持久化(durable=true)
        boolean durable = true;
        channel.queueDeclare(QUEUE_NAME, durable, false, false, null);

        // 自定义消息属性,设置持久化消息(deliveryMode=2)
        AMQP.BasicProperties basicProperties = new AMQP.BasicProperties()
                // deliveryMode=1表明不持久化消息;deliveryMode=2表明持久化消息
                .builder().deliveryMode(2)
                .build();

        for (int i = 0; i < 50; i++) {
            String message = "hello durable " + i;
            channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
        }

        System.out.println("send durable end");

        channel.close();
        connection.close();
    }
}

运行上面的程序,运行完成后查看RabbitMQ的队列信息:

在这里插入图片描述

重启RabbitMQ服务后,可以看到队列依然存在,队列中的消息也恢复了:

在这里插入图片描述

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

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

相关文章

mapbox-gl添加threejs飞线

文章目录前言飞线实现1 初始化地图并加载three图层2 绘制飞线几何体将几何体正确定位在mapbox上正确操作BufferGeometry几何体3 tween实现动画全部代码总结待改进之处参考前言 mapbox-gl是一个基于webgl开发的三维地图渲染引擎&#xff0c;但是很多三维特效只用mapbox并不容易…

【CSDN 年终总结】CSDN的进阶之路—— “1+1=王”的2022总结

正文之前打个广告&#xff0c;我正在参加年度博客之星评选&#xff0c;请大家帮我投票打分&#xff0c;您的每一分都是对我的支持与鼓励。⭐ ⭐ ⭐ ⭐ ⭐https://bbs.csdn.net/topics/611386885?spm1001.2014.3001.6953 2022我在CSDN 2022 在CSDN是持续输出&#xff0c;持续…

TinyPng图片压缩的正确打开方式

https://tinypng.com/ TinyPNG使用智能的「有损压缩技术」来减少WEBP、JPEG和PNG文件的文件大小。通过选择性地减少图像中的「颜色数量」&#xff0c;使用更少的字节来存储数据。这种效果几乎是看不见的&#xff0c;但在文件大小上有非常大的差别。 使用过TinyPNG的都知道&…

MyBatis 万字长文:从入门到动态SQL超详细

文章目录1. 前言2. 创建项目3. 添加框架支持4. 建库5. 配置数据库连接信息和 XML 文件路径5.1 创建 Java 类5.2 Java 接口5.3 XML 文件6. 查询6.1 不带参数的查询6.2 单元测试6.3 带参数的查询7. 修改8. 增加8.1 将对象插入表中8.2 获取自增主键9. 删除10. 数据库字段和类属性名…

Video2StyleGAN: Disentangling Local and Global Variations in a Video翻译

点击下载论文 代码地址 摘要 使用预训练的StyleGAN生成器进行图像编辑已成为面部编辑的强大范例&#xff0c;它提供了对年龄、表情、照明度等的解纠缠控制。然而&#xff0c;该方法不能直接用于视频操作。我们认为主要因素是缺乏对面部位置、面部姿势和局部面部表情的精细和清…

腾讯云-云服务器购买流程-Java项目部署(详细的一批)

文章目录云服务器购买云服务搭建部署环境宝塔面板使用&#xff08;安装所需环境&#xff09;部署SpringBoot项目出现Error: Unable to access jarfile /www/wwwroot/xxxx.jar--server.port6066 问题解决腾讯云COS有什么用&#xff1f;如果感觉有用就一键三连吧&#xff0c;创作…

Electron 实现切换暗_亮模式与主题

文章末尾附上仓库地址&#xff01;&#xff01;&#xff01;&#xff01; 清单 模板基于 electron-vite-vue vue3 ts vite组件库 element-plushooks库 vueuse 、useElementPlusTheme 初始化工程 使用 electron-vite 作为模板&#xff0c;方便大家尽快吧项目跑起来 # 创建模…

Java面试之数据库篇

一、基础 1.数据库事务的特征ACID 原子性&#xff08;Atomicity&#xff09;&#xff1a;原子性是指事务包含的所有操作要么全部成功&#xff0c;要么全部失败回滚&#xff0c;这和前面两篇博客介绍事务的功能是一样的概念&#xff0c;因此事务的操作如果成功就必须要完全应用…

UOS服务器操作系统多版本Java切换

一、修改java的环境变量和软链接来实现版本切换 1、配置环境变量 sudo vim &#xff5e;/.bashrc 2、创建java运行程序软连接 3、使配置生效&#xff0c;并检查java版本 source /etc/profile 二、使用update-alternatives 进行版本的切换 1、同时安装了openjdk-8-jdk 和…

shell第七天作业——awk

题目 1、获取根分区剩余大小 2、获取当前机器ip地址 3、统计出apache的/var/log/httpd/access_log文件中访问量最多的前3个IP 4、打印/etc/passwd中UID大于500的用户名和uid 5、/etc/passwd 中匹配包含root或sys或tcp的任意行 6、请打印出/etc/passwd 第一个域&#xff0…

指针进阶之数组参数和指针参数

文章目录一、回顾1.字符指针2.指针数组和数组指针&#xff08;1&#xff09;指针数组&#xff08;2&#xff09;数组指针二、数组参数1.一维数组传参&#xff08;1&#xff09;整型数组&#xff08;2&#xff09;指针数组&#xff08;3&#xff09;总结2.二维数组传参&#xff…

基于Python tensorflow2.3实现的水果识别系统源码+模型+数据集,卷积神经网络的入门案例

水果识别-基于tensorflow2.3实现 水果识别是卷积神经网络的入门案例&#xff0c;这里我将模型的训练、测试、保存以及使用整合在了一起&#xff0c;至于原理部分&#xff0c;大家可以参考知乎或者B站上的回答&#xff0c;在这里我就不赘述了 完整代码下载地址&#xff1a;基于…

计算机网络实验---验证性实验

实验一/ipconfig 实作一 实作二 实验二/ping 实作一 实作二 实验三/tracert 实作一 实作二 实验四/ARP 实作一 实作二 实作二 实验五/DHCP 实作一 实验六/netstat 实作一 实作二 实验七/DNS 实作一 实作二 实作二 实验八/cache 实作一 实作二 总结 实验一/ipconfig 实…

[Leetcode] 二叉树的遍历

转载自&#xff08;有删减和少量改动&#xff09; 图解二叉树的四种遍历 https://leetcode.cn/problems/binary-tree-preorder-traversal/solution/tu-jie-er-cha-shu-de-si-chong-bian-li-by-z1m/1. 相关题目144.二叉树的前序遍历 https://leetcode.cn/problems/binary-tree-p…

【SpringMVC 入门教程】

SpringMVC_day02 &#x1f308;博客主页&#xff1a;屠一乐的博客 &#x1f4c5; 发文时间&#xff1a;2023.1.5 &#x1f388; 一定存在只有你才能做成的事 &#x1f339; 博主水平有限&#xff0c;如有错误&#xff0c;欢迎指正 欢迎各位&#x1f44d;收藏&#x1f48e;评论✉…

MacBookPro安装mysql遇到的几个问题

用Mac的好处是不用开关机&#xff0c;无弹窗无广告&#xff0c;坏处是在安装某些第三方的软件时&#xff0c;总是和视频教程上的winows版不一致&#xff0c;需要自己上网找资料尝试怎么安装。今天学python&#xff0c;需要安装mysql&#xff0c;幸好网上有一些文章&#xff0c;…

Vulnhub靶机:MISDIRECTION_ 1

目录介绍信息收集主机发现主机信息探测网站探测反弹shell方式1&#xff1a;使用nc方式2&#xff1a;使用bash方式3&#xff1a;使用MSF提权sudo提权passwd提权docker提权参考介绍 系列&#xff1a;Misdirection&#xff08;此系列共1台&#xff09; 发布日期&#xff1a;2019 …

【ClickHouse】从Mysql迁移到ClickHouse大全

从关系型的数据库(Mysql)升级到列式管理的联机分析型数据库(ClickHouse)&#xff0c;这不亚于是小米加步枪升级为加特林机关枪的性能提升了&#xff0c;查询能力等确实是大大的提升了&#xff0c;这出现了一个问题我们之前存储在Mysql里的历史数据怎么往ClickHouse里面迁移呢&a…

访问者模式Visitor

1.意图&#xff1a;表示一个作用于某对象结构中的各元素的操作。它允许在不改变各元素的类的前提下定义作用于这些元素的操作。 2.结构 Visitor&#xff08;访问者&#xff09;为该对象结构中ConcreteElement的每一个类声明一个Visit操作。该操作的名字和特征标识了发送Visit请…

本地机器 Google Colab 通过 SSH 连接远程服务器

1. 情景描述 我自己笔记本配置太垃圾&#xff0c;想要用学校的深度学习服务器在Colab上跑程序。 2. 环境描述 远程服务器 (Ubuntu)&#xff1a; 用pip安装 jupyter notebook 以及 jupyter_http_over_ws 拓展包 (前提有python环境和pip) pip install notebookpip install j…