基于 tcp 协议,建立真实的 tcp 连接内的虚拟连接,每条 tcp 连接上的信道没有限制
mq缺点:
1、系统可用性降低了:本来A调用B好好的,突然加入个消息队列,mq挂了,系统不能运行了
2、系统复杂度提高:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等
3、一致性问题:异步处理,A、B都执行成功了,但是C失败了,导致数据不一致
优势:
1、erlang语言天生支持高并发
2、中小型公司,用这个正好
主要解决的问题:消峰,解耦,异步
高级特性:
1.可靠性投递:成功发出,mq节点成功接收,发送端收到mq节点(broker)确认应答,完善的消息进行补偿机制
2.幂等性:乐观锁,一个消息同一时间只能被一个消费者消费
3.confirm确认消息:broker发送一个消息给生产者,保证消息成功发送到broker
4.return消息机制:ReturnListener 处理一些不可路由的消息,就是消息找不到队列(queue),routing key有问题
5.消费端自定义监听:自定义消费者
6.消费端限流:qos功能,不能自动签收
7.消费端的ack与重回队列:一般不开启重回队列
8.TTL:Time To Live,生存时间的意思(过期时间,消息队列的消息过期之后就会自动清除)
9.死信队列:Deal-Letter-Exchange
影响性能的因素:
1、持久化IO 、磁盘IO操作
解决办法:批量处理 + 缓冲区
2、消费者消费能力太低,造成消息堆积
解决办法:消费者集群,批量拉取
各种mq的对比
| activeMq | rabbitMq | rocketMq | kafka | |
| 开发语言 | java | erlang | java | scala |
| 单机吞吐量 | 万级 | 万级 | 10万级 | 10万级 |
| 实效性 | ms | us | ms | ms |
| 可用性 | 高 | 高 | 非常高 | 非常高 |
| 功能特性 | 很成熟,各种协议支持的较好 | 并发能力很强,性能及其好,延时很低 | 功能比较完备,扩展性佳 | 为大数据准备的 |
a. kafka 编程语言:java/scala
b. RabbitMq 编程语言:erlang
c. RocketMq 编程语言:java (大一点的公司) 它的前身:Notify
d. ActiveMq 编程语言:java (小公司)
命令
// 启动:
1、rabbitmq-server start
2、rabbitmq-server start
3、/sbin/service rabbitmq-server start
// 停止:
rabbitmq-server stop
// 查看的状态:
1、rabbitmqctl status
2、rabbitmqctl status | grep rabbit
结构
解释:
1、borker:中介,相当于一个 mq 程序
2、exchange:交换机,绑定的列表,它和队列是多对多的关系
它的属性:
name:姓名
type:类型 --- > direct,topic,fanout
internal:当前exchange是否用户rabbitmq内部使用,一般都是false
arguments:扩展参数,用户amqp协议自制定化使用
auto delete:自动删除,交换机最后一个消息消费后,交换机自动删除
durability:是否需要持久化,true
3、channel:信道,虚拟链接
4、queue:独立的进程,存放消息(有数据库,erlang语言)
push:推送模式
pull:拉取模式
交换机
1、基本类型:一个提供者,一个队列,一个消费者
2、工作模型:一个提供者,一个队列,多个消费者
发布/订阅模式(多个队列):
3、fanout exchange:没有routingkey,队列和交换机直接绑定(消息转发速度最快)
4、direct exchange:队列和交换机的routingkey完全匹配,才能进行消息的转发
5、topic exchange:可以进行模糊匹配
#:可以匹配一个或多个单词
*:只可以匹配一个单词
6、headers exchange:用消息头进行路由,不怎么常用
AMQP
什么是 AMQP 协议?
Advaced Message Queue,高级消息队列协议(应用层协议),不受产品、开发语言等条件的限制
AMQP 和JMS 的区别?
1、jms 定义统一的接口,对消息操作进行统一;amqp规定了统一数据交互的格式
2、jms 是针对java语言;amqp是协议,任何语言都可以实现
3、jms 规定了两种消息模型;amqp的消息模式更加丰富
设计模式
1、观察者模式
观察者模式里面,changed()方法所在的实例对象,就是被观察者(Subject,或者叫Observable)
它只需维护一套观察者(Observer)的集合,这些Observer实现相同的接口,Subject只需要知道,通知Observer时,需要调用哪个统一方法就好了
2、发布订阅模式
发布者只需告诉Broker,我要发的消息,topic是AAA;
订阅者只需告诉Broker,我要订阅topic是AAA的消息;
于是,当Broker收到发布者发过来消息,并且topic是AAA时,就会把消息推送给订阅了topic是AAA的订阅者。当然也有可能是订阅者自己过来拉取,看具体实现。
也就是说,发布订阅模式里,发布者和订阅者,不是松耦合,而是完全解耦的。
死信队列
什么是死信队列?没有被及时消费的队列
没有被及时消费的原因:
1、消息被拒绝
2、TTL 消息超时未被消费
3、达到队列的最大程度
消息变成死信后,会被重新投递(publish)到另一个交换机上(Exchange),
这个交换机往往被称为DLX(dead-letter-exchange)“死信交换机”,然后交换机根据绑定规则转发到对应的队列上,
监听该队列就可以被重新消费。
生产者-->发送消息-->交换机-->队列-->变成死信队列-->DLX交换机-->队列-->监听-->消费者
拓展:
发送者发送消息的时候,如果队列长度满了,默认的策略是,丢弃最早进入队列消息的策略
但是我们可以对此进行修改(设置 overflow 为 reject - publish),此时将最新到的消息直接丢弃。
如果开启了 confirm 模式,mq 会通过 basic.nack 的方式对发送者进行消息拒绝
相关配置博客
集群模式
1、单机模式(standalone)
2、普通集群模式
运作过程:
1、创建的 queue,只会放在一个 RabbitMQ 实例上,但是每个实例都同步 queue 的元数据
(元数据可以认为是 queue 的一些配置信息,通过元数据,可以找到 queue 所在实例)
2、你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上拉取数据过来
会出现的问题:
1、mq 集群内部会有大量数据传输
2、一个节点宕机,如果消息和队列没有持久化,数据就丢了
3、镜像集群模式
特点:这个模式下,不论是你创建的 queue 还是 发送的消息,都会在集群内部进行同步,保证了消息的一致性
缺点:
1、消息同步给带宽带来的压力很大
2、这样就不是分布式了,因为每台 mq 机器都有集群中的所有数据,所以扩展性很差
扩展:什么是 node ,cluster,broker?
node:集群中的一个 mq 节点
cluster (翻译:集群):在broker的基础之上,增加了node之间共享元数据的约束
broker:指一个或多个 erlang node 的逻辑分组
关系图: