002-kafka设计分析

文章详细阐述了Kafka在生产者和消费端的关键配置参数,包括消息持久化策略、重试机制、缓冲区管理以及消费者拉取策略。此外,还介绍了Kafka的日志存储方式、分区选举、Controller角色、offset记录以及rebalance过程和不同分配策略。文中强调了消息的HW与LEO对于确保幂等性的重要性。
摘要由CSDN通过智能技术生成

客户端参数

生产者

acks=0或1或-1或all
0 : 不关心消息是否持久化
1 :消息必须持久化并返回
-1或者all :所有副本成功,如果配置了min.insync.replicas就是执行副本同步成功才返回成功

RETRIES_CONFIG: 重试此处
RETRY_BACKOFF_MS_CONFIG: 重试间隔
BUFFER_MEMORY_CONFIG: 消息缓冲区大小,消息先放在buffer中然后每16k拉取
LINGER_MS_CONFIG: 如果消息不足16k 但是到了设置时间 就按设置时间发送

消费端

消费者发起拉取,在时间窗口中反复拉取 如果拉到则直接返回,如果没有拉取到则重新拉取并计算是否大于时间窗口,如果大于时间窗口则直接返回为空
KEY_DESERIALIZER_CLASS_CONFIG|VALUE_DESERIALIZER_CLASS_CONFIG:序列化和反序列化

订阅主题
consumer.subscribe(Arrays.asList(TOPIC_NAME));

是否自动提交,客户端返回MQ offset
自动提交的时间 一般不会自动提交 需要手动批量提交
ENABLE_AUTO_COMMIT_CONFIG
AUTO_COMMIT_INTERVAL_MS_CONFIG
consumer.commitSync()

心跳最大间隔时间 超过时间则集群认为消费者有问题踢出集群
HEARTBEAT_INTERVAL_MS_CONFIG : 每次心跳间隔时间 默认3s
SESSION_TIMEOUT_MS_CONFIG :心跳异常最大容忍时间

每次拉取消息最大数
MAX_POLL_RECORDS_CONFIG
两次poll间隔最大容忍时间,超过时间则kafka就认为消费者性能太弱提出集群
这个配置一般不要随意调整 可以调整每次拉取任务数来控制
MAX_POLL_INTERVAL_MS_CONFIG

每次新增分组的时候默认是读取新的消息 此时offset为0
如果想消费之前的消息则修改设置为earliest
消费完之后已经有offset了下次启动就从次offset开始
默认为latest
ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, “earliest”

指定消费

  1. 指定分区消费
consumer.assign(Arrays.asList(new TopicPartition(TOPIC_NAME, 0)));
  1. 消息全部回溯
consumer.assign(Arrays.asList(new TopicPartition(TOPIC_NAME, 0)));
consumer.seekToBeginning(Arrays.asList(new TopicPartition(TOPIC_NAME, 0)));
  1. 指定offset消费
consumer.assign(Arrays.asList(new TopicPartition(TOPIC_NAME, 0)));
consumer.seek(new TopicPartition(TOPIC_NAME, 0), 10);
  1. 指定时间消费 先调用Api提供的根据时间查询offset后自己根据offset查询
List<PartitionInfo> topicPartitions = consumer.partitionsFor(TOPIC_NAME);

Kafka日志

分段存储
根据log.segment.bytes设置文件大小

索引文件
存储每4k消息中最小的offset
查询的时候使用二分法先查索引文件

时间索引
索引和发送消息的时间戳

集群设计

总控制器Controller

所有的broker会选取一个Controller
职责:

  1. 分区leader异常重新选举
  2. 分区ISR集合变化,通知所有broker更新元信息
  3. 增加分区时,通知其他节点感知

选举机制

谁先启动谁就是Controller
同时启动则同时执行zk create controller(临时节点)
创建成功的则为Controller
如果Controller挂了重新 create controller(监听)

Partition选举

controller监听 /broker/ids节点内容
如果发生变化

  1. leader挂了 则直接读取ids中的 Isr(已同步列表)中第一个节点为新的leader
  2. 如果ISR列表为空了 则读取 unclean.leader.eletion.enable=true则可以用ISR意外的服务参加选举,这样提高了可用性 但是会丢消息

offset记录机制

每个consumer提交消费分区给kafka内部topic:_consumer_offset
内容中key为consumerGroupId + topic + 分区号
内容value就是当前的offset值

内部topic分区 默认50个
存储规则为 hash(consumerGroupId) % _consumer_offset 分区数

Rebalance

每个消息只有group中的一个消费者消费
其实是通过每个partition都只绑定group中一个服务实现的 所以也是固定的
但是如果消费者挂了partition和消费者之间需要重新建立连接
这个过程就是rebalance

会发生rebalance的情况:

  1. 消费者增加或减少
  2. topic增加了分区
  3. 消息组订阅了新的topic

rebalance影响性能注意

过程
  1. 消费者调用kafka选出kafka 组长(GroupCoordinator)
    组长负责监控消费组内所有消费者的心跳,判断是否挂机、是否举行rebalance
  2. 第一个调用kafka 组长的消费者就是 消费者组长(leaderCoordinator)
    这个 消费组长负责指定分区方案
  3. 分区方案 同步给 kafka组长 在其他消费者ping的时候同步给各个消费者
策略

partition.assignment.strategy控制

range策略
假设一个主题有10个分区(0-9),现在有三个consumer消费:
range策略就是按照分区序号排序,假设 n=分区数/消费者数量 = 3, m=分区数%消费者数量 = 1,那么前 m 个消费者每个分配 n+1 个分区,后面的(消费者数量-m )个消费者每个分配 n 个分区。
round-robin策略
轮询分配,
比如分区0、3、6、9给一个consumer,分区1、4、7给一个consumer,分区2、5、8给一个consumer
sticky策略
初始时分配策略与round-robin类似,
但是在rebalance的时候,需要保证如下两个原则。
1)分区的分配要尽可能均匀 。
2)分区的分配尽可能与上次分配的保持相同。(其余两个为整体rebalance)

HW与LEO详解

HW
取一个partition对应的ISR中最小的LEO(log-end-offset),consumer最多只能消费到HW所在的位置。

leader写入新的消息不会立即给consumer消费
需要ISR中的从节点同步数据并更新自身HW,所有的更新完了
消息才会被消费者消费

这个就是保证了消息幂等性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值