RabbitMQ
基础
整体结构

理解:
1.消息先发送到交换机,由交换机将消息发送给与他绑定的队列(所以必须先绑定)
2.每个虚拟主机有自己的交换机和队列,实现数据隔离
work queue
个人理解:
1.一个队列的消息属于同一个业务,同一个队列的不同消费者实现的同样的业务
2.增加订阅同一个队列的消费者,可以提高这个队列的消息处理速度,prefetch保证了消费者只有处理完当前消息,再接受下一个消息
- 为什么要有交换机?
因为同一个队列对应了一个微服务(业务),而一条消息往往需要设计多个业务,比如一个订单信息,需要创建订单、删除库存等业务,此时就需要发送到不同的队列(不同业务),所以直接发给交换机,交换机可以将其路由到队列
Fanout(广播)
概念:和交换机绑定的所有队列都能收到
Direct交换机
和这个交换机绑定的queue,不一定全都能收到,因为queue绑定交换机的时候,要指定routingkey,相当于一个暗号(一个单词),只有暗号和routingkey相同的queue可以收到,不同的queue也可以有相同的routingkey
Topic交换机
与Direct不同的是,再queue绑定交换机的时候指定的routingkey之一使用通配符,并且可以使用多个单词,发送消息的时候,满足条件的routingkey的队列就可以收到
注:通配符是用于绑定的时候,不是发送消息的时候

消息转换器


上述能实现的原因是:我自己配置的Bean会优先注册到容器里面,而当spring再注册他自己的Bean的时候,会先判断容器里面是否,已经存在这个Bean,然后再来判断是否注册到容器
高级
生产者可靠性问题

生产者确认

持久化
数据持久化
-
非持久化消息
只存在内存中,重启后会丢失,当内存存满以后,出现pageout(将现在内存里面没有处理的消息,写入磁盘,阻塞),然后再清空内存 -
持久化消息
开始先存入内存,后面异步写入磁盘(内存中的消息仍然不变),当内存满了之后,直接清空内存, 不用再pageout了
LazyQueue

消费者确认模式

幂等性
概念:执行一次操作和执行多次操作的结果是一样的
MQ中同一个消息会被多次消费,导致性能损耗
解决方法:
给每一条消息设置一个id,当消息到达消费者的时候,消费者,先去数据库判断,是否存在这个id(之前是否已经处理过),如果存在,则直接return,反之就处理,并将其存入数据库
再处理消息的时候,先判断处理的业务是否,已经被处理成了我向处理的样子(乐观锁),如果是直接return,反之就处理
RabbitMQ的死信交换机(延迟队列)

延迟队列=死信交换机+TTL
成为死信的条件:

成为死信后,然后进入死信交换机,然后再发送到队列,交给其他消费者处理
Rabbit的高可用机制
- 普通集群

如果节点一创建了一个队列,其他节点会由节点一的队列的引用,当访问其他节点的时候,实际会通过这个引用访问到储存消息的节点,但是,如果这个节点宕机了,其他节点不知道,就会造成数据丢失
- 镜像集群

每一个节点的每一个队列可能是父队列,也有可能是子队列,通过同步父队列消息到子队列,来 保证一致性吗,但是如果同步过程中,发生宕机导致数据不一致
- 仲裁队列




