千家信息网

消息队列之kafka(核心架构)

发表于:2024-12-12 作者:千家信息网编辑
千家信息网最后更新 2024年12月12日,1. Kafka的经典架构 Kafka是LinkedIn 用于日志处理的分布式消息队列,同时支持离线和在线日志处理。 Kafka 对消息保存时根据 Topic 进行归类。 发送消息者就是Produce
千家信息网最后更新 2024年12月12日消息队列之kafka(核心架构)

1. Kafka的经典架构


 Kafka是LinkedIn 用于日志处理的分布式消息队列,同时支持离线和在线日志处理。
 Kafka 对消息保存时根据 Topic 进行归类。
 发送消息者就是Producer,消息的发布描述为Producer
 消息接受者就是 Consumer,消息的订阅描述为 Consumer
 每个 Kafka 实例称为 Broker,将中间的存储阵列称作 Broker(代理),Broker也是kafka集群的节点

2.架构的角色介绍

  (1)broker

  kafka集群包括一个或者多个服务器,这种服务器被称为brker。
  broker也就是中间的存储队列的节点实例。我们将消息发布者称为:Produce,将消息的订阅者称为:Consumer,将中间的存储阵列称为broker。

  (2)topic

  每条发布到kafka集群的消息都有一个类别,这个类别被成为Tpoic。物理上不同的topic的消息分开存储,逻辑上一个topic的消息虽然保存与一个或者多个broker中。但用户只需要指定消费的topic,即生产或者消费数据的客户端不需要关心数据存储与何处。
  kafka中发布订阅的对象就是topic。为每一个数据类型创建一个topic,把向topic发布消息的客户端称为producer,从topic订阅消息的客户端称为consumer,producer和consumer可以同时从多个topic读写数据。一个kafka集群由一个或者多个broker服务器组成。他负责持久化和备份具体的kafka消息。
  topic就是数据的主题,是数据记录发布的地方,可以用来区分业务系统。kafka中的topics总是多订阅者模式,一个topic可以拥有一个或者多个消费者来订阅它的数据。

  (3)partition


  partition是物理的概念,每一个topic包含一个或者多个partition。
  topic的分区策略(针对写数据的时候进行分区):
    - 轮询:顺序分发,仅针对于message没有key的时候。
    - Hash分区:在message有key的情况下,(key.hash%分区个数)。如果在增加分区的时候,partition里面的message不会重新进行分配,随着数据的继续写入,这个新的分区才会参与load balance。


  topic的分区逻辑存储方式

   topic 会分成一个或多个 partition,每个 partiton 相当于是一个 子 queue。在物理结构上,每个 partition 对应一个物理的目录(文件夹),文件夹命名是 [topicname][partition][序号],一个 topic 可以有无数多的 partition,根据业务需求和数据量 来设置。在 kafka 配置文件中可随时更高 num.partitions 参数来配置更改 topic 的 partition 数 量,在创建 Topic 时通过参数指定 parittion 数量。Topic 创建之后通过 Kafka 提供的工具也可以修改 partiton 数量。分区中存放着数据本身和数据的index下标。在向partition写入数据的时候,是顺序写入的,每一个数据写入的时候都会有一个类似下标的东西(index),随着数据的写入而增长。partition也是集群负载均衡的基本单位。


  总结
    - 一个topic的partition数量大于等于broker的数量,可以提高吞吐率。
    - 同一个partition的Replica尽量分散到不同的机器上,高可用。
    - kafka的分区数:(1|2|3 + 0.95) * broker数量

  (4)Producer

   负责主动发布消息到kakfa broker(push)
   kafka消息的保存策略:每个 Topic 被分成多个 partition(区)。每条消息在 partition 中的位置称为 offset(偏移量),类型为 long 型数字。消息即使被消费了,也不会被立即删除, 而是根据 broker 里的设置(基于时间存储或者基于大小),保存一定时间后再清除,比如 log 文件设置存储两天,则两天后, 不管消息是否被消费,都清除。

  (5)Consumer

   消息消费者,向kafkabroker读取消息的客户端。(pull)
   消费消息的策略:(使用的是roundrabin算法):如果有4个分区,现在有三个消费者线程,那么这个三个线程一人分一个分区消费,最后一个分区以轮询的方式,发送给第一个线程消费,如果此时又多加入一个线程,那么就会将第4个分区就分给新加入的线程消费,如果有一个线程退出,那么第三个和第四个分区也会以轮询的方式,发送给第一个线程和第二个线程消费。(kafka内部自动维护这个负载均衡)。
   消费的原则:一个consumer对一个partition中的一条数据只需要消费一次,每一个consumer组维护一个下标文件,叫做offset,这个offset用于记录当前的consumer组消费数据的下标,每进行消费一条数据,当前的offset就会递增1(offset之前的数据,都表示已经消费过的数据)。

  (6)Consumer group


   一个consumer group 包含多个consumer,这个是预先在配置文件中配置好的。各个consumer可以组成一个租,partition中的每一个message只能被一个组中的一个consumer进行消费,其他的consumer不能消费同一个topic中同一个分区的数据,不同组的consumer可以消费同一个topic的同一个分区的数据。
    广播和单播
     广播:所有的consumer每一个consumer划分一组
     单播:所有的consumer划分一组(一组中只允许一个消费)
    对于kafka消费的总结
      - 一个分区只能被一个消费者组中的一个成员消费
      - 一个成员可以消费一个topic的多个分区
      - 一个 Topic 中的每个 Partition 只会被一个"Consumer group"中的一个 Consumer 消费
      - 一个成员还可以消费另外一个topic的分区

  (7)segment

    在kafka文件存储找中,同一个topic下有多个partition,每一个partition为一个目录,partition命名规则为:topic 名称+有序序号,第一个partition序号从0开始,序号最大值为partitions数量-1,partition物理上由多个segment组成,每一个segment存储着多个message信息(默认是:1G),而每一个message是由一个key-value和一个时间戳组成。
    segment文件的生命周期由服务器配置参数决定:默认的是168个小时后删除。
    segment由两大部分组成: index filedata file,这2个文件一一对应,成对出现,后缀".index"和".log"分别表示为 segment 索引文件、数据文件。

    segment的命名规则:partion 全局的第一个 segment 从 0 开始,后续每个 segment 文件名为上一个 segment 文件最后一条消息的 offset 值。数值最大为 64 位 long 大小,19 位数字字符长度,没有数字用 0 填充。(每一个partition都是如此)
    segment的index file: 索引文件存储大量元数据,数据文件存储大量消息,索引文件中元数据指向对应数据文件中 message 的物理偏移地址。

    segment的data file


kafka读取数据的查找message的步骤
以读取 offset=368776 的 message,需要通过下面 2 个步骤查找。

第一步:00000000000000000000.index,表示最开始的文件,起始偏移量(offset)为 0,00000000000000368769.index 的消息量起始偏移量为 368770 = 368769 + 1,00000000000000737337.index 的起始偏移量为 737338=737337 + 1,其他后续文件依次类推。以起始偏移量命名并排序这些文件,只要根据 offset 二分查找文件列表,就可以快速定 位到具体文件。当 offset=368776 时定位到 00000000000000368769.index 和对应 log 文件。
第二步:当 offset=368776 时,依次定位到 00000000000000368769.index 的元数据物理位置和 00000000000000368769.log 的物理偏移地址,然后再通过 00000000000000368769.log 顺序查找直到 offset=368776 为止。查找的时候是通过相对偏移量,在.index文件中有两列(序列,地址),其中序列是相对偏移量:序列=查找的message的偏移量-当前文件的起始偏移量 ,然后根据序列对应的地址,找到相应的位置上的数据message。

0