消息队列之Kafka | 青训营

99 阅读4分钟

前言:

本笔记主要记录了学习消息队列相关知识的内容,因篇幅较长将Kafka和BMQ、RocketMQ拆分为两篇笔记

本文主要为Kafka相关内容

什么是消息队列

消息队列(MQ),指保存消息的一个容器,本质是个队列。

但这个队列,需要支持高吞吐,高并发,高可用。

常见的消息队列有:ActiveMQ,RabbitMQ,Kafka,阿里的RocketMQ,以及目前存算分离的Pulsar,在目前互联网应用中消息队列中间件基本上成为标配。


关于Kafka

Kafka是什么?

Kafka是Apache旗下的一款分布式流媒体平台,Kafka是一种高吞吐量、持久性、分布式的发布订阅的消息队列系统。 它最初由LinkedIn(领英)公司发布,使用Scala语言编写,与2010年12月份开源,成为Apache的顶级子项目。 它主要用于处理消费者规模网站中的所有动作流数据。动作指(网页浏览、搜索和其它用户行动所产生的数据)。

使用步骤

  1. 创建集群
  2. 新增Topic,设置好分片数量
  3. 编写生产者逻辑
  4. 编写消费者逻辑

基本概念

Topic:

Kafka中的逻辑队列,不同的业务场景对应不同的Topic,对于这个业务来说,所有的数据都存储在这个topic中。

Partition:

通常topic会有多个分片,不同分片之间消息可以并发处理,这样提高单个topic的吞吐

Cluster:

Kafka中的物理集群,每个集群中可以新建多个不同的topic。

一个Kafka服务器也称为Broker,若干个Broker组成一个集群(Cluster),其中集群内某个Broker会成为集群控制器Cluster Controller),它负责管理集群,包括分配分区到 Broker、监控 Broker 故障等。在集群内,一个分区由一个 Broker 负责,这个 Broker 也称为这个分区的 Leader;当然一个分区可以被复制到多个 Broker 上来实现冗余,这样当存在 Broker 故障时可以将其分区重新分配到其他 Broker 来负责。

Producer:

消息的生产端,负责将业务消息发送到topic中。

Consumer:

消息的消费端,负责消费已经发送到topic中的消息。

Offset:

消息在partition内的相对位置信息,可以理解为唯一ID,在partition内部严格递增。

Replica:

即为分片的副本,分布在不同的机器上,可以用来容灾,Leader对外服务,Follower异步去拉取Leader的数据进行同步。如果Leader挂掉了,可以将Follower升级为Leader再对外服务

每个Partition有多个Replica,Leader Replica 将会从 ISR(In - Sync Replica )中选出

ISA:意思是同步中的副本,对于Follower来说,始终和Leader是有差距的,但当这个差距比较小的时候,我们就可以将这个follower副本加入ISR中,不在ISR中的副本是不允许提升为Leader的。

Kafka架构

在集群的基础上,还有一个模块是Zookeeper。

这个模块其实是存储了集群的元数据信息,比如副本的分配信息,Controller计算好的方案都会放到这个地方。

为什么Kafka能支持这么高的吞吐?

下面由一条消息的处理流程进行分析,了解其为何有如此高的吞吐

  • Producer :

    • 批量发送:批量发送可以减少IO次数,从而加强发送能力
    • 数据压缩:通过压缩,减小信息大小,目前支持Snappy、Gzip、LZ4、ZSTD压缩算法
  • Broker:(数据的存储:如何存储到磁盘)

    • 顺序写:由于物理上的磁盘结构:移动磁头寻找对应磁道,磁盘转动,找到对应扇区,最后写入,其中寻道成本较高。因此顺序写可以减少寻道带来的时间成本
    • 消息索引:通过offset索引文件,加快寻找消息的速度
    • 零拷贝:Consumer从Broker中读取数据,通过sendfile的方式,将磁盘读到os内核缓冲区后,直接转到socket buffer 进行网络发送。Producer生产的数据持久化到Broker,采用map文件映射,实现顺序的快速写入。
  • Consumer

    • Rebalance:对于一个Consumer Group来说,通过多个分片并发的消费,可以大大提高消费的效率。这其中存在一个问题:对于每一个Partition来说,该由哪一个Consumer来消费。对于这个问题,一般有两种解决方法:手动分配和自动分配
      1. 手动分配:即Kafka中的Low Level的消费方式进行消费,好处是启动快(因为已经确定了每个Consumer对应的Partition),缺点是不够灵活。
      2. 自动分配:即Kafka中的High Level的消费方式。即每一Consumer Group集群中使用一个Broker作为Coordinator来进行分片的分配。

架构缺点

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