RabbitMQ交换机使用场景和消息可靠性总结分析
作者:失败的面 发布时间:2023-10-06 14:00:55
RabbitMQ的一些基本组件
Producer:消息的生产者
Consumer:消息的消费者
Broker:MQ服务器,管理队列、消息
Message:消息,程序间通讯的数据
Queue:队列,消息存放的容器,消息先进先出
Exchange:交换机,用于分发消息
各种类型交换机的使用场景
扇形交换机(Fanout)
发布/订阅模式,类似于广播,交换机将收到的消息发给多个队列,消费者如果订阅了这个队列的话,就可以收到生产者的消息。生产者不直接与队列绑定,而且将数据发送至交换机Exchange。
扇形交换机不需要路由键,设置了也没有作用。
使用场景
如天气预报信息,生产者将天气预报信息发送到交换机,网易、新浪等门户通过各自队列绑定到该交换机,来获取推送的消息。
扇形交换机发布一次可以让所有消费者收到,但有时候我们需要进行一些数据集筛选,比如我只想接收关于广东省的天气预报,其他省份的忽略,那么我们就需要用到路由或者主题交换机模式。
直连交换机(Direct)
路由模式,通过路由键进行匹配,Exchange交换机会根据路由键(RoutingKey)有条件的将数据筛选后发送给队列
使用场景
日志收集系统,收集了info、warn、error三种类型日志,要发送给对应的队列做处理,如info队列做记录,warn和error队列在info队列基础上还要发送邮件给运维人员,那么可以创建一个直连交换机(Direct),然后绑定三个路由键:INFO、WARN、ERROR到三个队列。
路由模式是一种精准匹配,只有设置了RoutingKey才可以分发消息,在实际应用中可能会有一些模糊匹配的情况,这时候我们可以用主题交换机来实现。
主题交换机(Topic)
在路由模式上增加了通配符,可以进行路由键的模糊匹配,更加灵活的进行消息分发
通配符:*和#,*代表单个关键字,#代表多个关键字
在实际使用场景中,路由模式的效率高于主题模式,所以可以使用路由模式的时候优先使用路由模式。
关于延时队列
在Rabbit MQ中实现延时队列有两种方式:
使用官方提供的延时插件
具体操作可以看我的这篇文章:docker-compose安装RabbitMQ及插件
注意:这个插件的使用还是有一定的限制性,官方说:
Current design of this plugin doesn't really fit scenarios with a high number of delayed messages (e.g. 100s of thousands or millions). See #72 for details.
这个插件目前的设计并不适合有大量延迟消息的场景(例如10万或数百万)。详见第72条。
所以在大消息场景下可以改用Kafka来实现。
通过死信队列来实现
如订单超时功能,创建两个交换机队列,一个订单超时消息,一个订单消息,订单超时消息不设置消费者,仅设置过期时间,这样在到期后会转发给一个交换机Exchange(我们设置为订单消息交换机),订单队列收到这个转发就会发送消息,由此曲线救国的来做到延时消息。
但是死信队列有个大问题:当往队列放入一条过期时间是10秒的A消息,再放入一条过期时间是5秒的B消息,等待5秒后B消息并不会优先进入死信队列被消费,而是遵循队列先进先出规则,在10秒后A消息过期,A和B一起进入死信队列被消费。
不过这个问题也好解决,就是固定这个死信队列的延时时间就好了,比如订单15分钟后超时,就全部订单都是15分钟后超时,不要有A订单10分钟超时,B订单5分钟超时的情况,
消息监听
通过监听消息,我们可以实现消息的确认,是一种实现消息可靠性的方案。
如何保证消息不重复消费
接口 做防重和幂等性保证
保存唯一索引到Redis中,设置一个短一点的过期时间,消费消息前判断缓存中是否有数据,有就说明刚刚已经处理过了,这是一条重复消费
消息可靠性如何保证
生产者提供消息给消费者时使用消息确认机制
消息服务器的队列、交换机都进行持久化,保证数据不丢失
在消息可靠性上,没有方法可以保证完全绝对的可靠,所以必要的日志收集一定要做好,实时监控,在运维上也要下一些功夫。
参考资料
RabbitMQ六种工作模式与应用场景
来源:https://juejin.cn/post/7178693976713609253


猜你喜欢
- 要让项目实现 ssl 免密登录,首先需要开启 https 。所以先从 Spring Boot 如何开启 https 说起。创建服务端证书为了
- 添加jar包这里的Scala不是maven工程所以要找到项目结构(快捷键:同时按住Ctrl+shift+Alt+s)在模块里面添加添加MyS
- 介绍意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更灵活。主要解决:我们扩展一个类常使用继承方式实现,由于继
- 1. 下载Tomcat首先,下载Apache Tomcat并解压到本地计算机,可存放于任何位置。另外,需要在系统中环境JRE_H
- 在安卓操作系统下对于 TextView 字体的支持非常有限,默认情况下 TextView 的 typeface 属性支持 "San
- 简单的页面分析在上一个文章简单的数据库连接测试,已经测试和数据库做简单的交互,也就是dao层的实现,接下来要说的却是action的简单实现,
- 提供表示 Windows 注册表中的根项的 RegistryKey 对象,并提供访问项/值对的 static&
- 一,Maven 依赖 pom.xml配置1, 去掉默认日志,以便切换到log4j2的日志依赖2, 然后添加如下两个日志依赖二,在工程根目录下
- 面试题1:你了解线程池么?简单介绍一下。java提供的一个java.util.concurrent.Executor接口的实现用于创建线程池
- 占位符Placeholder的使用xml中的配置:<?xml version="1.0" encoding=&qu
- 一、前言在项目中,我们有一些公共的字段需要做修改如:gmt_create:创建时间creator_id:创建人gmt_modified:修改
- 本文实例讲述了c#实现随鼠标移动窗体的方法,分享给大家供大家参考。具体实现方法如下:private void MainForm_Load(o
- 介绍众所周知,AOP(面向切面编程)是Spring框架的特色功能之一。通过设置横切关注点(cross cutting concerns),A
- ReentrantLock内部由Sync类实例实现。Sync类定义于ReentrantLock内部。Sync继承于AbstractQueue
- 本文给大家介绍Activity的生命周期,如果大家学习过iOS的小伙伴的话,Activity的生命周期和iOS中ViewController
- 前言我们程序员在开发的时候经常会遇到各种各样的 BUG 问题,其中大部分是业务逻辑异常,还有一些是代码书写不规范造成的异常例如:NullPo
- 一、项目概述本系统采用MVC架构设计,SQLite数据表有用户表、成员表和活动表,有十多个Activity页面。打开应用,进入欢迎界面,3s
- 效果图:A.绘制圆环,圆弧,文本//1.画圆环//原点坐标float circleX = width / 2;float circleY =
- 楼主大菜鸟一只,第一次写技术博客,如果有概念错误或代码不规范的地方,还请各位多多批评指正。话不多说,来看题:前一阵子开发了一个用户控件,里面
- 前言: 有时候我们需要实现长按选择文字功能,比如阅读器一般都有这个功能,有时候某个自定义控件上可能就有这种需求,如何实现呢?正好最近还算闲,