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

news2024/11/30 2:31:00

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/626048.html

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

相关文章

Mysql中联合索引的最左匹配

联合索引 通过将多个字段组合成一个索引&#xff0c;该索引就被称为联合索引。 比如&#xff0c;将商品表中的 product_no 和 name 字段组合成联合索引(product_no, name)&#xff0c;创建联合索引的方式如下&#xff1a; CREATE INDEX index_product_no_name ON product(pr…

尝试用Go goroutine实现一个简单的聊天服务

hello&#xff0c;大家好&#xff0c;我是张张&#xff0c;「架构精进之路」公号作者。 对于聊天服务&#xff0c;想必大家都不会陌生&#xff0c;因为在我们的生活中经常会用到。 我们用 Go 并发来实现一个聊天服务器&#xff0c;这个程序可以让一些用户通过服务器向其它所有用…

总有人问我 Cookie 是什么?

苏生不惑第432 篇原创文章&#xff0c;将本公众号设为星标&#xff0c;第一时间看最新文章。 之前分享过我写的微博批量下载工具2023 更新版&#xff1a;苏生不惑开发过的那些原创工具和脚本 &#xff0c;因为要输入自己账号的cookie&#xff0c;总有人问我cookie是什么?今天写…

FPGA 的数字信号处理:重写 FIR 逻辑以满足时序要求

在上一篇文章中&#xff08;FPGA 的数字信号处理&#xff1a;Verilog 实现简单的 FIR 滤波器&#xff09;演示了在 Verilog 中编写自定义 FIR 模块的初始demo。该项目在行为仿真中正常&#xff0c;但在布局和布线时未能满足时序要求。 所以今天的文章让我们来看看当设计不能满足…

Nacos集群Raft反序列化漏洞-修复

近日&#xff0c;奇安信CERT监测到 Nacos 集群Raft反序列化漏洞(QVD-2023-13065)&#xff0c;在Nacos集群处理部分Jraft请求时&#xff0c;攻击者可以无限制使用hessian进行反序列化利用&#xff0c;最终实现代码执行。鉴于该漏洞仅影响集群间通信端口 7848(默认配置下)&#x…

计算机网络管理-实验6-使用SNMPc开展网管活动

一、实验目的 全面学习SNMPc网络管理软件业务服务监控功能&#xff0c;了解如何使用网管软件从事网络管理工作 二、实验内容与设计思想 1&#xff09;操作映射数据库。 2&#xff09;查看管理对象的MIB数据。 3&#xff09;创建、保存长期统计数据&#xff08;要求一定时长…

spring事务隔离

在数据库中读取数据时&#xff0c;可能会遇到以下三个常见的问题&#xff1a;脏读&#xff08;Dirty Read&#xff09;、不可重复读&#xff08;Non-repeatable Read&#xff09;和幻读&#xff08;Phantom Read&#xff09;。 这些问题主要涉及并发事务的隔离性和一致性。 脏…

ChatGPT 4 的 6 个最佳使用场景

作者&#xff1a;SYDNEY BUTLER 译者&#xff1a;明明如月 无论是在 ChatGPT 中还是通过 API&#xff0c;对 OpenAI 的 GPT-4 模型的访问比 GPT-3.5 限制更多。这意味着你需要慎重考虑在何种情况下使用 GPT-4&#xff0c;并选择性地将最适合的任务交给它&#xff0c;以便让其发…

来薅羊毛!阿里云 AI 神器公测了

阿里云 AI 神器「通义听悟」上线了&#xff0c;宣称是身边的 AI 学习助手。这名字听着挺玄乎的&#xff0c;老逛也去试了一下&#xff0c;确实解决了之前遇到的很多问题。 01 视频转文字 老逛是小破站的资深用户&#xff0c;喜欢几个不错的 UP 主&#xff0c;比如老蒋&#xff…

sklearn中的roc_auc_score(二分类或多分类)

官方API地址&#xff1a; sklearn.metrics.roc_auc_score — scikit-learn 1.2.2 documentationExamples using sklearn.metrics.roc_auc_score: Release Highlights for scikit-learn 0.22 Release Highlights for scikit-learn 0.22 Probability Calibration curves Probabi…

AI创作与大语言模型:2023亚马逊云科技中国峰会引领企业应用新潮流

川川出品&#xff0c;必属精品。 文章目录 CodeWhispere免费的代码生成器安装教程使用自动编码 2023亚马逊云科技中国峰会最后总结 CodeWhispere免费的代码生成器 这里我介绍亚马逊云科技的一个产品&#xff0c;那就是Amazon codewhisperer。大家肯定对AI各种产品的火爆已经有…

F/S系统分分钟系统秒变BS/CS,但共享文件夹上的DBF访问掉了个坑

接VFP MIX ALL社群狐友求助&#xff0c;说IIS访问共享文件夹的DBF出错了&#xff1a; 猫猫复现了一下错误: 错误号1705 不能访问DBF表 这个问题估计还是会有很多狐友会遇到这个问题&#xff0c;那么我们就来解决一下吧. 在服务器上面建好共享文件夹 \\newserver\dbf 里面放一个…

开源项目|EasyOCR一款实用的图片OCR文字识别项目

欢迎关注「全栈工程师修炼指南」公众号 点击 &#x1f447; 下方卡片 即可关注我哟! 设为「星标⭐」每天带你 基础入门 到 进阶实践 再到 放弃学习&#xff01; “ 花开堪折直须折&#xff0c;莫待无花空折枝。 ” 作者主页&#xff1a;[ https://www.weiyigeek.top ] 博客&…

一级建造师执业资格考试--工程经济--速学36记--联想法

第一记&#xff1a;利息的计算 第二记&#xff1a;等值计算 第三记&#xff1a;名义利率与有效利率 第四记&#xff1a;经济效果评价指标体系 第五记&#xff1a;静态投资回收期分析 第六记&#xff1a;静态投资回收期分析 第七记&#xff1a;预付款 第八记&#xff1a;施工索赔…

2023年深圳某互联网公司前端开发初级岗笔试真题(含解析和源码)

&#x1f4da;关于该专栏: 该专栏的发布内容是前端面试中笔试部分真题、答卷类、机试等等的题目&#xff0c;题目类型包括逻辑题、算法题、选择题、问答题等等&#xff0c;除了内容的分享&#xff0c;还有解析和答案。真实来自某些互联网公司&#xff0c;坐标广东广州、深圳。 …

如何使用Python Flask和MySQL创建管理用户的REST API

部分数据来源&#xff1a;ChatGPT 引言 在现代化的应用开发中&#xff0c;数据库是一个非常重要的组成部分。关系型数据库&#xff08;例如&#xff1a;MySQL、PostgreSQL&#xff09;在这方面尤其是很流行。Flask是一个Python的web框架&#xff0c;非常适合实现REST API。在…

NLP学习笔记六-lstm模型

NLP学习笔记六-lstm模型 上一篇我们讲的是simple RNN模型&#xff0c;那么其实lstm模型更像是simple RNN模型的改进或者变种。 对于lstm模型&#xff0c;我们先看下面一张图&#xff1a; 其实lstm模型的思想是建立在simple RNN模型上的&#xff0c;但是要更加贴近于显示&…

内网安全:内网渗透.(拿到内网主机最高权限 vulntarget 靶场 A)

内网安全&#xff1a;内网渗透.&#xff08;拿到内网主机最高权限&#xff09; 内网穿透又被称为NAT穿透&#xff0c;内网端口映射外网&#xff0c;在处于使用了NAT设备的私有TCP/IP网络中的主机之间建立连接的问题。通过映射端口&#xff0c;让外网的电脑找到处于内网的电脑。…

数据分析第19课pyecharts布局(基础图形绘制)

官网:https://pyecharts.org/#/zh-cn/global_options?id=legendopts%ef%bc%9a%e5%9b%be%e4%be%8b%e9%85%8d%e7%bd%ae%e9%a1%b9 不想每个属性方法的看,可以直接看gallery 官网的数据都是静态的,如果要做数据实时更新的,即做前后端结合时,会用到Vue框架,与后端连接,实现动…

Nacos架构与原理 - CAP一致性协议 ( Raft Distro)

文章目录 为什么 Nacos 需要⼀致性协议为什么 Nacos 选择了 Raft 以及 Distro从服务注册发现来看从配置管理来看为什么是 Raft 和 Distro &#xff1f;Raft (CP模式)Distro &#xff08;AP模式&#xff09; Nacos ⼀致性协议的演进早期的 Nacos ⼀致性协议当前 Nacos 的⼀致性协…