什么是消息队列?

消息队列MQ是保存消息的一个容器,本质是一个队列,这个队列需要支持高吞吐、高并发和高可用

消息队列诞生于1985,服务于金融机构和新闻机构,简称为TIB。后来IBM和微软逐渐开始加入研发属于自己的消息队列。后来AMQP将消息队列技术推广了开来。

常用消息队列:
Kafka:分布式、分区的、多副本的日志提交服务,在高吞吐场景下发挥出色
RocketMQ:出自阿里之手,低延迟、强一致、高性能,在实时场景中运用较广
Pulsar:开源的下一代云原生分布式消息流平台,采用存算分离架构设计,腾讯出资并在使用,
BMQ:和Pulsar蕾西,存算分离,初期定位是承接高吞吐离线业务场景,逐渐替换掉Kafka集群

Kafka

使用场景

一般用于离线业务场景,比如日志信息、Metrics数据和用户行为分析。

基本概念和结构

创建集群->新建Topic->编写生产者逻辑->编写消费者逻辑

mq切换kafka kafka ibm mq_分布式


一些基本概念

Topic:逻辑队列,不同的业务场景可以创建不同的Topic

Cluster:物理集群,每个集群可以创建不同的Topic

Producer:生产者,负责将业务消息发送到Topic中

Consumer:消费者,负责消费Topic中的消息

ConsumerGroup:消费者组,不同的消费者组进度互不干涉

在一个topic内部,有多个partition,用于存储消息,每一个partition可以存储多个消息,每一个消息有一个 OFFSET,OFFSET是消息在partition内的相对位置信息,可以理解为唯一的ID

mq切换kafka kafka ibm mq_数据_02

每一个partition中有多个replica(副本),这些副本有着不同的角色,分别是leader和Follower,Leader负责对外进行写入和读出,Follower会尽量保持自身存储内容和Leader一致。如果Leader发现有Follow和自身存储的信息差别太大(比如下图中的replica3),则会将replica踢出ISR。那么ISR有什么用呢,当Leader发生了宕机,则会从ISR中选择Follower成为新的Leader,这就是Kafka高可用的地方

mq切换kafka kafka ibm mq_数据_03

Kafka架构

mq切换kafka kafka ibm mq_分布式_04


Kafka中Zookeeper用于存储集群单元信息,包括分区信息

而broker是消息的中介,生产者producer往broker里面指定的topic中写消息,消费者consumer从broker里面拉取指定topic的消息,然后进行业务处理,broker在中间起到一个代理保存消息的中转站。

从一条消息分析Kafka流程

mq切换kafka kafka ibm mq_数据_05

producer在向broker发送消息的时候,会进行批量发送,而不是逐条发送,而且会通过Snappy,Gzip等压缩算法对消息进行压缩,从而减少带宽的压力。

在讨论Broker如何将消息回存到本地磁盘之前(也就是Consumer消费的过程),我们先看看Broker消息文件结构。

mq切换kafka kafka ibm mq_mq切换kafka_06

副本replica最终会以log的形式写入到磁盘中

Broker如何找到已经存入的文件

可以通过时间戳索引,也可以通过OFFSET寻找

待补充

数据拷贝

传统的数据拷贝

mq切换kafka kafka ibm mq_分布式_07


这期间使用了十分多的Buffer之间的拷贝,使得开销十分大

使用了零拷贝之后,内核态直接从磁盘读出数据后,直接送到网卡缓冲区NIC Buffer,这大大降低了开销

mq切换kafka kafka ibm mq_分布式_08

Consumer-消息接收端

每个消费者组都需要拉取全部partition数据,那么哪个Consumer负责拉取哪个partition数据呢?最简单的是手动拉取的,在启动的时候分配任务,哪个Consumer负责拉取哪几个partition。但是万一其中一个Consumer宕机,就会导致无法拉取到完全的partition。

另外还可以使用自动分配方式,也就是对于每一个消费者组,都会选择一个Broker作为一个协调者Coordinator,这个协调者负责分配各个消费者获取partition的任务,这使得可以动态调整各个Consumer的任务。这又称为Consumer Rebalance。

Kafka的缺点

  1. 运维成本高
  2. 对于负载不均衡场景,解决方案负责
  3. 没有自己的缓存,完全依赖Page Cache
  4. Controller和Coordinator以及Broker在同一进程内,大量IO会导致其性能下降