AMQP
RabbitMQ 就是 AMQP 协议的 Erlang 的实现(当然 RabbitMQ 还支持 STOMP2、 MQTT3 等协议 ) AMQP 的模型架构和 RabbitMQ 的模型架构是一样的,生产者将消息发送给交换器,交换器和队列绑定。
RabbitMQ中的交换器、交换器类型、队列、绑定、路由键等都是遵循的 AMQP 协议中相应的概念。
AMQP 协议的三层 :
- Module Layer:协议最高层,主要定义了一些客户端调用的命令,客户端可以用这些命令实现自己的业务逻辑。
- Session Layer:中间层,主要负责客户端命令发送给服务器,再将服务端应答返回客户端,提供可靠性同步机制和错误处理。
- TransportLayer:最底层,主要传输二进制数据流,提供帧的处理、信道服用、错误检测和数据表示等。
AMQP 模型的三大组件
- 交换器 (Exchange) :消息代理服务器中用于把消息路由到队列的组件。
- 队列 (Queue) :用来存储消息的数据结构,位于硬盘或内存中。
- 绑定 (Binding) :一套规则,告知交换器消息应该将消息投递给哪个队列
RabbitMQ架构
- Broker:接收和分发消息的应用,RabbitMQ Server 就是 Message Broker
- Connection:publisher/consumer 和 broker 之间的 **TCP** 连接
- Channel:如果每一次访问 RabbitMQ 都建立一个 Connection,在消息量大的时候建立 TCP,Connection 的开销将是巨大的,效率也较低。Channel 是在 connection 内部建立的逻辑连接,如果应用程序支持多线程,通常每个 thread 创建单独的 channel 进行通讯,AMQP method 包含了 channel id 帮助客户端和message broker 识别 channel,所以 channel 之间是**完全隔离**的。Channel 作为轻量级的 Connection 极大减少了操作系统建立 TCP connection 的开销
- Exchange:message 到达 broker 的第一站,根据分发规则,匹配查询表中的 routing key,分发消息到 queue 中去。常用的类型有:direct (point-to-point), topic (publish-subscribe) and fanout (multicast)
- Queue:消息最终被送到这里等待 consumer 取走
- Binding:exchange 和 queue 之间的虚拟连接,binding 中可以包含 routing key,Binding 信息被保存到 exchange 中的查询表中,用于message 的分发依据
RabbitMQ六大模式
死信队列
由于特定的原因导致 queue 中的某些消息无法被消费,这样的消息如果没有 后续的处理,就变成了死信,从而有了死信队列。
应用场景:为了保证订单业务的消息数据不丢失,需要使用到 RabbitMQ的死信队列机制,当消息消费发生异常时,将消息投入死信队列中.还有比如说: 用户在商城下单成功并点击去支付后在指定时间未支付时自动失效
- 消息 TTL 过期
- 队列达到最大长度(队列满了,无法再添加数据到mq中)
- 消息被拒绝(basic.reject 或 basic.nack)并且 requeue=false
消息可靠性
分为三个阶段:消息到 MQ 的过程中,MQ 本身,MQ 到消费过程中
- 生产者到 RabbitMQ:事务机制和 Confirm 机制(不能共存)
- RabbitMQ 自身:持久化、集群、普通模式、镜像模式。
- RabbitMQ 到消费者:basicAck 机制、死信队列、消息补偿机制。
幂等性
幂等是数学上的概念,可以理解为同样的参数多次调用同一个接口和调用一次产生的结果是一致的;
SQL层面:做前置条件判断,版本号控制,对比消息中的版本号和数据库中的版本号;约束例如唯一键;
消息层面:记录关键的key例如:订单ID,也可以用全局唯一ID等等;利用 redis里面的set数据结构+Lua 的原子性去实现