简述Kafka架构设计
- Consumer Group:消费者组,消费者组内每个消费者负责消费不同分区的数据,提高消费能力。逻 辑上的一个订阅者。
- Topic:可以理解为一个队列,Topic 将消息分类,生产者和消费者面向的是同一个 Topic。
- Partition:为了实现扩展性,提高并发能力,一个Topic 以多个Partition的方式分布到多个 Broker 上,每个 Partition 是一个 有序的队列。一个 Topic 的每个Partition都有若干个副本(Replica),一个 Leader 和若干个 Follower。生产者发送数据的对象,以及消费者消费数据的对象,都是 Leader。Follower负责实时从 Leader 中同步数据,保持和 Leader 数据的同步。Leader 发生故障时,某个 Follower 还会成为新的 Leader。
- Offset:消费者消费的位置信息,监控数据消费到什么位置,当消费者挂掉再重新恢复的时候,可以从 消费位置继续消费。
- Zookeeper:Kafka 集群能够正常工作,需要依赖于 Zookeeper,Zookeeper 帮助 Kafka 存储和管理 集群信息。
Kafka在什么情况下会出现消息丢失及解决方案
消息发送
- ack=0,不重试
producer发送消息完,不管结果了,如果发送失败也就丢失了。
- **ack=1,leader crash **
producer发送消息完,只等待lead写入成功就返回了,leader crash了,这时follower没来及同步,消 息丢失。
- unclean.leader.election.enable 配置true
允许选举ISR以外的副本作为leader,会导致数据丢失,默认为false。producer发送异步消息完,只等待 lead写入成功就返回了,leader crash了,这时ISR中没有follower,leader从OSR中选举,因为OSR 中本来落后于Leader造成消息丢失。
解决方案:
- 配置:ack=all / -1,tries > 1,unclean.leader.election.enable : false
producer发送消息完,等待follower同步完再返回,如果异常则重试。副本的数量可能影响吞吐量。
不允许选举ISR以外的副本作为leader。
- 配置:min.insync.replicas > 1
副本指定必须确认写操作成功的最小副本数量。如果不能满足这个最小值,则生产者将引发一个异常(要么是 NotEnoughReplicas,要么是NotEnoughReplicasAfterAppend)。
min.insync.replicas和ack更大的持久性保证。确保如果大多数副本没有收到写操作,则生产者将引发异 常。
- 失败的offset单独记录
producer发送消息,会自动重试,遇到不可恢复异常会抛出,这时可以捕获异常记录到数据库或缓存,进行 单独处理。
消费:
先commit再处理消息。如果在处理消息的时候异常了,但是offset 已经提交了,这条消息对于该消费者来 说就是丢失了,再也不会消费到了。
broker的刷盘:
减小刷盘间隔
Kafka是pull?push?优劣势分析
pull模式:
- 根据consumer的消费能力进行数据拉取,可以控制速率
- 可以批量拉取、也可以单条拉取
- 可以设置不同的提交方式,实现不同的传输语
缺点:如果kafka没有数据,会导致consumer空循环,消耗资源
解决:通过参数设置,consumer拉取数据为空或者没有达到一定数量时进行阻塞
push模式:不会导致consumer循环等待
缺点:速率固定、忽略了consumer的消费能力,可能导致拒绝服务或者网络拥塞等情况
Kafka中zk的作用
/brokers/ids:临时节点,保存所有broker节点信息,存储broker的物理地址、版本信息、启动时间 等,节点名称为brokerID,broker定时发送心跳到zk,如果断开则该brokerID会被删除
/brokers/topics:临时节点,节点保存broker节点下所有的topic信息,每一个topic节点下包含一个固 定的partitions节点,partitions的子节点就是topic的分区,每个分区下保存一个state节点、保存着当 前leader分区和ISR的brokerID,state节点由leader创建,若leader宕机该节点会被删除,直到有新的 leader选举产生、重新生成state节点
**/consumers/[group_id]/owners/[topic]/[broker_id-partition_id]**:维护消费者和分区的注册关系
**/consumers/[group_id]/offsets/[topic]/[broker_id-partition_id]**:分区消息的消费进度Offset
client通过topic找到topic树下的state节点、获取leader的brokerID,到broker树中找到broker的物理 地址,但是client不会直连zk,而是通过配置的broker获取到zk中的信息
简述Kafka的rebalance机制
consumer group中的消费者与topic下的partion重新匹配的过程 何时会产生rebalance:
- consumer group中的成员个数发生变化
- consumer消费超时
- group订阅的topic个数发生变化
- group订阅的topic的分区数发生变化
coordinator:通常是partition的leader节点所在的broker,负责监控group中consumer的存活, consumer维持到coordinator的心跳,判断consumer的消费超时
- coordinator通过心跳返回通知consumer进行rebalance
- consumer请求coordinator加入组,coordinator选举产生leader consumer
- leader consumer从coordinator获取所有的consumer,发送syncGroup(分配信息)给到 coordinator
- coordinator通过心跳机制将syncGroup下发给consumer
- 完成rebalance
leader consumer监控topic的变化,通知coordinator触发rebalance
如果C1消费消息超时,触发rebalance,重新分配后、该消息会被其他消费者消费,此时C1消费完成提 交offset、导致错误
解决:coordinator每次rebalance,会标记一个Generation给到consumer,每次rebalance该 Generation会 1,consumer提交offset时,coordinator会比对Generation,不一致则拒绝提交
Kafka的性能好在什么地方
Kafka不基于内存,而是硬盘存储,因此消息堆积能力更强
顺序写:利用磁盘的顺序访问速度可以接近内存,kafka的消息都是append操作,partition是有序的, 节省了磁盘的寻道时间,同时通过批量操作、节省写入次数,partition物理上分为多个segment存储, 方便删除
传统:
- 读取磁盘文件数据到内核缓冲区
- 将内核缓冲区的数据copy到用户缓冲区
- 将用户缓冲区的数据copy到socket的发送缓冲区
- 将socket发送缓冲区中的数据发送到网卡、进行传输
零拷贝:
- 直接将内核缓冲区的数据发送到网卡传输
- 使用的是操作系统的指令支持
Kafka不太依赖JVM,主要理由操作系统的pageCache,如果生产消费速率相当,则直接用pageCache 交换数据,不需要经过磁盘IO