什么是rabbitMQ
一种由Erlang语言开发,实现了高级消息队列(AMQP)的开源消息中间件。
- 实现消息队列
- 实现发布/订阅
- 兼具Push和Pull模式
- 支持消息持久化
- 支持高可用
- 可视化的管理界面
- 不保存历史数据(对比kafka)
- ......
重要概念
-
连接Connection
Connection是RabbitMQ的TCP连接 -
通道Channel
应用与AMQP可能有时候想创造多个连接,但是过多的TCP连接会消耗系统资源,所以通道是在Connection上为线程开启的单独的虚拟连接 -
虚拟主机VHost
为了在同一个MQ服务上实现多个隔离环境,可以设置不同的VHost -
交换机Exchange
消息发送者在建立连接后,首先将消息发送到交换机上,交换机负责根据规则将消息路由给不同的队列 -
路由Route
交换机将消息匹配到队列的过程 -
队列Queue
队列是接收消息的实体,消息存放在队列中 -
路由键RoutingKey
路由键是关联交换机和队列的唯一标识,发送消息到交换机上并且指定路由键,就能将消息路由到队列
不同的交换机区别
- Direct
直连交换机,需要routingKey,通过routingKey精确匹配交换机和队列 - Topic
主题交换机,需要routingKey,通过routingKey模糊匹配交换机和队列 - Fanout
扇形交换机,不需routingKey,发送消息到交换机上,会拷贝给每一个绑定的队列 - Headers
头交换机,不需routingKey,绑定时需要声明匹配规则,发送消息时根据消息头中设定内容,自动匹配到队列
发送消息
默认情况下,rabbit是异步发送消息到exchange,且不会有任何通知;如果需要保证数据发送成功可以通过以下两种方式实现:
- producer设置事务机制(AMQP的实现)
- channel设置confirm模式实现
保存消息
在client声明交换机、队列和消息时,可以选择是否持久化,非持久化消息会在rabbitmq服务器重启后丢失。
- 持久化需要对exchange、queue、message都进行持久化
- 持久化并非一条条持久化,而是缓存在内存中批量持久化,所以此处存在风险;但是可通过镜像高可用解决
消费消息
- ACK实现消费确认
- 可以对消息进行拒绝,并指定是否重新加入队列或者是丢弃
- 预取消息:在consumer发送上一条消息的ACK之前,最多向其投送的数据量。 默认情况下,rabbit接收到消息后就会向consumer投递,假设存在这样的一种情况,producer瞬时发送大量消息,而consumer处理消息能力并不能承受如此大批数据,此时我们可以设置预取消息量。
高可用方案
普通集群模式
普通集群模式是rabbit mq 默认的集群模式。
假设存在A/B两个节点,queue存在于A节点上;则B节点只拷贝A节点上queue的元数据,并不会对消息进行拷贝。当consumer从B节点拉取数据时,B节点会从A节点同步消息,发送给consumer。
此模式存在缺点:
- A节点会形成性能瓶颈
- A节点失效后,B节点也会拉取不到A的数据。
镜像模式
该模式和集群模式的区别在于,message data 会在镜像节点间主动同步,而不是在consumer 取数据时临时拉取。
此模式的缺点是:
- 节点间主动同步数据,降低系统性能。
- 数据冗余。
两种集群模式对比
普通模式符合rabbitMq设计初衷,希望在增加机器的同时,能够线性提升其集群性能。
镜像模式对消息的健壮性更加有保证,但是会降低性能。
消息过期TTL
TTL:Time-To-Live Extensions
在发送消息时,我们可以设置消息的过期时间,消息过期后MQ会丢弃消息 。
消息过期可以从三个方面设置:
-
对队列中消息统一设置
在队列属性上面统一设置消息的过期时间,时间过后队列会丢弃消息,并且队列相应的大小会进行变化。 -
单个消息设置
在消息头属性上面设置过期时间,即使消息过期,也不会马上从队列中抹去,所以此时统计队列大小信息不会发生变化;而这种设置主要是让消费端去判断。 -
设置队列过期时间
设置队列过期时间,而不是队列中的消息,队列过期后会自动被删除。
消息过期转发DLX
DLX,Dead-Letter-Exchange
当消息过期后,可以设置消息转发到其他队列。