Kafka 题

作者: 水木共美 | 来源:发表于2021-06-29 13:43 被阅读0次

    1、kafka的设计

    消息的生产者producer
    消息的消费者consumer
    kafka服务节点broker
    kafka消息类型 topic
    每个topic可以有多个分区 partition
    每个topic的分区都有备份 replication
    消费者组 consumer group
    每个分区和其多个备份间 leader follower

    2、ZooKeeper在Kafka中的作用

    • broker注册
      /brokers/ids/[0-N]
      临时节点 - 宕机自动删除

    • topic注册
      /borkers/topics/[topic_key]
      /brokers/topics/login_topic/3->2 标识id为3的broker为该topic总共提供了2个分区

    • 生产者负载均衡
      1、四层负载均衡
      根据生产者的ip和端口,为其确定唯一的一个broker连接
      好处:只用与一个broker建立tcp连接,减小开销
      坏处:如果生产者生产能力差异很大,会导致broker的负载差异很大,负载均衡效果减弱
      2、使用ZooKeeper负载均衡
      生产者通过ZooKeeper获取broker的列表,并监听节点变化。进行负载均衡

    • 分区与消费者的关系
      consumer group 会分配唯一id,topic下的某个分区只能分配给group_id下一个consumer。(所以group下consumer不要超过分区数,会出现有的consumer无法消费到消息)
      /consumers/[group_id]/owners/[topic]/[broker_id-partition_id]
      [broker_id-partition_id]就是一个消息分区的标识,该节点内容就是消费者的consumer_id

    • 记录消费进度offset
      /consumers/[group_id]/offsets/[topic]/[broker_id-partition_id]
      节点内容记录的就是该分区的offset

    • 消费者注册
      /consumers/[group_id]/ids/[consumer_id] 消费者启动后注册consumer_id,节点内容是订阅的topics
      每个消费者都需要监听/consumers/[group_id]/ids节点的子节点变化,用来触发消费者的负载均衡

      image.png

    3、Kafka消息如何保证消费的顺序性

    • topic下只创建一个分区,同一分区内的消费是有顺序性的
    • 生产者负载均衡的设计。比如如果使用对key的hash值进行负载均衡发送消息,那我们可以根据业务,需要保证顺序性的业务使用相同的key,如用户id 也可以代码指定需要发送的partition

    4、如何保证消息的不丢失

    生产者有个参数acks设置
    0 标识只管发送,不用等待response,性能高,吞吐强
    1 标识leader写入完成就返回,不需要等待ISR 吞吐量高 默认值
    -1或者all 标识需要等待leader写入完成和ISR副本备份完成,才返回。 吞吐量低

    消费者 设置是否自动提交
    enable.auto.commit
    consumer是批量拉取消息的,自动提交开启,会在拉取到消息后就立马提交offset,不管消息是否已经都消费了
    关闭后,你可以在每次消费完当前消息就提交当前消息的offset,可以确保不丢失消费消息

    5、Kafka如何加快消息消费速度

    • 增加consumer消费者个数,存在一个问题不能超过分区数
    • consumer内使用多线程消费,如拉取到一堆消息,将消息丢到线程池进行消费,消费完后提交offset。然后再拉取消息

    6、Kafka如何加快生产

    producer 需要设置批量发送,减少网络开销。
    batch.size 消息达到多少时(字节数,不是条数),触发一次发送
    linger.ms 缓存时间超过多少时,触发一次发送

    如果消息设置了key,默认情况producer会根据key的hash值选取分区发送,而如果没有设置key,默认是轮训分区发送到每个分区
    无key的情况下,很容易造成消息分散,batch发送无法达成。针对这个情况出现了粘性分区策略,也即某个短时间内的消息都发到一个分区上,过了这个时间段,然后换个分区。轮训的时间段版本

    7、Kafka消费者语义at least once,如何处理重复消费问题

    发送消息时,传入key作为唯一流水ID
    消费消息时,判断是否已经已经消费过该ID消息
    业务上做幂等

    8、Kafka ISR机制

    in sync replicate
    这些机制都是针对acks=0或者1的情况

    follower与leader不同步的原因:

    • 1.速度跟不上 leader写入速度过快,而follower因为网络IO等问题,拉取写入速度慢与leader速度
    • 2.进程卡主 follower一段时间内卡主未向leader拉取新消息FetchRequest,如太过频繁的GC等
    • 3.新增备份因子 factor扩大 刚启动的follower肯定慢与leader

    replica.lag.max.messages 落后消息数大余这个值时,剔除出ISR列表,适合上诉场景的1
    该参数已经被删除了,原因是这个值的设置需要根据具体业务数据量进行设置,而这个设置值是全局的,针对所有topic的。如果设置值过大,相当于无效设置,如果设置值过小,会导致不断触发剔除与加入,性能降低。
    replica.lag.time.max.ms 超过这个时间没向leader请求数据FetchRequest,剔除出ISR列表。适合剔除上诉场景的2,3

    9、Kafka文件存储机制 吞吐量为啥大

    题外:

    • 磁盘随机读写慢 寻址耗时
    • linux pagecache 在内存上缓存了部分磁盘上的数据,免除用户访问每次都对磁盘进行直接操作
      预读
      回写
    • 普通IO
      读取网络数据写入磁盘过程 :
      DMA IO读取到内核socket缓冲区 -》 内核socket缓冲区读取到用户内存 -》用户内存写入内核磁盘缓冲区 -》 DMA内核缓冲区刷新存储到磁盘
      读取磁盘数据发送网络过程 :
      DMA磁盘读取到内核磁盘缓冲区 -》 内核磁盘缓冲区读取到用户内存 -》用户内存写入到内核socket缓冲区 -》DMA内核socket缓冲区写入到网络IO

    Kafka文件存储
    一个topic可以分多个partition存储到不同的broker,一个partition由多个segment组成,每个segment有.index和.log文件组成。segment的文件名由起始的offset定义,第一个segment文件从0开始。 .index 文件存储元数据,如(3,349)标识这个segment中的第3条消息在.log文件的物理偏移位置是349,


    image.png

    示例:查找offset为368776的消息
    1、通过文件名列表排序后进行二分查找,定位到该消息在00000000000000368769.index|log这个segment中,
    2、通过368769.index文件查找第7条元数据,定位到消息在.log中的偏移量,然后对368769.log文件进行顺序查找,找到该偏移量处的消息
    .index这个文件 叫稀疏索引存储 降低索引文件存储空间占用

    吞吐量高的原因:

    • 顺序读写 Kafka的message信息,是不断追加到本地磁盘末尾,而不是随机写入。对应到上面即为.log文件末尾写入,引起的问题是,不允许中间删除消息或修改消息。kafka提供了基于时间和空间的自动删除策略,删除是已segment为单位的整文件删除。
    • 使用PageCache 利用的是内核内存而不是jvm内存,避免了虚拟机内存开销及垃圾回收机制和构建Object的开销。服务重启PageCache也还在,缓存重建快速。
    • 零拷贝机制 系统的sendfile方法,可以直接将内核缓冲区数据PageCache 发送到 内核socket缓冲区,避免了向用户内存的2次拷贝。 mmap 直接操作内核缓冲区数据。
      java FileChannel 的支持
    // 将当前 FileChannel 的字节传输到给定的可写 channel 中
    public abstract long transferTo(long position, long count,  WritableByteChannel target) throws IOException;
    // 将一个可读 channel 的字节传输到当前 FileChannel中
    public abstract long transferFrom(ReadableByteChannel src, long position, long count) throws IOException;
    // 对 Channel 做 mmap 映射
    public abstract MappedByteBuffer map(MapMode mode, long position, long size) throws IOException;
    
    • 分partition分segment
    • 批量写和批量读

    10、kafka消费分区策略

    • 默认 Range 每个topic都按其消费者数连续分配等量的分区数,多余的优先分配到前面的消费者
      如 T1 消息有7个分区T1-0,T1-1..T1-6,T2 消息有4个分区 有3个消费者C0,C1,C1
      则:
      C0 :T1-0,T1-1,T1-2,T2-0,T2-1
      C1: T1-3,T1-4,T2-2
      C2: T1-5,T1-6,T2-3
      缺陷:排号靠前的消费者,会分配到更多的分区,压力更大
    • RoundRobin
      1、如果组内消费者订阅的topic都相同,最终分配是均匀的
      如T0,T1都有3个分区,C0,C1都订阅了T0,T1
      则:
      C0:T0-0,T0-2,T1-1
      C1:T0-1,T1-0,T1-2
      2、组内消费者订阅topic不同时
      如T0,T1,T2都有3个分区, 消费者C0订阅的是主题T0,消费者C1订阅的是主题T0和T1,消费者C2订阅的是主题T0、T1和T2 会出现分配不均
      C0:T0-0
      C1:T1-0
      C2:T1-1,T2-0,T2-1,T2-3
    • StickyAssignor

    11、消息队列

    优点:解耦、异步、削峰
    缺点:系统复杂性增加 (如一致性,重复消费,消息丢失等)、系统可用性降低

    相关文章

      网友评论

          本文标题:Kafka 题

          本文链接:https://www.haomeiwen.com/subject/ttbbyltx.html