![11215cdc7733c398ff2d82b7a048a281.png](https://i-blog.csdnimg.cn/blog_migrate/974800e9cd7ea2f9882c173554642cf6.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](https://i-blog.csdnimg.cn/blog_migrate/a051de427f3322ebfcc499de43343dc1.png)
![94513d10203a75f73ada03aa5934bb4a.png](https://i-blog.csdnimg.cn/blog_migrate/31d3ea6fb19b31b0203f6b287f07db7c.jpeg)
![98a8c0a2f4f6dbbd8018c7ed5167e536.png](https://i-blog.csdnimg.cn/blog_migrate/624f07b588f44453eb30e4b754774996.jpeg)
![b463c842522205b22582d3df9deddabc.png](https://i-blog.csdnimg.cn/blog_migrate/fde8c2bc92ae4f072bb1252c8fe30448.png)
=================================================================
========================整体架构和细节分割线=========================
=================================================================
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](https://i-blog.csdnimg.cn/blog_migrate/98588aaa9e6cbf5ce258f71dda995c17.png)
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](https://i-blog.csdnimg.cn/blog_migrate/7d4f497b0907d9f204dfa68da04058ee.jpeg)
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)
- produce->kafka:
- 强稳定性场景
- 多副本
- acks=all
- min.insync.relicas: ISR集合中最少副本数
- 强顺序性场景
- topic中只有一个partition
- max.in.flight.requests.per.connection: 设置为1
- 延时队列
- 时间轮