- RabbitMq
- MQ相关概念
- 是什么
- 为什么用MQ
- 知道那些MQ各有什么优缺点
- RabbitMq
- 四大核心概念
- 简述RabbitMq的架构设计
- RabbitMQ如何确保消息可靠性
- RabbitMQ事物消息
- 交换机有几种类型及特点
- 你项目中的RabbitMQ是如何使用的
本质是一个先入先出的队列,用于服务间的解耦
为什么用MQ1、流程削峰:例如处理订单的时候把一秒内的订单放到MQ分散成一段时间来出来。
2、应用解耦:例如物流系挂掉需要一段时间恢复,依赖MQ不影响继续下单。
3、异步处理:A调用B,A只需要监听不处理完的消息。不像以前,要么同步,要么提供回调API,要么A去查B。
1、ActiveMQ:单机吞吐量高,社区不够活跃
2、Kafka:吞吐高,适合大数据处理。
3、RocketMQ:能做到消息0丢失,支持的语言少java,c++
4、Rabbit:高并发,高吞吐,支持语言多,社区活跃度高,商业版要收费。
1、生产者
2、交换机:一方面接收来自生产者的消息,另一方面将来消息推送到队列。交换机需要确切知道他接收的消息如何处理,将消息推入队列或者把消息丢弃由交换机的类型决定。 交换机会找查询表中bunding里的routing key,分发消息到queue中。常用的类型有:direct,topic,fanout
3、队列:消息存储的地方
4、消费者
HelloWord代码
生产者
消费者
Broker:rabbitMq的服务节点
Exchange:生产者将消息发给交换机,交换机负责将消息路由到一个或多个队列。如果路由不到则返回给生产者,或者直接丢弃或做其他处理。
Queue:顾名思义就是一个队列,是rabbitMQ的内部对象,用于存储消息。生产者把消息投递到队列,消费者从队列中获取消息并消费。多个消费者可以订阅同一个队列,这时队列中的消息会被平均分配给多个消费者进行消费,而不是每个消费者都收到所有的消息进行消费(注意:RabbitMq不支持队列层面的广播消费,如果需要广播消费,可以采用一个交换器通过路由key绑定多个队列,由多个消费者来订阅这些队列的方式)。
RoutingKey:路由key。生产者将消息发给交换机的时候,一般会指定一个routinigKey,用来指定这个消息路由规则。这个路由key需要与交换器类型和绑定建(BindingKey)联合使用才能生效。在交换器类型和绑定键固定的情况下,生产者可以在发消息给交换机时通过RoutingKey来决定消息流向哪里。
Binding:通过绑定交换器和队列关联起来,在绑定的时候一般会指定一个绑定键,这样RabbitMQ就可以指定如何正确的路由到队列。
交换器和队列实际上是多对多关系。他们通过BingKey关联,在投递消息时候,可以通过Exchange和RoutingKey就可以找到相应的队列。
信道:建立在Connection之上的虚拟连接。当应用程序与Rabbit Broker建立TCP连接的时候,客户端紧接着可以创建一个AMQP信道,每个信道都会被指派一个唯一的ID。
面试回答技巧:通过讲述数据的流转过程,来把个组件都串联起来
发送方确认机制:
信道设置为/confirm/i模式,则所有信道上发布的消息都会分配一个唯一的ID。一旦消息投递到queue(可持久化的消息需要写入磁盘),信道会发送一个确认给生产者(包括消息唯一ID)。如果RabbitMQ发生内部错误从而导致消息丢失,会发送一条nack(未确认)消息给生产者。所有被发送的消息都会被/confirm/i(即ACK)或者NACK一次。但是没有对消息被/confirm/i的快慢做任何保证,并且同一条消息不会既被/confirm/i有被nack。发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发消息。当确认消息到达生产者,生产者的的回调方法会被触发。/confirm/iCallBack接口:消息是否正确到达Exchange中,成功则回调。RetrunCallback接口:消息失败返回时回调。
接收方确认机制
RabbitMQ事物消息消费者在声明队列时,可以指定noAck参数,当noAck=fase时(实际上就是设为手动提交),RabbitMQ会等待消费者显式发回ack信号后才从内存(或者磁盘,持久化消息)中移去消息。否则,消息被消费后会立即删除。
消费者接收每一条消息都必须进行确认只有确认了,RabbitMQ才会把它从队列中删除。
RabbitMQ不会为未ack的消息设置超时时间,它判断次消息是否需要重新投递给消费者的唯一依据就是该消息的消费者连接是否已经断开。这么设计的原因是RabbitMQ允许消费者消费一条消息的时间可以很长,保证数据最终一致性。
如果消费者返回ack之前断开了链接,RabbitMQ会重新分发给下一个订阅者。(可能存在消息重复消费的隐患)这个时候需要对消息去重。
通过对信道的设置实现
- channel.txSelect():通知服务器开启事物模式;服务端会返回Tx.Select-Ok
- channel.basicPublish:发送消息,可以是多条
- channel.txCommit()提交事物
- channel.txRollback()回滚事物
消费者使用事物:
1、autoAck=false,手动提交ack,以事物提交或者回滚为准;
2、autoAck=true,不支持事物,收到消息队列就会删掉
如果任意一个环节出了问题,会抛出IoException,用户可以拦截异常进行事物回滚,混着要不要重复消息。事物会降低rabbitmq的性能
- 直接(direct):广播给特定对垒,例如日志信息,info,warning,error我只希望把error写入磁盘其他只打印日志。那就把bundingKey设置为error发给特定的对列
- 主题(topic):单词.号隔开可以用*和#来指定匹配规则,有限想我们配置的spring切面表达式
- 标题(headers):不太了解
- 扇出(fanout):广播给所有队列
异步的写入日志



