【RabbitMQ教程】第八章 —— RabbitMQ - 幂等性、优先级、惰性

news2024/11/25 17:51:40

在这里插入图片描述

                                                                  💧 【 R a b b i t M Q 教程】第八章—— R a b b i t M Q − 幂等性、优先级、惰性 \color{#FF1493}{【RabbitMQ教程】第八章 —— RabbitMQ - 幂等性、优先级、惰性} RabbitMQ教程】第八章——RabbitMQ幂等性、优先级、惰性💧          


🌷 仰望天空,妳我亦是行人.✨
🦄 个人主页——微风撞见云的博客🎐
🐳 《数据结构与算法》专栏的文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺
💧 《Java学习笔记》专栏的文章是本人在Java学习中总结的一些知识点~ 💐
🥣 《每天一点小知识》专栏的文章可以丰富你的知识库,滴水成河~ 🌊
🥕 《RabbitMQ》专栏的文章是在学习尚硅谷课程时整理的笔记,方便复习巩固~ 🍑
🪁 希望本文能够给读者带来一定的帮助~🌸文章粗浅,敬请批评指正!🐥


文章目录

  • 🌊RabbitMQ - 幂等性、优先级、惰性
    • 幂等性
    • 优先级队列
    • 惰性队列
  • 🐳结语


🌊RabbitMQ - 幂等性、优先级、惰性

幂等性

概念

用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。 举个最简单的例子,那就是支付,用户购买商品后支付,支付扣款成功,但是返回结果的时候网络异常, 此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额发现多扣钱 了,流水记录也变成了两条。在以前的单应用系统中,我们只需要把数据操作放入事务中即可,发生错误立即回滚,但是再响应客户端的时候也有可能出现网络中断或者异常等等

消息重复消费

消费者在消费 MQ 中的消息时,MQ 已把消息发送给消费者,消费者在给 MQ 返回 ack 时网络中断, 故 MQ 未收到确认信息,该条消息会重新发给其他的消费者,或者在网络重连后再次发送给该消费者,但实际上该消费者已成功消费了该条消息,造成消费者消费了重复的消息。

解决思路

MQ 消费者的幂等性的解决一般使用全局 ID 或者写个唯一标识比如时间戳 或者 UUID 或者订单消费者消费 MQ 中的消息也可利用 MQ 的该 id 来判断,或者可按自己的规则生成一个全局唯一 id,每次消费消息时用该 id 先判断该消息是否已消费过。

消费端的幂等性保障

在海量订单生成的业务高峰期,生产端有可能就会重复发生了消息,这时候消费端就要实现幂等性, 这就意味着我们的消息永远不会被消费多次,即使我们收到了一样的消息。

业界主流的幂等性有两种操作:a. 唯一 ID+指纹码机制,利用数据库主键去重, b.利用 redis 的原子性去实现

  • 唯一ID+指纹码机制

指纹码:我们的一些规则或者时间戳加别的服务给到的唯一信息码,它并不一定是我们系统生成的,基本都是由我们的业务规则拼接而来,但是一定要保证唯一性,然后就利用查询语句进行判断这个 id 是否存在数据库中,优势就是实现简单就一个拼接,然后查询判断是否重复;劣势就是在高并发时,如果是单个数据库就会有写入性能瓶颈当然也可以采用分库分表提升性能,但也不是我们最推荐的方式。

  • note Redis 原子性

利用 redis 执行 setnx 命令,天然具有幂等性。从而实现不重复消费

优先级队列

使用场景

在我们系统中有一个订单催付的场景,我们的客户在天猫下的订单,淘宝会及时将订单推送给我们,如果在用户设定的时间内未付款那么就会给用户推送一条短信提醒,很简单的一个功能对吧。

但是,tmall 商家对我们来说,肯定是要分大客户和小客户的对吧,比如像苹果,小米这样大商家一年起码能给我们创造很大的利润,所以理应当然,他们的订单必须得到优先处理,而曾经我们的后端系统是使用 redis 来存放的定时轮询,大家都知道 redis 只能用 List 做一个简简单单的消息队列,并不能实现一个优先级的场景,所以订单量大了后采用 RabbitMQ 进行改造和优化,如果发现是大客户的订单给一个相对比较高的优先级, 否则就是默认优先级。

如何添加?

a.控制台页面添加
在这里插入图片描述

b.队列中代码添加优先级

Map<String, Object> params = new HashMap();
params.put("x-max-priority", 10);
channel.queueDeclare("hello", true, false, false, params);

c.消息中代码添加优先级

AMQP.BasicProperties properties = new AMQP.BasicProperties().builder().priority(10).build();

注意事项:

要让队列实现优先级需要做的事情有如下事情:队列需要设置为优先级队列,消息需要设置消息的优先级,消费者需要等待消息已经发送到队列中才去消费因为,这样才有机会对消息进行排序

实战

生产者:

public class PriorityProducer {
    private static final String QUEUE_NAME = "hello";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();

        //给消息赋予一个 priority 属性
        AMQP.BasicProperties properties = new AMQP.BasicProperties().builder().priority(10).build();

        for (int i = 1; i < 11; i++) {
            String message = "info" + i;
            if (i == 5) {
                channel.basicPublish("", QUEUE_NAME, properties, message.getBytes());
            } else {
                channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
            }
            System.out.println("发送消息完成:" + message);
        }
    }

}

消费者:

public class PriorityConsumer {
    private final static String QUEUE_NAME = "hello";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();

        //设置队列的最大优先级 最大可以设置到 255 官网推荐 1-10 如果设置太高比较吃内存和 CPU
        Map<String, Object> params = new HashMap();
        params.put("x-max-priority", 10);
        channel.queueDeclare(QUEUE_NAME, true, false, false, params);

        //推送的消息如何进行消费的接口回调
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody());
            System.out.println(message);
        };
        //取消消费的一个回调接口 如在消费的时候队列被删除掉了
        CancelCallback cancelCallback = (consumerTag) -> {
            System.out.println("消息消费被中断");
        };

        channel.basicConsume(QUEUE_NAME, true, deliverCallback, cancelCallback);
    }

}

在这里插入图片描述

惰性队列

  • 使用场景

RabbitMQ 从 3.6.0 版本开始引入了惰性队列的概念。惰性队列会尽可能的将消息存入磁盘中,而在消费者消费到相应的消息时才会被加载到内存中,它的一个重要的设计目标是能够支持更长的队列,即支持更多的消息存储。当消费者由于各种各样的原因(比如消费者下线、宕机亦或者是由于维护而关闭等)而致使长时间内不能消费消息造成堆积时,惰性队列就很有必要了。

默认情况下,当生产者将消息发送到 RabbitMQ 的时候,队列中的消息会尽可能的存储在内存之中, 这样可以更加快速的将消息发送给消费者。即使是持久化的消息,在被写入磁盘的同时也会在内存中驻留一份备份。当RabbitMQ 需要释放内存的时候,会将内存中的消息换页至磁盘中,这个操作会耗费较长的时间,也会阻塞队列的操作,进而无法接收新的消息。虽然 RabbitMQ 的开发者们一直在升级相关的算法, 但是效果始终不太理想,尤其是在消息量特别大的时候。

  • 两种模式

队列具备两种模式:default 和 lazy。默认的为default 模式,在3.6.0 之前的版本无需做任何变更。lazy 模式即为惰性队列的模式,可以通过调用 channel.queueDeclare 方法的时候在参数中设置,也可以通过 Policy 的方式设置,如果一个队列同时使用这两种方式设置的话,那么 Policy 的方式具备更高的优先级。 如果要通过声明的方式改变已有队列的模式的话,那么只能先删除队列,然后再重新声明一个新的。

在队列声明的时候可以通过“x-queue-mode”参数来设置队列的模式,取值为“default”和“lazy”。下面示例中演示了一个惰性队列的声明细节:

Map<String, Object> args = new HashMap<String, Object>();
args.put("x-queue-mode", "lazy");
channel.queueDeclare("myqueue", false, false, false, args);

  • 内存开销对比

在这里插入图片描述
在发送 1 百万条消息,每条消息大概占 1KB 的情况下,普通队列占用内存是 1.2GB,而惰性队列仅仅 占用 1.5MB


在这里插入图片描述


🐳结语

🐬初学一门技术时,总有些许的疑惑,别怕,它们是我们学习路上的点点繁星,帮助我们不断成长。

🐟文章粗浅,希望对大家有帮助!

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

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

相关文章

chatgpt赋能python:Python调试技巧:如何使用断点运行程序

Python调试技巧&#xff1a;如何使用断点运行程序 在Python编程中&#xff0c;程序出现错误或需要调试时&#xff0c;我们需要一些工具来帮助我们定位问题和修复代码。其中之一就是使用断点来运行程序。接下来我们将讨论如何在Python中使用断点进行程序调试的相关技巧。 什么…

C++11核心特性---右值引用(代码+讲解)

右值引用C11 1.左值和右值2.左值引用3.右值引用4.右值引用的性能优化空间5.移动语义6.值类别7.将左值转化为右值8.万能引用和引用折叠9.完美转发10.针对局部变量和右值引用的隐士类型转换11.总结 今天看到谢丙堃老师的《现代C语言核心特性解析》一书中关于右值引用的介绍&#…

21.网络编程|Java学习笔记

文章目录 网络的相关概念ipv4地址分类网路通信协议TCP和UDP InetAdress类SocketTCP网络通信编程应用案例服务端客户端 netstat指令TCP网络通讯不为人知的秘密 UDP网络通信编程【了解】网络传输文件代码示例 网络的相关概念 网络通信 网络 ip地址 1. 概念:用于唯一标识网络…

【数据库原理与应用 - 第七章】数据库安全性和完整性控制

目录 一、数据库安全性控制 二、数据库完整性控制 三、课后习题 数据库的保护功能&#xff1a;数据库安全性、完整性、数据库恢复、并发控制 一、数据库安全性控制 数据库的安全性&#xff1a;保护数据库&#xff0c;以防止非授权用户非法存取造成的数据泄密、更改、破坏DBM…

Python开发中的常见问题和解决方法:如何解决常见的性能和bug问题

第一章&#xff1a;引言 在Python开发中&#xff0c;我们经常会遇到一些常见的问题&#xff0c;包括性能瓶颈和程序错误&#xff08;bug&#xff09;。这些问题可能会影响我们的应用程序的运行效率和稳定性。因此&#xff0c;了解这些问题的根源并学习解决方法是非常重要的。本…

IDEA集成GitHub - Gitee集成

GitHub 集成 实际的开发中&#xff0c;代码都是采用IDE进行开发&#xff0c;所以我们这里介绍一下IDEA软件是如何集成GitHub远程仓库进行代码版本控制的。这里采用的IDEA版本为2022.2.1,其他版本的IDEA软件会略有差别。 1、 配置 Git 软件 2、 配置 GitHub 账号 继续点授权按…

三.数据类型

目录 1、布尔类型 2、整数类型 3、浮点数类型 4、字符类型 5、字符串类型 6、类型转换 1、布尔类型 Go语言中的布尔类型与其他语言基本一致&#xff0c;关键字也为bool&#xff0c;可赋值为预定义的true和false 示例代码如下&#xff1a; var v1 bool v1 true v2 :…

【TCP/IP】利用I/O复用技术实现并发服务器 - select函数

目录 I/O复用技术 select函数 设置文件描述符 指定监视范围 设置超时 I/O复用服务器端的实现 由服务器创建多个进程来实现并发的做法有时会带来一些问题&#xff0c;比如&#xff1a;内存上的开销、CPU的大量占用等&#xff0c;这些因素会消耗掉服务器端有限的计算资源、…

chatgpt赋能python:Python中如何更新pip版本

Python中如何更新pip版本 Python是一种非常强大的编程语言&#xff0c;它在现代编程领域中广泛使用。使用Python的好处之一是能够轻松地在其上安装和使用各种库&#xff0c;其中许多库由Python包管理器pip&#xff08;pip-installs-packages&#xff09;提供。尽管pip可以使Py…

新建的springboot 项目往往删除(1).mvn(2) .gitignore(3) HELP.md (4)mvnw (5)mvnw.cmd 文件

问题 新建的springboot 项目&#xff0c;项目开发人员往往删除&#xff08;1&#xff09;.mvn&#xff08;2&#xff09; .gitignore&#xff08;3&#xff09; HELP.md &#xff08;4&#xff09;mvnw &#xff08;5&#xff09;mvnw.cmd 文件&#xff0c;这些文件是什么&…

康耐视3D相机-DSMAX-VisionPro软件安装向导

机器视觉Halcon-字符识别 一. 系统需求 PC最小需求. OS: Win7 Pro/8Pro/10Pro X64 . Memory: 4GB RAM . PCIe 槽:X4 Gen2 一个 . 显存大小大于1GB 注意:1)PCIe插槽推荐使用x4 Gen 3; 软件版本VisionPro 9.2 CR1 X64/VisionPro 9.5及以上版本+ VisionPro_9_2_CR1_64-bit_…

合宙Air724UG Cat.1模块硬件设计指南--开关机

开关机 简介 模块支持上电后的开机、关机、复位三种状态&#xff0c;本章节会对其进行相应的介绍。 特性 PWRKEY&#xff1a; VILmin0V&#xff0c;VILmax0.5V&#xff0c;推荐值0.1V以下&#xff1b; 引脚状态&#xff1a;模块供电后PWRKEY内部拉高&#xff0c;满足低电平输入…

【哈佛积极心理学笔记】第22讲 自尊与自我实现

第22讲 自尊与自我实现 Unconditional self-esteem is the highest level, the level that Maslow would talk about “the self-actualization”, what David Schnarch talks about as “differentiated” or at the level of being known rather than desiring to be valida…

chatgpt赋能python:Python怎样使用断言?

Python怎样使用断言&#xff1f; 在Python中&#xff0c;断言是一种在程序执行中自动检查程序是否具有给定条件的方法。在程序的开发和调试过程中&#xff0c;通过正确使用断言&#xff0c;可以增强代码的可靠性并提升编程效率。 Python中的断言语法 Python中的断言语法非常…

CRC校验(2):CRC32查表法详解、代码实现及CRC反转

对于现在的CPU来说&#xff0c;基本上都在硬件上实现了CRC校验。但我们还是想用软件来实现一下CRC的代码&#xff0c;这样可以更深入地理解里面的原理。所以这一节就来详细地解释如何使用查表法从软件上来实现CRC-32的校验。另外&#xff0c;CRC还有一种反转的情况&#xff0c;…

MongoDB入门笔记

MongoDB入门笔记 1.MongoDB简介 MongoDB是一个开源、高性能、无模式的文档型数据库&#xff0c;当初的设计就是用于简化开发和方便扩展&#xff0c;是NoSQL数据库产品中的一种。是最像关系型数据库&#xff08;MySQL&#xff09;的非关系型数据库。 它支持的数据结构非常松散…

LuatOS-Air AT应用指南--CMUX

目录 简介 语法规则 参数定义 简介 CMUX是指串口多路复用。串口的多路复用器模式&#xff0c;就是使一个串行接口能够将数据传输到四个不同的客户应用程序。 要在Linux下使用模块的CMUX功能&#xff0c;需要在内核中开启相应的支持&#xff0c;开启方法见下图 将Air724UG开…

flink学习文档四 checkpoint机制

目的 checkpoint作为flink保障任务稳健运行的一个重要机制&#xff0c;在日常使用和flink 学习框架图 简单创建一个FlinkKafkaConsumer kafka是大数据中常用的消息存储中间件&#xff0c;也是flink任务中最常用的source源之一&#xff0c;因此flink 也为 kafka提供了内置的连接…

(UE5 5.2)HISM Mobile DrawInstance在渲染层的实现浅分析

在 (UE4 4.27) UHierarchicalInstancedStaticMesh(HISM)原理分析 这篇博客大致介绍HISM组件从游戏线程到渲染线程的重建KD-Tree和剔除并提交DrawCall逻辑&#xff0c;但是没有分析渲染层的大致数据结构和实现. FHierarchicalStaticMeshSceneProxy的相关数据结构 可以看出FHier…

YOLOv5改进系列(9)——替换主干网络之EfficientNetv2

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制