目录
1、Kafka的作用
- 应用解耦:屏蔽实现细节、异步通信,升级、扩容互不影响
- 流量消峰:生产速率>消息速率、消息积压能力、秒杀系统、批量导入
- 消息广播
- 最终一致性
2、Kafka高吞吐量、高可用的原因
kafka多实例、多分区、多副本:
1、说明:
kafka实例:有四个Broker(四个kafka实例),多实例保证一个broker挂了,整个集群还能继续使用,高可用;
该topic有三个分区:part0,part1,part2,多分区,可以并行、并发比如写入消息到某一个topic,高吞吐量;
每个分区有两个副本,比如part0,在Broker2和Broker3中有两个副本(follower),在Broker1中的part0是leader,负责与生产者、消费者进行消息的生产和消费;leader分区还有一个任务就是将自己收到的消费同步到他的两个副本中;多副本保障的也是高可用,不至于因为一个副本的丢失导致整个消息的丢失;
2、意义:
一个topic,为什么要有多个part:为了方便多个生产者忘多个part并发写入消息,提供吞吐量;
一个part,为什么要有多个副本:为了防止某个broker宕机,导致消息的丢失,提高可用性;
3、名词解释
ISR(In-Sync Replicas):副本 同步队列,
OSR(Outof-Sync Replicas):副本 非同步队列
AR(Assigned Replicas)= ISR+OSR
我们知道副本数对Kafka的吞吐率是有一定的影响,但极大的增强了可用性。所有的副本(replicas)统称为Assigned Replicas,即AR。ISR是AR中的一个子集,由leader维护ISR列表,follower从leader同步数据有一些延迟,任意一个超过阈值都会把follower剔除出ISR, 存入OSR(Outof-Sync Replicas)列表,新加入的follower也会先存放在OSR中,即AR=ISR+OSR。
HW(HighWatermark):consumer能够看到的此partition的位置,即消费者能消费到的消息,消费者可见的消息,这个涉及到多副本的概念,取一个partition对应的ISR中最小的LEO作为HW,consumer最多只能消费到HW所在的位置。
LEO(LogEndOffset):表示每个partition的log最后一条Message的位置。
下图详细的说明了当producer生产消息至broker后,ISR以及HW和LEO的流转过程:
由此可见,Kafka的复制机制既不是完全的同步复制,也不是单纯的异步复制。事实上,同步复制要求所有能工作的follower都复制完,这条消息才会被commit,这种复制方式极大的影响了吞吐率。而异步复制方式下,follower异步的从leader复制数据,数据只要被leader写入log就被认为已经commit,这种情况下如果follower都还没有复制完,落后于leader时,突然leader宕机,则会丢失数据。而Kafka的这种使用ISR的方式则很好的均衡了确保数据不丢失以及吞吐率。一条消息只有被ISR中的所有follower都从leader复制过去才会被认为已提交。这样就避免了部分数据被写进了leader,还没来得及被任何follower复制就宕机了,而造成数据丢失。而对于producer而言,它可以选择是否等待消息commit,这可以通过request.required.acks来设置。这种机制确保了只要ISR中有一个或者以上的follower,一条被commit的消息就不会丢失。
Consumer Group:同样是逻辑上的概念,是Kafka实现单播和广播两种消息模型的手段。同一个topic的数据,会广播给不同的group;同一个group中的worker,只有一个worker能拿到这个数据。换句话说,对于同一个topic,每个group都可以拿到同样的所有数据,但是数据进入group后只能被其中的一个worker消费。group内的worker可以使用多线程或多进程来实现,也可以将进程分散在多台机器上,worker的数量通常不超过partition的数量,且二者最好保持整数倍关系,因为Kafka在设计时假定了一个partition只能被一个worker消费(同一group内)。
Consumer Group延伸论述:
什么是消费者组
什么是consumer group? 一言以蔽之,consumer group是kafka提供的可扩展且具有容错性的消费者机制。既然是一个组,那么组内必然可以有多个消费者或消费者实例(consumer instance),它们共享一个公共的ID,即group ID。组内的所有消费者协调在一起来消费订阅主题(subscribed topics)的所有分区(partition)。当然,每个分区只能由同一个消费组内的一个consumer来消费。理解consumer group记住下面这三个特性就好了:
- consumer group下可以有一个或多个consumer instance,consumer instance可以是一个进程,也可以是一个线程
- group.id是一个字符串,唯一标识一个consumer group
- consumer group下订阅的topic下的每个分区只能分配给某个group下的一个consumer(当然该分区还可以被分配给其他group)
kafka中partition和消费者对应关系:即同一个partition内的消息只能被同一个组中的一个consumer消费。当消费者数量多于partition的数量时,多余的消费者空闲。也就是说如果只有一个partition你在同一组启动多少个consumer都没用,partition的数量决定了此topic在同一组中被可被均衡的程度,例如partition=4,则可在同一组中被最多4个consumer均衡消费。
消费者位置(consumer position)
消费者在消费的过程中需要记录自己消费了多少数据,即消费位置信息。在Kafka中这个位置信息有个专门的术语:位移(offset)。很多消息引擎都把这部分信息保存在服务器端(broker端)。这样做的好处当然是实现简单,但会有三个主要的问题:1. broker从此变成有状态的,会影响伸缩性;2. 需要引入应答机制(acknowledgement)来确认消费成功。3. 由于要保存很多consumer的offset信息,必然引入复杂的数据结构,造成资源浪费。而Kafka选择了不同的方式:每个consumer group保存自己的位移信息,那么只需要简单的一个整数表示位置就够了;同时可以引入checkpoint机制定期持久化,简化了应答机制的实现。
4、Kafka存储结构
TODO
5、面试点:
- Kafka的用途有哪些?使用场景如何?
- Kafka中的ISR、AR又代表什么?ISR的伸缩又指什么
- Kafka中的HW、LEO、LSO、LW等分别代表什么?
- Kafka中是怎么体现消息顺序性的?:1、单个partition 中的数据一定是有顺序的,消费者从 partition 中取出来数据的时候,也一定是有顺序的;2、但如果消费者搞多个线程来并发处理消息,那很有可能导致未按照理想的消费顺序:写 N 个内存 queue,具有相同 key 的数据都到同一个内存 queue;然后对于 N 个线程,每个线程分别消费一个内存 queue 即可,这样就能保证顺序性
- Kafka中的分区器、序列化器、拦截器是否了解?它们之间的处理顺序是什么?
- Kafka生产者客户端的整体结构是什么样子的?
- Kafka生产者客户端中使用了几个线程来处理?分别是什么?
- “消费组中的消费者个数如果超过topic的分区,那么就会有消费者消费不到数据”这句话是否正确?如果正确,那么有没有什么hack的手段?:正确
- 消费者提交消费位移时提交的是当前消费到的最新消息的offset还是offset+1?:offset+1
- 有哪些情形会造成重复消费?:若enable-auto-commit被改成了true,即自动提交,对于自动提交偏移量,如果auto_commit_interval_ms的值设置的过大,当消费者在自动提交偏移量之前异常退出,将导致kafka未提交偏移量,进而出现重复消费的问题,所以建议auto_commit_interval_ms的值越小越好。鉴于Kafka自动提交offset的不灵活性和不精确性(只能是按指定频率的提交),Kafka提供了手动提交offset策略。手动提交能对偏移量更加灵活精准地控制,以保证消息不被重复消费以及消息不被丢失。不管怎么样,消费端做好幂等处理。
- 那些情景下会造成消息漏消费?:https://blog.csdn.net/qingqing7/article/details/80054281 。使用同步模式的时候,有3种状态保证消息被安全生产,在配置为1(只保证写入leader成功)的话,如果刚好leader partition挂了,数据就会丢失。还有一种情况可能会丢失消息,就是使用异步模式的时候,当缓冲区满了,如果配置为0(还没有收到确认的情况下,缓冲池一满,就清空缓冲池里的消息),数据就会被立即丢弃掉。生产端如何保证不丢:就是说在同步模式的时候,确认机制设置为-1,也就是让消息写入leader和所有的副本。还有,在异步模式下,如果消息发出去了,但还没有收到确认的时候,缓冲池满了,在配置文件中设置成不限制阻塞超时的时间,也就说让生产端一直阻塞,这样也能保证数据不会丢失。
- KafkaConsumer是非线程安全的,那么怎么样实现多线程消费?:因为Kafka consumer是非线程安全的,当多个线程同时共用一个consumer时会导致异常
ConcurrentModificationException,多线程多个consumer or 单线程接受消息后,多线程处理。
- KafkaProducer是线程安全的,在一个Kafka集群中多线程之间共享一个KafkaProducer实例通常比创建多个KafkaProducer实例性能更好;KafkaProducer有一个缓存池,用于存储尚未向代理发送的消息,同时一个后台IO线程负责从缓冲池中读取消息构造请求,将消息发送至代理。
- 简述消费者与消费组之间的关系
- 当你使用kafka-topics.sh创建(删除)了一个topic之后,Kafka背后会执行什么逻辑?
- topic的分区数可不可以增加?如果可以怎么增加?如果不可以,那又是为什么?topic的分区数可不可以减少?如果可以怎么减少?如果不可以,那又是为什么?:可以增加,不可以减少,为什么呢,减少太难实现了,需要考虑的因素太多了,可以减少副本数
- 创建topic时如何选择合适的分区数?
- Kafka目前有那些内部topic,它们都有什么特征?各自的作用又是什么?
- 优先副本是什么?它有什么特殊的作用?
- Kafka有哪几处地方有分区分配的概念?简述大致的过程及原理
- 简述Kafka的日志目录结构
- Kafka中有那些索引文件?
- 如果我指定了一个offset,Kafka怎么查找到对应的消息?
- 如果我指定了一个timestamp,Kafka怎么查找到对应的消息?
- 聊一聊你对Kafka的Log Retention的理解
- 聊一聊你对Kafka的Log Compaction的理解
- 聊一聊你对Kafka底层存储的理解(页缓存、内核层、块层、设备层)
- 聊一聊Kafka的延时操作的原理
- 聊一聊Kafka控制器的作用
- 消费再均衡的原理是什么?(提示:消费者协调器和消费组协调器)
- Kafka中的幂等是怎么实现的
- Kafka中的事务是怎么实现的(这题我去面试6加被问4次,照着答案念也要念十几分钟,面试官简直凑不要脸)
- Kafka中有那些地方需要选举?这些地方的选举策略又有哪些?
- 失效副本是指什么?有那些应对措施?
- 多副本下,各个副本中的HW和LEO的演变过程
- 为什么Kafka不支持读写分离?
- Kafka在可靠性方面做了哪些改进?(HW, LeaderEpoch)
- Kafka中怎么实现死信队列和重试队列?
- Kafka中的延迟队列怎么实现(这题被问的比事务那题还要多!!!听说你会Kafka,那你说说延迟队列怎么实现?)
- Kafka中怎么做消息审计?
- Kafka中怎么做消息轨迹?
- Kafka中有那些配置参数比较有意思?聊一聊你的看法
- Kafka中有那些命名比较有意思?聊一聊你的看法
- Kafka有哪些指标需要着重关注?
- 怎么计算Lag?(注意read_uncommitted和read_committed状态下的不同)
- Kafka的那些设计让它有如此高的性能?
- Kafka有什么优缺点?
- 还用过什么同质类的其它产品,与Kafka相比有什么优缺点?
- 为什么选择Kafka?
- 在使用Kafka的过程中遇到过什么困难?怎么解决的?
- 怎么样才能确保Kafka极大程度上的可靠性?
- 聊一聊你对Kafka生态的理解
6、参考:
kafka日志文件结构:链接:Kafka文件存储机制那些事
深度分析kafka可靠性良心好文:kafka数据可靠性深度解读
深入分析消费组良心好文:消费组详解
消费组&&topic多分区的分配详解,真心好文好文,深入且易懂:kafka中partition和消费者对应关系