Kafka-杂记

零碎

  1. 每个 topic 是分区的,消息按照 topic 分类
  2. 一个 partition 同时只能被同一个 consumer group 中的某一个 consumer 消费
  3. topic 是逻辑上概念,partition 是物理概念
  4. 一般修改kafkaconfig配置文件server.properties
    • broker.id:唯一整数
    • delete.topic.enable=true:能否删除主题
    • log.dirs:运行日志存储地址
    • zookeeper.connectzk集群地址
  5. 创建 topic 后,会在配置的 log.dirs 下生成文件名为 [topicName]-[partitionName] 的几个文件夹,用来存放数据
    • 00000000000000000000.log:配置项为 log.segment.bytes,只存储数据,默认存7天,默认大小1G,超过了就会重新创建,其命名以当前 segment 的第一条消息的 offset 命名
    • 00000000000000000000.index:存储相应 log 的索引与偏移量、大小等,之后去 log 中迅速查找消息
    • 00000000000000000000.timeindex
    • leader-epoch-checkpoint
  6. 每个 partition 中维护一个从头开始的 offset,仅区内有序,不一定全局有序

生产者

1. 分区策略

  1. 指明 partition ,直接使用其值
  2. 未指明 partition 但有 key 值,将 keyhash 值与 topicpartition 数取余,作为 partition
  3. 未指明 partition 也没有 key 值,第一次调用时生成一个随机整数的绝对值(之后再其上自增),将其值与 topic 的可用 partition 数取余,作为 partition 数,这种方式称为 round-robin 算法(轮询算法)

2. 数据可靠保证(ISR)

topic的每个partitionleader收到生产者发送的数据后,会向生产者发送ack ,生产者收到后会进行下一轮发送,否则会重新发送

2.1. 副本数据同步策略(发送 ack 时机)

策略 优点 缺点
半数以上完成 延迟低 选举新leader时,容忍n台节点故障,需要2n+1个副本
全部完成 选举新leader时,容忍n台节点故障,需要n+1个副本 延迟高

2.2. kafka的同步策略(全部完成的升级版)

ISR(in-sysc replica set),由leader维护,意为与leader保持同步的的follower集合,集合中的follower完成数据同步后,则会发送ack。当其长时间未向leader同步数据,则将该follower踢出ISR。时间阈值配置项为replica.lag.time.max.ms

2.3. ack应答机制

对于不太重要的数据,允许少量丢失,所以没必要等待ISR全部接收成功,此时提供了三种可靠性级别,即ack 参数

  • 0:生产者不等待brokerack,延迟最低。broker一接收到还没有落盘就返回,broker故障时可能丢失数据
  • 1:生产者等待brokerackpartitionleader落盘成功后返回ack。如果在follower同步成功前leader故障,可能丢失数据
  • -1(all):生产者等待brokerack,并且在follower同步成功前后返回ack。如果在follower同步成功后,broker发送ack前,leader故障,则会造成重复数据

2.4. 副本数据一致性

  • LEO(Log End Offset):每个副本中最后一个(即最大的)offset
  • HW(High Watermark):指消费者所能见到的最大的offsetISR中最小的LEOHW之前的数据才对消费者可见
2.4.1. follower故障

follower故障后,会被临时踢出ISR,恢复后会读取本地磁盘的HW,并将高于部分截掉,从HW重新开始同步,等到其LEO大于等于该partitionHW时,重新加入ISR

2.4.2. leader故障

leader故障后,会选举出新的leader,其余follower会将各自高于HW的部分截掉,从新的leader开始同步

3. Exactly-Once

3.1. 几个概念

  • At Least Once:至少一次,即ack=-1时,此时不会丢数据,但可能重复数据
  • At Most Once:只多一次,即ack=0时,此时保证每条消息只会被发送一次,不会重复数据,但可能会丢数据
  • 幂等性:无论发送多少次重复数据,都只会保留一条。配置项为 enable.idompotence=true
  • Exactly-Once:等于At Least Once+幂等性

3.2. 语义实现

开启幂等性的生产者初始化时会生成一个PID,发往同一个partition的消息会附带sequence number,而broker端会对<PID,partition,sequence number>做缓存,相同主键的消息只会持久化一条。但是由于PID重启生产者会变化,不同的partition也有不同主键,所以无法做到跨分区跨回话的Exactly-Once

消费者

1. 消费方式

pull模式,优点是适应了消费能力,缺点是如果没有数据会陷入循环中。可使用timeout,消费者会等待一段时间才返回

2. 分区分配策略

2.1. RoundRobin

消费者组的所有消费者,必须订阅相同的主题时,其将所有订阅的主题看成一个整体,按照hash值排序,按照顺序依次分配

2.2. Range

按照相同的topic分别分组,之后在按顺序分配

3. offset

消费者组+topic+partition,唯一确定一个offset

3.1. 保存位置

  • 0.9之前:默认将 offset 保存在 Zookeeper
  • 0.9开始:默认将 offset 保存在 Kafka 一个内置topic,叫__consumer_offsets

3.2. 如何查看

高效读写

  • 顺序写磁盘
  • 零拷贝

事务

为了实现跨分区会话事务,引入了TransactionID,其与PID绑定,当生产者重启后,可以通过它找回原先的PID

__consumer_offsets

由于 zookeeper 不擅长大批量的频繁写操作,kafka_1.0.2consumer 的位移信息保存在内部的 topic 中,即 __consumer_offsets ,并提供了 kafka_consumer_groups.sh 脚本供用户查看 consumer 信息