kafka学习

331 阅读4分钟

kafka构成

  • producer:消息生产者
  • broker:kafka实例,集群的单点,每个实例有自己的编号
  • topic:消息的主题,每个broker都有多个topic,topic一致,逻辑分区。
  • Topic的分区,每个topic可以有多个分区,分区的作用是做负载,提高kafka的吞吐量。同一个topic在不同的分区的数据是不重复的,partition的表现形式就是一个一个的文件夹
  • Replication:每一个分区都有多个副本,副本的作用是做备胎。当主分区(Leader)故障的时候会选择一个备胎(Follower)上位,成为Leader。在kafka中默认副本的最大数量是10个,且副本的数量不能大于Broker的数量,follower和leader绝对是在不同的机器,同一机器对同一个分区也只可能存放一个副本(包括自己)。
  • Message:每一条发送的消息主体。
  • Consumer:消费者,即消息的消费方,是消息的出口。
  • Consumer Group:将多个消费组者组成一个消费者组,同一个分区的数据只能被消费者组中的某一个消费者消费。同一个消费者组的消费者消费同一个topic的不同分区的数据提高kafka的吞吐量(个人理解:ConsumerABC对应topicABC,一个Consumer可以对应多个partition(物理分区),但是一个partition只能对应一个Consumer,建议数量一致)
  • Zookeeper:kafka集群依赖zookeeper来保存集群的的元信息,来保证系统的可用性。

image.png

工作流程

  • 发送数据:follower在leader收到消息后主动去同步,每个topic中的消息采用队列的方式FIFO。
  • 如何发送到partition:
    1. partition在写入的时候可以指定需要写入的partition,如果有指定,则写入对应的partition。
    2. 如果没有指定partition,但是设置了数据的key,则会根据key的值hash出一个partition。
    3. 如果既没指定partition,又没有设置key,则会轮询选出一个partition。

image.png

  • 如何保证消息不丢失:上图中的ack机制:

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

    • Producer将数据写入kafka后,集群就需要对数据进行保存了,kafka将数据保存在磁盘,写入磁盘是比较耗时的操作,不适合这种高并发的组件。Kafka初始会单独开辟一块磁盘空间,顺序写入数据(效率比随机写入高)。
  • Partition结构

    • 如下图,每个Partition在磁盘中相当于一个文件夹,文件夹中又有个好几个segment文件夹,segment文件夹中有三个文件,index就是offset,通过分段+索引来完成快速查找
    • log存储producer发送的消息,消息体主要包括消息体,消息大小,offset
      • offset8位byte的id序号,确定唯一的在partition内位置
      • 消息大小:4byte来描述消息的大小
      • 消息体:存放被压缩过的消息数据 image.png
  • 存储策略:无论消息是否被消费,kafka都会保存消息。对于旧数据的删除有基于时间(默认七天)和基于大小(默认1073741824)的删除策略,读取消息时间复杂度为o(1),删除过期时间不会提高读取效率

  • 消费数据:

    • consumer找leader拉取消息(找到对应partition)
    • 二分查找找到partiton中segment的位置
    • index文件中查找对应偏移量的行号
    • 打开数据文件,查到找index中找到的行号

ISR AR OSR

AR = ISR + OSR

  • AR 所有副本
  • ISR 副本同步队列
  • OSR 副本不同步队列

为什么kafka速度快

  • 零拷贝技术,不用到用户态,内核态复制后直接传递
  • 顺序写,partition是一块连续硬盘空间,加上操作系统的预读和写技术,比内存的随机读取快
  • pull辣模式,消息消费速度等同于消费端处理速度

为什么kafka不支持读写分离

  • kafka主写从写
  • 涉及一致性问题,可能出现主从不一致的情况
  • 同时在同步的过程中,需要时间,不同于redis,这个还需要拷贝到硬盘中,速度更慢。

kafka解决消费丢失和重复消费

  • 消费丢失:kafka有ack机制,参考上文。
  • 重复消费:当消费者消费后,还没有更新offset,重启后再次消费。
    • 解决:主要就是保证幂等
      • 如果是写库,先查一下主键是否存在,存在就update
      • 如果是redis,天然幂等,set
      • 可以设置一个全局id,消费存入redis,先在redis查询是否消费过
      • 设置主键约束,不能插入多条主键相同的数据