MQ简单介绍
MQ全称Message Queue(消息队列),顾名思义就是用来存储消息的容器,基础数据结构就是队列,MQ主要有以下几个功能:
- 应用解耦,解除多个应用之间相互调用的耦合关系
- 异步处理,应用异步处理消息,减少处理时间
- 削峰填谷,在高并发请求时限制并发的处理数量减轻系统压力
几种常用MQ比较
常用的MQ有kafka、rabbitmq、rocketmq、activemq,其中kafka主要用在大数据领域
RabbitMQ简单介绍
rabbitmq由rabbit公司使用Erlang语言开发,rabbitmq中的基本概念:
- Broker:接收和分发消息的应用,就是Rabbit Server
- VirtualHost:虚拟地址,类似数据库的db,每个vhost有自己单独的exchagnet/queue,同一个VirtualHost 里面不能有相同名称的Exchange或Queue
- Conncetion:publish/consumer和broker之间的TCP连接
- Channel:网络信道,进行消息读写的通道,channel是在connection内部建立的逻辑连接,客户端可以建立多个channel,从而节省大量建立connection的开销
- Exchange:消息交换器,生产者发送消息给exchange时一般会指定一个routing key,exchange根据分发规则,匹配查询表中的路由规则分发消息到queue中
- Queue:队列,用来存储消息
- Binding:exchange和queue之间的虚拟连接,binding中可以包含routing key,binding信息被保存到exchange中的查询表中,用于message的分发规则
RabbitMQ的工作模式
- 简单模式
- work queue
- Publish/Subscribe发布订阅模式
- Routing路由模式
- Topics主题模式
- RPC远程调用模式
官方介绍文档:https://www.rabbitmq.com/getstarted.html
1、简单模式
生产者发送消息给队列,消费者从队列取消息
2、work queue
生产者发送消息给队列,多个消费者从队列取消息
3、Publish/Subscribe发布订阅模式
多了一个exchange,生产者发送消息给交换机,交换机决定如何分发消息,exchange有以下三种类型:
- Fanout:广播分发,将消息分发给所有绑定在交换机上的队列
- Direct:定向分发,将消息分发给指定Routing Key的队列
- Topic:通配符分发,将消息分发给符合Routing Patter的队列
交换机只负责转发消息如果分发失败,消息会丢失
4、Routing路由模式
队列和交换机通过Routing Key绑定,生产者发送消息时必须指定Routing Key,exchange根据Routing Key分发给对应的队列
5、Topics主题模式
RabbitMQ的高级特性
1、生产者消息可靠性传递
- confirm确认消息
confirm是指producer投递消息给broker,如果broker将消息发送给exchange,会返回一个confirmCallback消息,producer通过判断confirmCallback消息中的字段来确认投递是否成功,通过配置文件和代码都可以开启confirm模式,具体就不细说了 - return退回消息
return模式代表exchange到queue的环境是否正常,当exchange路由到queue失败时,会发送return消息给producer,具体开启方法和接收回调的代码我也不细述了
2、消费者确认消息
- 自动确认,acknowledge=“none”
当customer接收消息,则queue自动确认customer收到了消息,并将message从rabbitmq的消息缓存中移除,实际中可能会丢消息,如果不配置的话默认是使用自动确认 - 手动确认,acknowledge=“manual”
customer处理完消息后,需要调用channel.basicAck()手动确认,如果出现异常,则调用basicNack或basicReject拒绝签收并让MQ重新发送消息 - acknowledge=“auto”
这种模式基本不用
3、消费端限流
如果某一时刻,生产者生产的消息激增,但是消费者的消费能力有限,那我们就需要对消费者限制消费个数以免消费者压力过大宕机,可以在配置文件或者代码中配置每次消费消息的个数,如果消息没有确认则阻塞消费,所以必须设置消费端手动签收否则限流配置无效
4、TTL
TTL全称Time To Live(存活时间/过期时间),rabbitmq支持配置消息的ttl(expiration),当超过ttl时间还未被消费则自动清除,也支持配置队列的tll(x-message-ttl),当队列中消息超过队列的ttl则自动清除
5、死信队列
成为死信的消息会被发送到死信交换机,死信交换机再投递到死信队列
成为死信的原因:
- 消息被消费者拒绝(basic.reject/ basic.nack)并且不再重新投递 requeue=false
- 达到TTL时间未被消费
- 队列长度达到限制
6、延迟队列
rabbitmq并未提供延迟队列的功能,但是我们可以用死信队列+TTL来实现延迟队列
7、消息幂等性
幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同,消息幂等性指的是消费多条消息应该产生与消费一条消息相同的结果,常见的幂等性方案有:
- 全局唯一id+数据库,利用数据库主键去重
- 全局唯一id+redis,利用redis的setnx