0%

mq

Basic

Concept

  • topic:主题,实现发布订阅功能
  • queue:队列,实现负载均衡功能
  • partition:分区,实现并发处理功能

ps:partition和queue的作用类似,但partition的抽象度更高

Protocol

TMQP

TMQP(Topical Message Queuing Protocol):主题消息队列协议

  • 基于主题(Topic)的消息队列协议
  • 基于生产和消费模式,支持主题分区
  • 功能较弱,但性能强大,适合数据量大的业务场景

常见的组件有Kafka、RocketMQ

RocketMQ是Kafka和RabbitMQ的混合体,性能较高(能支持较大的数据量),且功能较丰富

ps:TMQP是我自己取的名字,方便和其他协议对照说明问题

AMQP

AMQP(Advanced Message Queuing Protocol):高级消息队列协议

  • 基于交换机(Exchange)的消息队列协议
  • 基于生产和消费模式,支持路由匹配
  • 功能强大,但性能较差,适合数据量小的业务场景

常见的组件有RabbitMQ

MQTT

MQTT(Message Queuing Telemetry Transport):消息队列遥测传输协议

  • 基于主题(Topic)的消息队列协议
  • 基于发布和订阅模式,支持传输质量控制(Qos)
  • 协议比较简单轻量,适合物联网(IOT)相关的业务场景

MQTT和WebSocket对比

  • MQTT是消息传输协议,WebSocket时报文传输协议
  • WebSocket比较简单,除了传递报文的功能,就没有其他核心的功能了
  • MQTT比较复杂,除了传递消息的功能,还支持消息的发布和订阅以及消息传输质量的控制

ps:MQTT可以基于Socket(Tcp)实现,也可以基于WebSocket实现

物联网通信的数据格式

  • xml
  • json
  • bin
    • Hessian(比较早期的框架)
    • MessagePack(Json格式的优化版)
    • Protobuf(Google出品的框架)
    • Thrift(FaceBook出品的框架)
    • Avro(Hadoop的一个子项目)
    • Kyro(针对java的二进制协议)
    • Fct(针对java的二进制协议)

Middleware

RabbitMQ

Basic

Concept

Exchange

交换机类型

  • 定向交换机(单播):Direct(bindingKey和routingKey进行等值匹配)
  • 主题交换机(组播):Topic (bindingKey和routingKey进行模糊匹配)
  • 扇出交换机(广播):Fanout(bindingKey和routingKey都会被忽略掉)
  • Header交换机:对消息和队列的header进行等值匹配(支持匹配全部或者任意一个header)
  • 默认交换机:每个队列创建时都会以队列名称为bindingKey绑定到默认交换机

ps:如果发送消息时不指定交换机,就会发送到默认交换机上,此时routingKey应该为队列名称

Consumer

Manage

RocketMQ

Basic

Concept

Topic
Consumer

Manage

Kafka

Basic

Concept

Topic
Consumer

Config

Tools

Manage

ZeroMQ

基于消息队列的多线程网络库

ActiveMQ

不常用

ActiveMQ是老牌的消息队列协议,性能较差

Disque

不常用

Disque是redis作者开源的内存队列

Usage

消息延时

延迟时间:TTD(Time To Delay)

RabbitMQ

RabbitMQ原生 不支持 消息延时,但可以用以下方式来实现延时功能

  • 死信队列
  • 延时插件

RocketMQ

RocketMQ原生 支持 消息延时

Kafka

Kafka原生 不支持 消息延时

消息过期

存活时间:TTL(Time To Live)

RabbitMQ

RabbitMQ原生 支持 消息过期 ,还支持为队列里面的消息统一设置过期时间

RocketMQ

RocketMQ原生 不支持 消息过期 ,但可以通过在消费端判断 当前时间消息产生时间 的差值来实现

Kafka

Kafka原生 不支持 消息过期 ,但可以通过在消费端判断 当前时间消息时间戳 的差值来实现

消费策略

MQ消费策略

  • 按照消费模式分
    • 集群模式:独占消息
    • 广播模式:共享消息
  • 按照消费顺序分
    • 串行消费:单个消费者
    • 并行消费:多个消费者
  • 按照消费数量分
    • 单条消费:一次取一条
    • 批量消费:一次取多条

集群消费模式的分配策略

  • 轮询(round-robin)
  • 分键(key-sharding)
    • 哈希分区(hash)
    • 粘性分区(sticky)

RabbitMQ

  • 简单队列:
  • 工作队列:相当于集群模式
  • 发布订阅:相当于广播模式
  • 直接匹配:相当于分区模式
  • 通配匹配:相当于分区模式

RocketMQ

Kafka

消费反馈

  • ack:确认(消费成功,可以删除)
  • retry:重试(消费失败,需要重试)
  • discard:丢弃(消费失败,可以丢弃)

RabbitMQ

RocketMQ

Kafka

分组消费

  • 同一组:集群模式(独占消息)
  • 不同组:广播模式(共享消息)

ps:分组消费又叫多路消费

RabbitMQ

RabbitMQ原生 不支持分组消费 , 但可以通过扇出交换机广播到多个队列(每个队列是一个分组,绑定了多个消费者)来实现

RocketMQ

RocketMQ原生 支持分组消费

Kafka

Kafka原生 支持分组消费

分区消费

RabbitMQ

RocketMQ

Kafka

死信队列

RabbitMQ

RabbitMQ原生 支持死信队列

RocketMQ

RocketMQ原生 支持死信队列

Kafka

Kafka原生 不支持死信队列

传输模式

生产端:只有推模式
消费端:支持拉模式和推模式

RabbitMQ

RocketMQ

Kafka

控制参数

RabbitMQ

RocketMQ

Kafka

Reliability

Reliability(可靠性)

可靠性的关键点

  • 传输
    • 确认机制
    • 重试机制
      • 超时重试
      • 异常重试
  • 存储(持久化)
    • 写盘策略
    • 刷盘策略
    • 同步策略(主从同步策略)

可靠性的保证

  • 生产端:使用确认机制
    • 同步发送:同步发送并ACK(sync)
    • 异步发送:异步发送并ACK(async)
    • 单向发送:异步发送且不ACK(oneway)
  • 队列端:开启持久化机制(刷盘策略 + 主从同步策略)
    • 写盘策略:
      • 同步写盘:写到磁盘后才返回ACK
      • 异步写盘:写到页缓存后就返回ACK
    • 刷盘策略:
      • 每次刷盘
      • 每秒刷盘
      • 系统刷盘
    • 同步策略:
      • 不同步:不需要同步到从节点
      • 半同步:至少需要同步到一个从节点
      • 全同步:需要同步到所有的从节点
  • 消费端:使用手动确认机制(不使用自动确认机制)
    • 不确认:收到消息后不需要确认
    • 自动确认:收到消息后先确认再消费
    • 手动确认:收到消息后先消费再确认

RabbitMQ

  • 生产端:使用确认机制(使用confirm机制)
  • 队列端:开启持久化机制(交换机、队列、消息)
  • 消费端:使用手动确认机制(basicAck)

ps:生产端建议使用确认(confirm)机制,不建议使用事务(transaction)机制
ps:确认机制是异步操作,性能好
ps:事务机制是同步操作,性能差

RocketMQ

  • 生产端:使用确认机制(使用异步发送)
  • 队列端:开启持久化机制(同步刷盘策略 + 同步主从同步策略)
  • 消费端:使用手动确认机制(ConsumeStatus)

ps:生产端建议使用异步发送,而不是同步发送和单向发送
ps:异步发送是异步操作,性能好
ps:同步发送是同步操作,性能差
ps:单向发送无确认机制,会丢失消息

Kafka

  • 生产端:使用确认机制(生产者的acks配置为1)
  • 队列端:开启持久化机制(同步刷盘策略 + 同步主从同步策略)
  • 消费端:使用手动确认机制(手动提交offset)

ps:acks含义 0:不关心结果 1:只需主节点写完成 -1:所有从节点都同步完成

Ack(确认机制)

RabbitMQ

RocketMQ

Kafka

Retry(重试机制)

RabbitMQ

RocketMQ

Kafka

Timeout(超时问题)

RabbitMQ

RocketMQ

Kafka

Quality(传输质量)

MQ传输质量

  • 最多一次:at most once(会导致消息丢失的问题)
  • 最少一次:at least once(会导致消息重复的问题)
  • 精确一次:exactly once(需要进行幂等处理)

MQTT传输质量

  • Qos-0:最多一次
    • 消息发送
      • PUBLISH:发送者
    • 消息丢失
      • PUBLISH:丢失了发送者不会重发
  • Qos-1:最少一次
    • 消息发送
      • PUBLISH:发送者
      • PUBACK:接收者
    • 消息丢失
      • PUBLISH:丢失了发送者会重发PUBLISH
      • PUBACK:丢失了发送者会重发PUBLISH
  • Qos-2:精确一次
    • 消息发送
      • PUBLISH:发送者
      • PUBREC:接收者
      • PUBREL:发送者
      • PUBCOMP:接收者
    • 消息丢失
      • PUBLISH:丢失了发送者会重发PUBLISH
      • PUBREC:丢失了发送者会重发PUBLISH
      • PUBREL:丢失了发送者会重发PUBREL
      • PUBCOMP:丢失了发送者会重发PUBREL

ps:发送者会重发消息,接收者不会重发消息

MQTT消息说明

  • PUBLISH:发送者发送了数据消息
  • PUBACK:接收者收到了数据消息
  • PUBREC:接收者收到了数据消息,告知发送者可以删除用来重发的数据消息缓存
  • PUBREL:发送者发送了释放消息,告知接收者可以删除用来去重的数据消息缓存
  • PUBCOMP:接收者收到了释放消息,告知发送者可以删除用来重发的释放消息缓存

ps:ACK -> acknowledge,REC -> received,REL -> release,COMP -> complete

RabbitMQ

RocketMQ

Kafka

Durability(持久化)

RabbitMQ

RocketMQ

Kafka

Problem

消息丢失

问题描述:消息丢失
解决办法:确认机制 + 重试机制 + 持久化机制

  • 生产时丢失
    • 场景1
      • 丢失原因:使用自动确认机制时,网络有问题导致生产端发送消息失败
      • 解决办法:使用重试机制
    • 场景2
      • 丢失原因:使用自动确认机制时,网络有问题导致队列端返回ACK失败
      • 解决办法:使用重试机制
    • 场景3
      • 丢失原因:使用自动确认机制时,队列端处理异常导致生产端发送消息失败
      • 解决办法:使用重试机制
  • 入队时丢失
    • 场景1
      • 丢失原因:队列端服务强停时,消息还在内存缓冲区中没有持久化到磁盘
      • 解决办法:开启持久化机制
    • 场景2
      • 丢失原因:队列端服务崩溃时,消息还在内存缓冲区中没有持久化到磁盘
      • 解决办法:开启持久化机制
    • 场景3
      • 丢失原因:队列端机器宕机时,消息还在内存缓冲区中没有持久化到磁盘
      • 解决办法:开启持久化机制
  • 消费时丢失
    • 场景1
      • 丢失原因:使用手动确认机制时,消费端收到消息后忘记了返回ACK
      • 解决办法:需要返回ACK
    • 场景2
      • 丢失原因:使用自动确认机制时,消费端收到消息后不管是否处理成功就返回了ACK
      • 解决办法:需要在处理成功后返回ACK
    • 场景3
      • 丢失原因:使用手动确认机制时,消费端收到消息后使用了异步处理并立即返回了ACK
      • 解决办法:需要在异步处理成功后返回ACK

RabbitMQ

RocketMQ

Kafka

消息重复

问题描述:消息重复
解决办法:幂等处理(数据库唯一性去重 或者 redis的setnx去重)

  • 生产时重复
    • 场景1
      • 重复原因:生产时,队列端回复的ACK丢失了,生产端没有收到ACK会重发
      • 解决办法:队列端进行幂等处理
  • 消费时重复
    • 场景1
      • 重复原因:消费时,消费端回复的ACK丢失了,队列端没有收到ACK会重推
      • 解决办法:消费端进行幂等处理

ps:反正最后都需要在消费端解决一下,所以只需要在消费端解决就行了

RabbitMQ

RocketMQ

Kafka

消息乱序

问题描述:消息乱序
解决办法:分区有序

  • 生产时乱序
    • 场景1
      • 乱序原因:因为网络的复杂性,先生产的消息可能因发送时间长而后到达
      • 解决办法:
    • 场景2
      • 乱序原因:因为消息的大小不同,先生产的消息可能因发送时间长而后到达
      • 解决办法:
  • 消费时乱序
    • 场景1
      • 乱序原因:存在多分区时,消息投递到了消息积压多的分区,导致比后面的消息晚消费
      • 解决办法:生产时保证分区有序 或者 只创建一个分区
    • 场景2
      • 乱序原因:存在多分区时,先消费的消息可能晚于后消费的消息完成
      • 解决办法:

ps:总结为3种原因,1. 先发送但后到达 2. 先到达但后消费 3. 先消费但后完成

RabbitMQ

RocketMQ

Kafka

消息积压

问题描述:消息积压
解决办法:需要提高消费速度(增加消费者)

  • 拉模式时消息会积压在队列端
  • 推模式时消息会积压在消费端

ps:当消费者数量大于分区数量时,多余的消费者也没活干,这时增加消费者也没用,这时候就需要新建一个分区更多的Topic,并启动一个 数据迁移消费者 将旧Topic迁移到新Topic中,然后增加消费者消费新的Topic

RabbitMQ

RocketMQ

Kafka

消息溢出

问题描述:消息溢出
解决办法:需要抑制生产速度(阻塞生产者)

RabbitMQ

RocketMQ

Kafka

Performance

Kafka为什么这么快

  • 顺序读写:寻址快
  • 分区读写:并发读写
  • 批量读写:减少网络耗时
  • 数据压缩:减少数据量从而减少读写时间和传输时间
  • 页缓存:避免实时写磁盘的慢操作
  • 零拷贝:避免多次拷贝造成的时间浪费

Architecture

Replication

Cluster

Distributed

Application

Theory

Other

Management

管理

Visual

Tools

Operation

运维

只想买包辣条