RabbitMQ是一个开源的消息中间件,用于应用之间进行消息传递。实现了AMQP(高级消息队列协议)。
1.整体组成:
producer(生产者):负责发送消息,将消息发送到交换器(Exchange);
Consumer(消费者):消息接收方,负责进行消息的消费、处理。
Exchange(交换器):消息接收和路由中心,接收生产者发送的消息,然后将消息路由到一个或多个绑定的队列(Queue)中。
Queue(消息队列):消息的存储和消费地,保存未被消费的消息。
Binding(绑定):一种绑定关连关系,Exchange和Queue之间的关系,决定了消息的路由方向。
Broker:RabbitMQ Server 服务器实体
Channel(信道):多路服用连接中的一条独立的双向数据通道。每个信道代表一个会话
Message(消息):生产者发送的内容,由消息头和消息体组成,消息体就是需要传递的内容,消息头是由一系列可选属性组成,包括:Routing-key(路由键)、priority(优先级)、delivery-mode(是否持久化)等信息
Routing Key(路由键):消息头的一个属性,标记路由规则,决定交换机的转发路径。
2.消息分发模式
2.1 简单模式
就是最简单的消息传递模式,就是一个生产者将消息发到消息队列,一个消费者进行消费处理。适用于单个生产者单个消费者模式,
2.2 工作队列模式
一个生产者,消息发到消息队列中,多个消费者进行处理,多个消费者并发处理,每个消息只能被一个消费者处理,适用于多个消费者的情况,但是需要做好消息的幂等处理,防止重复消费。
2.3 发布/订阅模式
一个消费者将消息发送到交换器(Exchange)中,交换器将消息广播到所有绑定的队列中,每个队列有自己的消费者进行消费,这种模式适用于消息需要被多个消费者同时接受和处理的广播场景,如日志订阅和时间通知。
2.4 路由模式
生产者将消息发送到Exchange之后,由交换器根据路由键(Routing key)将消息路由到不同的队列中。这种模式需要生产者发送消息到交换器的时候要设置消息的路由键,由交换器根据路由键将消息路由到与之匹配的队列中。适合根据不同条件将消息发送到不同队列中以实现消息筛选和分发。
2.5 主题模式
这种模式使用通配符匹配路由键,将消息路由到多个队列中。在这种模式下,生产者将消息发送到交换器,并制定Topic(主题),交换器会根据通配符匹配将消息路由到匹配的队列中。适合消息的复杂路由需求,实现高度灵活的消息筛选和分发。
3 Exchange 类型
3.1 fanout
不处理路由键,直接将消息分发到所有绑定的队列中。因为不处理路由键,所以速度快。
发布订阅模式就是Fanout。
3.2 Direct
将消息根据Routing-key匹配到一个对应的队列上,要求消息与路由键完全匹配
路由模式用的就是Direct
3.3 Topic
多对多正则表达式匹配,所有发送过来的消息都会被交换器转发到匹配的RouteKey中指定Topic的Queue中,其中#匹配任意个词,*匹配一个词。
4 关注点
4.1 在mq使用的过程中需要关注的内容
①队列深度(消息堆积),防止堆积过多造成延迟或者性能瓶颈。 解决方案:增加消费者并发数,提升消息处理的速度。
②消息吞吐量,生产消费的速率,确保平衡
③消息确认机制,
④连接数与信道数,防止连接数和信道数过多导致压力过大。根据情况合理配置连接池大小,关闭不必要的连接和信道
⑤服务器内存和磁盘的使用情况
4.2 消息丢失的原因
①消息发送方消息发送失败
②Exchange路由消息失败
③未进行持久化,服务挂掉
④消费者确认机制为自动,拉取消息后就确认,确认后消费者未实际处理消息就挂掉,
针对以上原因的解决方案:
①消息重试或者消息发送时利用confirm机制,注册回调监听是否成功,失败之后可以根据情况重发或者补偿机制(重试这种可能还是会有问题,只能解决网络抖动,一旦是其他原因短时间内重试可能于事无补,建议注册监听进行记录内容然后进行补偿操作)
②创建持久化消息,创建持久化队列,消息会在重启后保留,确保不会丢失
③消息自动确认改为手动确认,只有消费之后才手动确认ACK;
4.3 如何防止消息重复消费
使用消息确认机制,消息消费后就删除,另外可以通过消息唯一标识messageid进行幂等校验(但是这只能做消费端的幂等校验),通过业务相关的id进行幂等校验(生产者发送的时候就进行幂等校验,并将该对应业务id一并塞进消息体,在消费者方再做一次幂等,这样可以确保发送和消费方都可以避免重复消费)
4.4 事务消息
事务消息,允许生产者将一组操作打包成一个原子事务单元,要么全部成功要么全部失败,它提供了一种确保消息完整性的方式,但是谨慎使用,因为这会影响性能。
事务基于AMQP协议实现,通过channel上启用,与之相关的方法有三个:
txSelect() :将当前Channel设置为transaction模式。
txCommit() :提交
txRollback() :回滚
这个操作可以确保一批消息的原子性操作,有人说可以确保消息一定发送成功,不出异常一定是可以确保发送成功,但是出现异常就回滚了啊,事务消息只是开启了一个原子性操作,不确保成,只确保原子性,支持提交与回滚,作用不是为了确保消息成功的,就像mysql的事务一样的道理,是为了确保原子性操作用的。