1. rabbitMQ的组成
- 生产者:生产消息,消息由消息头、消息体和标签组成
- 消费者:消费消息,连接broker服务器,订阅队列获取消息
- broker:消息队列服务器,一般而言,一个broker可以认为是一个消息队列服务器
- queue:存放消息的队列,一个消息可以存放到多个队列,多个消费者可以订阅一个队列
- exchange:交换机,生产者生产的消息,通过交换机分发到队列中
- routing key:路由键,exchange通过消息的路由键匹配队列的路由键决定将消息路由到哪些队列
- binding key:绑定键,exchange通过binding key绑定队列
2. vhost
虚拟服务器,每个broker服务器都可以创建自己的虚拟服务器,虚拟服务器相当于一个小的broker,一个消息队列服务器可以通过创建多个vhost来对不同用户进行权限分离
3. amqp
高级消息队列协议,遵循此协议的客户端可以与消息中间件进行全功能的互操作
4. rabbitMQ如何进行消息路由
- 生产者发送消息:生产者发送消息到交换机,同时指定消息的路由键
- 交换机路由消息:交换机通过路由键匹配符合条件的绑定到自己身上的队列,决定将消息路由到哪些队列
- 消费者消费消息:订阅了相关队列的消费者获取消息进行消费
5. 路由模式
- direct(默认):直接交换机,exchange通过消息的routing key匹配队列的binding key,将消息路由到binding key与消息的routing key完全匹配的队列中
- topic:主题交换机,匹配逻辑与direct模式相同,但是消息的routing key是由多个由点号分隔的单词组成,并且可能带有*号与#号(如:*a. b. c#),exchange会进行模糊匹配,将消息发送到任意绑定建binding key包含在这routing key中的队列
- fanout:广播交换机,exchange通过广播的方式将消息路由到所有绑定了自己的队列中
- header:头部交换机,通过消息头的值与binding key进行匹配
- deal letter:死信交换机,专门用于处理死了的消息(已被拒绝但仍能重新投递的信息不算)
- 消息变成死信的情况:
①:消息被拒绝,且requeue属性设置为FALSE
②:消息过期,默认情况下rabbitMQ中的消息不会过期,但是消息可以设置过期时间
③:队列达到最大长度- 死信交换机的工作原理:
①:消息会先通过正常交换机进入正常队列,待正常队列中的消息变成死信后
②:消息从正常队列通过死信交换机,进入死信队列
③:对死亡消息进行后续处理
6. 交换机属性
- 交换机名字
- 交换机类型
- 是否持久化:持久化则rabbitMQ重启后,交换机仍存在
- 是否自动删除:当最后一个绑定到该交换机上的队列删除时,交换机是否自动删除
- 是否内置:设置了内置交换机则服务器不能直接发送消息到队列,必须经过交换机
- 扩展
7. 消息传输模式有哪些
- 简单模式(队列模式):生产者 - 队列 - 消费者;只能存在一个消费者
- 工作模式:生产者 - 队列 - 多个消费者;消息会平均分配到多个消费者上,当一个消费者从队列中获取消息并进行处理时,另一个消费者开始从队列中获取消息
- 发布订阅模式(广播模式):生产者 - 交换机 - 队列 - 多个消费者;增加交换机,消息会被交换机全部发送到绑定了自己的所有队列中
- 路由模式:生产者 - 交换机 - 队列 - 多个消费者;交换机决定往哪个队列中发送消息由路由键决定
- 主题模式:与上面路由模式的架构相同,只是routing key不同,可以模糊匹配
8. 消息分发策略
- 轮询分发策略:消息会平均得发送到每一个队列中
- 不公平分发策略:将prefetchCount设置为1,在消息处理完后,队列就会给消费者发送新的消息,处理快的消费者就会接收到更多消息,能者多劳
- 预值分发策略:通过设置prefetchCount的值来设置一个缓冲区,在消费者接收到消息时就会给服务器发送消息确认,让服务器继续发送消息以填充缓冲区,提高消息的传输效率和消费者的处理能力
9. 生产者消息投递的过程
- 生产者连接broker,在连接上开启一个信道
- 生产者创建交换机、队列
- 队列绑定到交换机并指定绑定键
- 生产者往交换机发送消息和信息标签(包含路由键)
- 交换机根据路由键和绑定键的匹配规则,将消息发送到对应队列,有匹配则发送 ,没有则将消息丢弃或返回
- 关闭信道
- 关闭连接
10. 消费者消费消息过程
- 消费者连接broker并请求消息
- 等待broker回应
- 接收消息,确认后发送消息确认‘
- broker从队列中删除消息
- 关闭信道
- 关闭连接
11. 排他队列
基于连接的排他,连接结束后,即使该队列是持久化的,也会在连接关闭后删除;同一连接的不同信道可以访问其他信道创建的排他队列;不同连接的信道不能创建同名排他队列
12. 自动确认
消费者订阅队列时可以指定autoack参数,当这个参数值为FALSE时,服务器发送消息后会等待消费者返回消息确认信号后才会从内存中删除消息;当参数值为TRUE时,发送完消息后就会自动把消息删除
13. 消息的顺序消费
- 消息不能顺序消费的原因:
- 多个消费者消费速度不一,速度快的先操作数据库就可能造成消费顺序问题
- 单个消费者使用了多线程处理消息,速度快的线程先操作数据库,可能造成消费顺序问题
- 解决方案:
方案①:
- 消息传递的方式变为:生产者 - 队列 - 消费者 - 消费者的多个内存队列 - 每个队列后面的线程消费消息
- 消费者不再直接消费消息,而是创建多个内存队列
- 消息通过关键词(如订单ID)哈希的方式,将关键值相同, 需要保证执行顺序的消息放入一个内存队列中,再由队列后的线程依次从中取出执行,这样就保证了消息的顺序执行
方案②:
- 消息的传递方式变为:生产者 - 多个队列 - 每个队列后跟消费者 - 消费者消费消息
- 使用关键词哈希等方式,将需要确保执行顺序的消息放入同一个队列中
- 每个队列后面的消费者依次从队列中取出消息执行,这样就保证了消息的顺序执行
14. rabbitMQ的应用场景
- 异步
- 解耦
- 削峰
15. 如何保证消息不丢失
消息丢失主要有以下场景:
-
生产者在发送过程中丢失消息
解决方案:
①:使用事务,如果发送不成功就回滚,但是会降低性能
②:使用rabbitMQ的消息确认机制,如果没有收到确认消息就任务消息发送失败,则重新发送 -
MQ传递消息过程中丢失消息
解决方案:将消息或队列持久化,在rabbitMQ重启后也不会丢失消息 -
消费者在消费过程中丢失消息
解决方案:
①:采用消息确认机制,消费者消费消息后向服务器发送确认消息,如未收到消息,则会重新向消费者发送消息
②:限制重试:设置重试次数,在消息处理失败时,将消息返回队列重新消费
③:死信队列:不能被处理的消息通过死信队列进行处理
16. 如何保证消息不重复消费
在保证了消息不丢失的时候,就会产生消息重复的问题,要保证消息不重复消费就是要保证消息的幂等性,所谓消息的幂等性就是指,一个消息多次执行与一次执行的结果一致
解决方案:
①:数据库写入的时候验证唯一值:如处理订单时,已存在某个订单ID就不再写入数据库
②:设置全局唯一ID,通过Redis的set来保证,在消费消息后,将消息ID存入Redis中,在消费前将通过ID查询是否存在Redis中,如果存在说明消息已被消费过
17. 如何处理消息堆积
-
消息堆积的原因:
①:总体来说是消费者消费消息的速度与生产者生产消息的速度不匹配,如消费者消息能力太弱
②:消费者在重试失败消息
③:消费者发生故障 -
解决方案:
①:先处理可能的消费者故障,停掉现有消费者,防止继续产生堆积问题
②:临时创建几倍数量的队列,并写一个临时分发数据的消费者程序将积压的消息分发到这些临时队列中,这样做可以快速将积压的消息取出,为后续的并行处理做好准备
③:临时使用几倍数量的机器来部署消费者,去消费临时队列中的消息
④:消费完成后恢复原先的部署
如果是消费者故障,那么处理故障,如果是消费者消费能力弱,可以尝试增加机器,或者降低其他非核心业务的处理
18. 如何实现消息队列的高可用
- 普通集群(不能实现高可用)
①概念:部署多个节点,每个节点有其他节点的元数据拷贝(包括:exchange、queue、bind、vhost元数据),但是一个节点只保存自己节点的消息,各个节点上的消息相互独立,在消费时,如果连接的是保存有要消费消息的节点,则直接获取 / 发送消息,如果不是,则可以通过当前节点上保存的其他节点的元数据信息,找到并发送到 / 获取那个节点的信息,相当于多个节点服务与一个queue的读写
②优点:可以提高系统的吞吐量,节省存储空间(消息不存在于全部节点)
③缺点:不能实现高可用,如果存在消息的节点宕机,那么服务失败
④其他:节点又分为磁盘节点与内存节点,内存节点的性能更强,但是持久化要依赖于磁盘节点(存储有一个磁盘节点的信息),因此集群中至少要添加一个磁盘节点,如果该磁盘节点宕机,那么创建交换机,队列,绑定信息等操作不可进行,但仍能生产发送消息
- 镜像集群
①概念:与普通集群的区别在于每个节点上都存在这个队列的完整数据(包括元数据与消息),有主从节点之分,消息只发送给主节点,由主节点提供服务,主节点执行命令后会将执行结果广播给从节点,从而保证主从节点之间的数据同步,从节点通常不提供服务,仅仅作为备用节点存在,当主节点发生故障时,剩余从节点中创建时间最早的一个升级为主节点继续提供服务
②优点:高可用
③缺点:每个节点存储全量数据,并且需要进行同步操作,性能开销更大
④其他:关于镜像集群是否属于分布式,查询到的信息表示,主从节点可以部署到不同机器上,从节点虽然通常不提供服务,但是它在故障转移和容错恢复方面起着重要作用,因此从节点可以认为共同参与了实现系统的高可用和容错性,满足分布式的定义
分布式定义:多台机器通过网络连接,彼此共享资源和信息,协调合作,实现系统的高可用和容错性
19. 持久化
队列、消息、交换机持久化
20. rabbitMQ的事务机制
txselect:开启事务,将当前信道设置为transaction
txCommit:提交事务
txRollback:回滚事务
21. 消息确认与消息返回
- 消息确认:用于确认消息是否正确被处理
- 消息返回:用于监听不可达消息,不可达消息:不能成功匹配routing key的消息,不能匹配到队列中