深入理解kafka_深入理解Kafka

11215cdc7733c398ff2d82b7a048a281.png

本文章为书籍《深入理解Kafka》的读书笔记,不负任何版权责任。

Kafka特征:

系统解耦,流量削峰,冗余存储,持久化到磁盘,提供消息顺序性保障及回溯。

目录:

  • 架构
  • 生产者
  • 消费者
  • 日志存储
  • 问题讨论

名词:

  • Producer:生产者,发送消息
  • Consumer:消费者,接收消息,进行业务逻辑处理
  • Zookeeper:树状2f+1集群保存metadata
  • Broker:服务代理节点,将消息持久化到磁盘
    • Topic:主题,每条消息都需要指定主题,可细分为多个分区
    • Partition:分区,一个可追加的日志文件,消息追加时分配offset
      • AR:Assigned Replicas,分区中所有副本
      • ISR:In-Sync Replicas,与leader保持一定程度同步,包括leader
      • OSR:Out-of-Sync Replicas,与leader同步滞后过多
      • AR=ISR+OSR
      • HW:High Watermark,标示特定offset,消费者只能拉取其之前消息
      • LEO:Log End Offset,标示当前log下一条写入消息位置
      • HW=min(LEO of ISR)
    • 保证消息分区有序,不保证主题有序
    • broker持久化消息;consumer宕机后通过之前保存的offset可继续,不丢失消息

1.架构

60e5db779598b331c1fea56aa1e279bf.png
kafka整体架构

94513d10203a75f73ada03aa5934bb4a.png
broker-partition多副本架构:一主多从,leader负责读写,follower只负责同步

98a8c0a2f4f6dbbd8018c7ed5167e536.png
broker-partition多副本架构:一主多从,leader负责读写,follower只负责同步

b463c842522205b22582d3df9deddabc.png
broker-partition架构:消息按顺序写入broker的分区中

=================================================================

========================整体架构和细节分割线=========================

=================================================================

2.生产者

  • 流程
    • KafkaProducer -> interceptors -> serializer -> partitioner -> recordAccumulator (by partition) -> InFlightRequests (by broker node)
  • 参数acks
    • acks=1:默认值,只要分区leader成功写入,就会收到成功响应;如果未被其他follower拉取前leader崩溃,会丢失消息。
    • acks=0:生产者发送消息后不需要等待任何响应;最小可靠,最大吞吐。
    • acks=-1:需要等待ISR中所有副本都写入成功才会收到响应;最大可靠,最小吞吐。
  • 参数retries和retry.backoff.ms
    • retries配置生产者重试的次数,默认为0
    • retry.backoff.ms配置两次重试之间的时间间隔
  • 参数max.in.flight.requests.per.connection
    • 默认为5,限制每个链接最多缓存数
    • 如果需要严格顺序,需要此参数设置为1;且topic中分区数为1
    • 如果第一批次写入失败,第二批次写入成功;生产者重发第一批次,会导致顺序错序
  • 多线程同时写入一个partition - 单线程

2861281cc87b2c7b14ca16d4b65b3a31.png
ConsumerGroup

3.消费者

  • 消费者和消费组
    • 每一个分区只能被同一个ConsumerGroup中的一个消费者所消费
    • 一个消费者可以消费一个或多个分区
    • num(consumer) > num(partition),会有消费者闲置
  • 消息拉取和offset提交
    • 不断轮询,重复地调用poll()方法,返回所订阅主题-分区上的一组消息
    • max.poll.records默认为500条
    • 当poll拉取[x+2,x+7]消息
      • 表示已经完成[0,x+1]所有消息的消费
      • 如果消费x+5的时候遇到异常
        • commitSync在消费前:导致消息丢失[x+5,x+7]
        • commitSync在消费后:导致重复消费[x+2,x+4]
    • enable.auto.commit
      • 默认为true
      • 自动提交不是每消费一条就提交一次,而是定期提交poll的最大消息位移,默认每5s
      • 会有重复消费和消息丢失的问题,设置为false可以增加掌控性
    • seek()
      • 可以指定partition中的offset进行消费
  • 多线程消费同一个partition
    • 通过assign(), seek()方法来实现
    • 对于位移提交和顺序控制处理变得很复杂,作者不推荐
    • 一般而言,分区是消费线程的最小划分单位

3628c3c46e2f9eb0a44ec2377586bebd.png
kafka日志结构

4.日志存储

  • LogSegment
    • Log在物理上以文件夹形式存储
    • LogSegment对应磁盘一个日志文件和两个索引文件
    • 追加消息都是顺序写入的,只有最后一个LogSegment才能执行写入操作
    • 根据时间戳查询流程
      • 根据给定的时间戳找到不大于该时间戳的最大偏移量(*.timeindex)
      • 根据给定的偏移量找到不大于该偏移量的物理文件位置(*.index)
      • 从指定的物理文件位置处扫描日志分段文件找到合适的消息(*.log)
  • 高性能
    • 消息顺序追加
    • 页缓存
    • 零拷贝 - 直接将数据从磁盘文件复制到网卡,不经过user space

5.问题讨论

  • 消息传输等级
    • at most once:可能丢失,不会重复
    • at least once:不会丢失,可能重复
    • exactly once:不会丢失,不会重复
  • Kafka消息传输
    • produce->kafka:
      • 超时会重试,所以是at least once
      • 使用新版本0.11.0.0的幂等可实现exactly once(enable.idempotence=true),通过版本号实现
    • kafka->produce:
      • 拉取到后就commit,at least once(中间失败,再读重复消费)
      • 处理完再commit,at most once(中间失败,再读消息丢失)
      • 使用新版本的事务可实现exactly once(transaction.id)
  • 强稳定性场景
    • 多副本
    • acks=all
    • min.insync.relicas: ISR集合中最少副本数
  • 强顺序性场景
    • topic中只有一个partition
    • max.in.flight.requests.per.connection: 设置为1
  • 延时队列
    • 时间轮
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值