• kafka学习(二)kafka工作流程分析


    一、发送数据

    follower的同步流程

    PS:Producer在写入数据的时候永远的找leader,不会直接将数据写入follower

    PS:消息写入leader后,follower是主动的去leader进行同步的!

    PS:producer采用push模式将数据发布到broker,每条消息追加到分区中,顺序写入磁盘,所以保证同一分区内的数据是有序的

    PS:不存在的topic写数据,kafka会自动创建topic,分区和副本的数量根据默认配置都是1。

    分区

    主要目的:

    方便扩展:因为一个topic可以有多个partition,所以我们可以通过扩展机器去轻松的应对日益增长的数据量。
    提高并发:以partition为读写单位,可以多个消费者同时消费数据,提高了消息的处理效率。

    分发策略:

      1、 partition在写入的时候可以指定需要写入的partition,如果有指定,则写入对应的partition。
      2、 如果没有指定partition,但是设置了数据的key,则会根据key的值hash出一个partition。
      3、 如果既没指定partition,又没有设置key,则会轮询选出一个partition。

    ACK应答机制

    在生产者向队列写入数据的时候可以设置参数来确定是否确认kafka接收到数据,这个参数可设置的值为0、1、all。(保证消息不丢失)

      0:代表producer往集群发送数据不需要等到集群的返回,不确保消息发送成功。安全性最低但是效率最高。
      1:代表producer往集群发送数据只要leader应答就可以发送下一条,只确保leader发送成功。
      all:代表producer往集群发送数据需要所有的follower都完成从leader的同步才会发送下一条,确保leader发送成功和所有的副本都完成备份。安全性最高,但是效率最低。

    二、保存数据

      Kafka初始会单独开辟一块磁盘空间,顺序写入数据(效率比随机写入高),将数据保存在磁盘。

      PS:任何发布到 Partition 的消息都会被追加到 Partition 数据文件的尾部,且消息消费后不会删除(删除策略是针对过期的 Segment 文件),这样的顺序写磁盘操作让 Kafka 的效率非常高(经验证,顺序写磁盘效率比随机写内存还要高,这是 Kafka 高吞吐率的一个很重要的保证)。

    Partition 结构

      Partition在服务器上的表现形式就是一个一个的文件夹,每个partition的文件夹下面会有多组segment文件,每组segment文件又包含.index文件、.log文件、.timeindex文件(早期版本中没有)三个文件, log文件就实际是存储message的地方,而index和timeindex文件为索引文件,用于检索消息

      PS:Segment 是 Kafka 文件存储的最小单位。

      如上图,这个partition有三组segment文件,每个log文件的大小是一样的,但是存储的message数量是不一定相等的(每条的message大小不一致)。文件的命名是以该segment最小offset来命名的,如000.index存储offset为0~368795的消息,kafka就是利用分段+索引的方式来解决查找效率的问题

    Message结构

      上面说到log文件就实际是存储message的地方,我们在producer往kafka写入的也是一条一条的message,message主要包含消息体、消息大小、offset、压缩类型……等等

    offset:offset是一个占8byte的有序id号,它可以唯一确定每条消息在parition内的位置!
    消息大小:消息大小占用4byte,用于描述消息的大小。
    消息体:消息体存放的是实际的消息数据(被压缩过),占用的空间根据具体的消息而不一样。

    存储策略

      无论消息是否被消费,kafka都会保存所有的消息(存在磁盘)。那对于旧数据有什么删除策略呢?
        基于时间,默认配置是168小时(7天)。
        基于大小,默认配置是1073741824。
      需要注意的是,kafka读取特定消息的时间复杂度是O(1),所以这里删除过期的文件并不会提高kafka的性能

    三、消费数据

    Kafka采用的是点对点的模式,消费者主动的去kafka集群拉取消息,与producer相同的是,消费者在拉取消息的时候也是找leader去拉取

    • 多个消费者可以组成一个消费者组(consumer group),每个消费者组都有一个组id。
    • 同一个消费组的消费者可以消费同一topic不同分区的数据,但是不会组内多个消费者消费同一分区的数据!!!
    • 消费者数少于分区:会出现某个消费者消费多个partition数据的情况(此时消费的速度不及只处理一个partition的消费者的处理速度)
    • 消费者数多于分区:多出来的消费者不消费任何partition的数据。
    • 建议消费者组的consumer的数量与partition的数量一致!

    四、搜索数据

    搜索数据样例解析

    假如现在需要查找一个offset为368801的message是什么样的过程呢?用一个例子来解释一下搜索过程

     

    • 先找到offset的368801message所在的segment文件(利用二分法查找),这里找到的就是在第二个segment文件。
    • 打开找到的segment中的.index文件(也就是368796.index文件,该文件起始偏移量为368796+1,我们要查找的offset为368801的message在该index内的偏移量为368796+5=368801,所以这里要查找的相对offset为5)。利用二分法查找相对offset小于或者等于指定的相对offset的索引条目中最大的那个相对offset,所以找到的是相对offset为4的这个索引。
    • 根据找到的相对offset为4的索引确定message存储的物理偏移位置为256。打开数据文件,从位置为256的那个地方开始顺序扫描直到找到offset为368801的那条Message。

      PS:注意该 index 文件并不是从0开始,也不是每次递增1的,这是因为 Kafka 采取稀疏索引存储的方式,每隔一定字节的数据建立一条索引,它减少了索引文件大小,使得能够把 index 映射到内存,降低了查询时的磁盘 IO 开销,同时也并没有给查询带来太多的时间消耗。

      小结:这套机制是建立在offset为有序的基础上,利用segment+有序offset+稀疏索引+二分查找+顺序查找等多种手段来高效的查找数据!至此,消费者就能拿到需要处理的数据进行处理了。

    消费者记录位置的方式

    早期的版本:消费者将消费到的offset维护zookeeper中,consumer每间隔一段时间上报一次,这里容易导致重复消费,且高并发时和ZK频繁交互,性能不好!

    新的版本:消费者消费到的offset已经直接维护在kafk集群的__consumer_offsets这个topic中!

     

    参考资料:

  • 相关阅读:
    标准部件工具箱概述
    从数据库和文件夹中读取图片并且resize
    控件的Lookup
    分隔字符串并以List返回(strSplit函数)
    窗体中的选中数据传递给报表
    对筛选之后的grid进行求和统计
    动态添加图片控件例子
    利用CSV文件导入数据的例子
    调用打开文件的对话框
    ax设置数据源的操作
  • 原文地址:https://www.cnblogs.com/riches/p/11426988.html
Copyright © 2020-2023  润新知