MQ是什么
MQ (message queue)消息队列
用列队机制来实现软件之间的通信,消费者可以到指定列队拉取消息,或者订阅相应的队列,由MQ服务端给其推送消息
什么是队列
是一种数据结构,遵守先进先出原则
MQ的优势
-
异步通信
将以前的业务中不必要的同步操作,优化成异步操作,提高性能
-
业务解耦
将原有一个模块直接调用另外一个模块,优化成,把请求给到MQ,MQ会主动推送给其他模块,
-
流量削峰
当某一时间大量的流量打到服务器上,服务器一时间无法承受,会宕机,这个时候可以用MQ进行削峰处理,请求都是消息队列里面出来,泽能够包装这种大流量的情况下,服务器仍然能够有序的稳定的处理请求。
MQ有什么劣势
- 系统可用性降低,对外部有依赖了
- 需要考虑效率丢失,重复消费的情况
- 需要保证消息的顺序性,一致性
常用的MQ性能对比
| ActiveMQ | RabbitMQ | RocketMQ | Kafka | |
|---|---|---|---|---|
| 开发语言 | java | erlang | java | scala |
| 单机吞吐量 | 万级 | 万级 | 十万级 | 十万级 |
| 时效性 | ms | us | ms | ms以内 |
| 可用性 | 高 主从架构 | 高主从架构 | 非常高 分布式架构 | 非常高 分布式架构 |
| 消息可靠性 | 较低概率丢失 | 基本不丢 | 可以做到基本不丢 | 可以做到基本不丢 |
| 功能支持 | 支持功能全 | 性能好 延迟低 并发能力强 | MQ功能完善 支持分布式,扩展性好 | 主要用于大数据的日志采集 |
MQ如何避免消息堆积
- 提高消费者的速率
- 消费者批量获取消息进行消费
MQ如何避免重复消费
- 全局ID(增加标志位)+保证业务的一致性
MQ如何保证消息不丢失
- 消息确认机制
- 消息的持久化
- 消息ACK
MQ如何保证消息顺序一致性
- 绑定同一个消费者和队列
MQ推与拉取的架构模型是怎么样的
- MQ服务器与消费者建立长连接,MQ服务器会主动推数据给到消费者
- 当消费者第一次启动的时候,会去找MQ服务器拉数据
MQ有哪些消费模式
- 推模式注册一个消费者后,RabbitMQ会在消息可用时,自动将消息镜像推送给消费者,这种方式效率最高最及时
- 拉模式属于一种轮询模型,发送一次get请求,获得一个消息,如果此时RabbitMQ中没有消息,会获得一个表示空的回复。
- 自动确认 消费者消费消息的时候,将自动向RabbitMQ确认
- 手动确认 消费者消费消息的时候手动调用相应函数进行确认
- pos预取模式 在确认纤细被接受之前,消费者可以预先接受一定数量的消息。在处理完一定数量的消息后,批量进行确认,当然,如果消费者应用程序在确认消息之前崩溃,则所有为确认的消息将被重新发送给其他消费者
RabbitMQ中既然有了 connections 为什么还需要channel
connection 是生产者或消费者与RabbitMQ broker 建立的连接。是一个TCP连接
一旦TCP 连接建立起来,客户端紧接着可以创建一个AMQP通道(channel),每个通道会被指派一个唯一的id,通道的建立是在connection 之上的虚拟连接,多个信道服用一个TCP 连接,可以减少性能开销,同时也便于管理,因为一个应用需要向RabbitMQ 中生成消费消息的话,都要建一个TCP连接,TCP连接开销非常大,如果遇到使用高峰,性能也会下降。
- 通道复用连接优势:复用TCP连接,减少性能开销,便于管理
- RabbitMQ保障每一个通道的私密性
当每个通道流量不是很大是,复用单一的connection 可以产生性能瓶颈的情况下有效的节省TCP连接资源,信道本身流量很大时,这个时候多个信道复用一个connection 就会产生瓶颈,是整体的流量被限制,此时会开辟多个connection 将这些信道均摊到这些connection中
RabbitMQ的作用
- 削峰填谷
- 生产者和消费者业务解耦
- 服务间异步通信
- 定时任务
- 顺序消费
为什么选择RabbitMQ
市面上有什么消息队列为什么选择
- rabbitmq是唯一实现了AMQP标准的消息服务器
- 可靠性,支持持久化,保证了消息的稳定性
- 高并发,rabbitmq是用的erlang语言开发的,erlang 是为电话交换机开发的语言,天生自带高并发光环和高可用特性
- 集群是简单
- 社区活跃度高
RabbitMQ的特点是什么
- 可靠 rabbitmq使用如持久化,传输确认及发布确认等机制来保证可靠性
- 灵活的路由 通过交换机来路由消息 对于典型的路由功能,rabbitmq已经提供了一些内置的交换机来实现。针对复杂的路由功能,可以将多个交换器绑定在一起。可以通过插件来实现
- 扩展性 多rabbitmq节点可以组成一个集群,也可以根据实际业务情况动态的扩展集群中的节点
- 高可用性 队列可以在集群中的机器上设置镜像,使得在部分节点出现问题的情况下附列仍然可用
- 支持的协议多 rabbitmq除了支持AMQP协议,还支持STOMP,MQTT等多种消息中间件协议
- 多语言客户端 几乎支持所有常用的语言 go、java、Python、PHP、.net等
- web管理界面 提供了一个易用的用户界面,是的用户可以监控和管理消息,集群中的节点等
- 命令插件机制 rabbitmq提供了很多插件,以实现从多方面进行扩展,当然也可以自己编写自己的插件
生产者producer和消费者consumer有哪些知识点?
生产者
- 消息生产者,投递消息
- 消息一般包含两个部分:消息体和标签
消费者
- 消费消息,接受消息
- 消费者连接到rabbitmq服务器,并订阅到队列 消费消息时只消费消息体,丢弃标签
RabbitMQ消息持久化中的坑
默认情况下重启服务器会导致消息丢失,我们如何保证重启RabbitMQ不丢失数据
那就是做持久化,持久化需要满足3个条件可以回复rabbitmq 的数据
- 投递消息的时候durable设置为true,消息持久化
- 消息已经到达持久化的交换机上
- 消息已经到达持久化的列队上
持久化的工作原理
rabbit会将持久化消息写入磁盘文件中,等消息被消费之后,rabbit会把这条消息标识为等待垃圾回收
持久化的优缺点
- 优点:数据持久化,数据不丢失
- 缺点:对性能有影响,写入硬盘比内存性能低,从而降低服务的吞吐量
rabbitmq的ack应答机制
ack应答分为手动和自动
- 如果消息不重要,丢失也没有关系,那么自动ack会比较方便
- 如果消息非常重要,不容丢失,那个最好在完成消费之后手动ack,否则如果业务处理失败消息也会丢失
ACK 机制的开发注意事项
如果忘记了 ACK,那么后果很严重
当 Consumer 退出时候,Message 会一直重新分发。然后 RabbitMQ 会占用越来越多的内容,由于 RabbitMQ 会长时间运行,这个” 内存泄漏” 是致命的
为什么需要限流,消费者流量控制
- 某一时刻,生产者在 RabbitMQ 队列中堆积了很多消息,此时有一个消费者启动,大量的消息会推送到消费者上面,这种瞬时大流量会把消费者打挂
- 生产者和消费者效率不平衡的情况,会导致消费者端性能下降,服务端卡顿或者崩溃
RabbitMQ 的组成
- 生产者 producer
- 消费者 consumer
- 交换机 exchange
用于接受、分配消息
- 消息 message
- 队列 queue
用于存储生产者的消息
- 信道 channel AMQP
消息推送使用的通道
- 连接 connections
生成者或者消费者与Rabbit 建立的TCP 连接
- 路由键 routingKey
用于把生成者的数据分配到交换器上
- 绑定键 BindingKey
用于把交换器的消息绑定到队列上
- 连接管理器 ConnectionFactory
应用程序与 Rabbit 之间建立连接的管理器,程序代码中使用
- VHost
vhost 可以理解为虚拟 broker,即虚拟机
其内部均含有独立的 queue、exchange 和 binding 等
拥有独立的权限系统,做到资源隔离,资源高效利用
RabbitMQ 的六种模式
- single
简单的生产者生产消息,放入队列,消费者消费消息
- work
当生产者生产消息的速度大于消费者消费的速度,就要考虑用 work 工作模式,这样能提高处理速度提高负载
work 模式与 single 模式类似, 只是work 模式比 single 模式多了一些消费者
- publish
应用场景:简单消息队列的使用,一个生产者一个消费者
- routing
消息生产者将消息发送给交换机按照路由判断,路由是字符串(info) 当前产生的消息携带路由字符(对象的方法),交换机根据路由的key
只能匹配上路由key对应的消息队列,对应的消费者才能消费消息
- topic
话题模式,一个消息被多个消费者获取,消息的目标 queue 可用 BindingKey 以通配符
- rpc
通过远程过程调用的方式实现
存储机制
- 持久化消息
持久化的消息在到达队列时就被写入磁盘,持久化的消息也会在内存中保存一份备份,这样可以提高一定的性能,当内存吃紧的时候会从内存中清除
- 非持久化消息
一般只保存在内存中,在内存吃紧的时候会被换入到磁盘中,以节省内存空间
RabbitMQ中消息可能有的几种状态
- alpha
消息内容(包括消息体、属性和 headers) 和消息索引都存储在内存中
- beta
消息内容保存在磁盘中,消息索引保存在内存中
- gamma
消息内容保存在磁盘中,消息索引在磁盘和内存中都有
- delta
消息内容和索引都在磁盘中
RabbitMQ 的队列结构?
- rabbit_amqqueue_process
负责协议相关的消息处理,即接收生产者发布的消息、向消费者交付消息、处理消息的确认等
- backing_queue
是消息存储的具体形式和引擎,并向 rabbit_amqqueue_process 提供相关的接口以供调用
交换器无法根据自身类型和路由键找到符合条件队列时,会如何处理?
我们对交换机设置参数的时候,有一个标志叫做 mandatory
- 当mandatory标志位设置为true时
如果exchange根据自身类型和消息routingKey无法找到一个合适的queue存储消息,那么broker就会调用basic.return方法将消息返还给生产者
- 当mandatory设置为false时
前置条件和上述保持一致,此时 broker会直接将消息丢弃
如何保证消息可靠性嘞?
- 消息从生产者到 MQ
由事务机制,确认机制 来保障
- MQ 自身可靠性
由持久化、集群、普通模式、镜像模式来保证
- MQ 消息到消费者
由basicAck机制、死信队列、消息补偿等机制来保证
集群中的节点类型有哪些?
- 内存节点
ram,将变更写入内存。
- 磁盘节点
disc,磁盘写入操作
RabbitMQ中 要求最少有一个磁盘节点
如何保证 RabbitMQ 消息队列的高可用?
RabbitMQ中有三种模式来保证:
- 单机模式
一般是本地启动,自己学习和测试使用,不会用在生产环境上
- 普通集群模式
在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个
- 镜像集群模式
RabbitMQ的高可用模式
跟普通集群模式不一样的是,创建的 queue,无论元数据(元数据指 RabbitMQ 的配置数据)还是 queue 里的消息都会存在于多个实例上,
然后每次写消息到 queue 的时候,都会自动把消息到多个实例的 queue 里进行消息同步