文章首发公众号:码哥字节(ID:MageByte)
Kafka 是一个优秀的分布式消息中间件,许多系统中都会使用到 Kafka 来作消息通讯。对分布式消息系统的了解和使用几乎成为一个后台开发人员必备的技能。今天码哥字节
就从常见的 Kafka 面试题入手,和你们聊聊 Kafka 的那些事儿。面试
分布式消息是一种通讯机制,和 RPC、HTTP、RMI 等不同,消息中间件采用分布式中间代理的方式进行通讯。如图所示,采用了消息中间件以后,上游业务系统发送消息,先存储在消息中间件,而后由消息中间件将消息分发到对应的业务模块应用(分布式生产者 - 消费者模式)。这种异步的方式,减小了服务之间的耦合程度。shell
定义消息中间件:数据库
在系统架构中引用额外的组件,必然提升系统的架构复杂度和运维的难度,那么在系统中使用分布式消息中间件有什么优点呢?消息中间件在系统中起的做用又是什么呢?bootstrap
面试时,面试官常常会关心面试者对开源组件的选型能力,这既能够考验面试者知识的广度,也能够考验面试者对某类系统的知识的认识深度,并且也能够看出面试者对系统总体把握和系统架构设计的能力。开源分布式消息系统有不少,不一样的消息系统的特性也不同,选择怎样的消息系统,不只须要对各消息系统有必定的了解,也须要对自身系统需求有清晰的认识。缓存
下面是常见的几种分布式消息系统的对比:安全
Kafka 架构中的通常概念:性能优化
Kafka Topic Partitions Layout服务器
Kafka 将 Topic 进行分区,分区能够并发读写。网络
Kafka Consumer Offsetsession
简单讲下 Kafka 的架构?
Producer、Consumer、Consumer Group、Topic、Partition
Kafka 是推模式仍是拉模式,推拉的区别是什么?
Kafka Producer 向 Broker 发送消息使用 Push 模式,Consumer 消费采用的 Pull 模式。拉取模式,让 consumer 本身管理 offset,能够提供读取性能
Kafka 如何广播消息?
Consumer group
Kafka 的消息是不是有序的?
Topic 级别无序,Partition 有序
Kafka 是否支持读写分离?
不支持,只有 Leader 对外提供读写服务
Kafka 如何保证数据高可用?
副本,ack,HW
Kafka 中 zookeeper 的做用?
集群管理,元数据管理
是否支持事务?
0.11 后支持事务,能够实现”exactly once“
分区数是否能够减小?
不能够,会丢失数据
Kafka 的命令行工具在 Kafka 包的/bin
目录下,主要包括服务和集群管理脚本,配置脚本,信息查看脚本,Topic 脚本,客户端脚本等。
咱们一般可使用kafka-console-consumer.sh
和kafka-console-producer.sh
脚原本测试 Kafka 生产和消费,kafka-consumer-groups.sh
能够查看和管理集群中的 Topic,kafka-topics.sh
一般用于查看 Kafka 的消费组状况。
Kafka producer 的正常生产逻辑包含如下几个步骤:
Producer 发送消息的过程以下图所示,须要通过拦截器
,序列化器
和分区器
,最终由累加器
批量发送至 Broker。
Kafka Producer 须要如下必要参数:
常见参数:
batch.num.messages
默认值:200,每次批量消息的数量,只对 asyc 起做用。
request.required.acks
默认值:0,0 表示 producer 毋须等待 leader 的确认,1 表明须要 leader 确认写入它的本地 log 并当即确认,-1 表明全部的备份都完成后确认。 只对 async 模式起做用,这个参数的调整是数据不丢失和发送效率的 tradeoff,若是对数据丢失不敏感而在意效率的场景能够考虑设置为 0,这样能够大大提升 producer 发送数据的效率。
request.timeout.ms
默认值:10000,确认超时时间。
partitioner.class
默认值:kafka.producer.DefaultPartitioner,必须实现 kafka.producer.Partitioner,根据 Key 提供一个分区策略。_有时候咱们须要相同类型的消息必须顺序处理,这样咱们就必须自定义分配策略,从而将相同类型的数据分配到同一个分区中。_
producer.type
默认值:sync,指定消息发送是同步仍是异步。异步 asyc 成批发送用 kafka.producer.AyncProducer, 同步 sync 用 kafka.producer.SyncProducer。同步和异步发送也会影响消息生产的效率。
compression.topic
默认值:none,消息压缩,默认不压缩。其他压缩方式还有,"gzip"、"snappy"和"lz4"。对消息的压缩能够极大地减小网络传输量、下降网络 IO,从而提升总体性能。
compressed.topics
默认值:null,在设置了压缩的状况下,能够指定特定的 topic 压缩,未指定则所有压缩。
message.send.max.retries
默认值:3,消息发送最大尝试次数。
retry.backoff.ms
默认值:300,每次尝试增长的额外的间隔时间。
topic.metadata.refresh.interval.ms
默认值:600000,按期的获取元数据的时间。当分区丢失,leader 不可用时 producer 也会主动获取元数据,若是为 0,则每次发送完消息就获取元数据,不推荐。若是为负值,则只有在失败的状况下获取元数据。
queue.buffering.max.ms
默认值:5000,在 producer queue 的缓存的数据最大时间,仅仅 for asyc。
queue.buffering.max.message
默认值:10000,producer 缓存的消息的最大数量,仅仅 for asyc。
queue.enqueue.timeout.ms
默认值:-1,0 当 queue 满时丢掉,负值是 queue 满时 block, 正值是 queue 满时 block 相应的时间,仅仅 for asyc。
Kafka 有消费组的概念,每一个消费者只能消费所分配到的分区的消息,每个分区只能被一个消费组中的一个消费者所消费,因此同一个消费组中消费者的数量若是超过了分区的数量,将会出现有些消费者分配不到消费的分区。消费组与消费者关系以下图所示:
Kafka Consumer Client 消费消息一般包含如下步骤:
由于 Kafka 的 Consumer 客户端是线程不安全的,为了保证线程安全,并提高消费性能,能够在 Consumer 端采用相似 Reactor 的线程模型来消费数据。
host:port
格式。key.serializer
对应,key 的反序列化方式。value.serializer
对应,value 的反序列化方式。false
,则须要在程序中手动提交位移。对于精确到一次的语义,最好手动提交位移max.poll.records
条数据须要在在 session.timeout.ms 这个时间内处理完 。默认值为 500rebalance 本质上是一种协议,规定了一个 consumer group 下的全部 consumer 如何达成一致来分配订阅 topic 的每一个分区。好比某个 group 下有 20 个 consumer,它订阅了一个具备 100 个分区的 topic。正常状况下,Kafka 平均会为每一个 consumer 分配 5 个分区。这个分配的过程就叫 rebalance。
何时 rebalance?
这也是常常被说起的一个问题。rebalance 的触发条件有三种:
如何进行组内分区分配?
Kafka 默认提供了两种分配策略:Range 和 Round-Robin。固然 Kafka 采用了可插拔式的分配策略,你能够建立本身的分配器以实现不一样的分配策略。
/bin
目录,管理 kafka 集群、管理 topic、生产和消费 kafka在分布式数据系统中,一般使用分区来提升系统的处理能力,经过副原本保证数据的高可用性。多分区意味着并发处理的能力,这多个副本中,只有一个是 leader,而其余的都是 follower 副本。仅有 leader 副本能够对外提供服务。 多个 follower 副本一般存放在和 leader 副本不一样的 broker 中。经过这样的机制实现了高可用,当某台机器挂掉后,其余 follower 副本也能迅速”转正“,开始对外提供服务。
为何 follower 副本不提供读服务?
这个问题本质上是对性能和一致性的取舍。试想一下,若是 follower 副本也对外提供服务那会怎么样呢?首先,性能是确定会有所提高的。但同时,会出现一系列问题。相似数据库事务中的幻读,脏读。 好比你如今写入一条数据到 kafka 主题 a,消费者 b 从主题 a 消费数据,却发现消费不到,由于消费者 b 去读取的那个分区副本中,最新消息还没写入。而这个时候,另外一个消费者 c 却能够消费到最新那条数据,由于它消费了 leader 副本。Kafka 经过 WH 和 Offset 的管理来决定 Consumer 能够消费哪些数据,已经当前写入的数据。
只有 Leader 能够对外提供读服务,那如何选举 Leader
kafka 会将与 leader 副本保持同步的副本放到 ISR 副本集合中。固然,leader 副本是一直存在于 ISR 副本集合中的,在某些特殊状况下,ISR 副本中甚至只有 leader 一个副本。 当 leader 挂掉时,kakfa 经过 zookeeper 感知到这一状况,在 ISR 副本中选取新的副本成为 leader,对外提供服务。 但这样还有一个问题,前面提到过,有可能 ISR 副本集合中,只有 leader,当 leader 副本挂掉后,ISR 集合就为空,这时候怎么办呢?这时候若是设置 unclean.leader.election.enable 参数为 true,那么 kafka 会在非同步,也就是不在 ISR 副本集合中的副本中,选取出副本成为 leader。
副本的存在就会出现副本同步问题
Kafka 在全部分配的副本 (AR) 中维护一个可用的副本列表 (ISR),Producer 向 Broker 发送消息时会根据ack
配置来肯定须要等待几个副本已经同步了消息才相应成功,Broker 内部会ReplicaManager
服务来管理 flower 与 leader 之间的数据同步。
一方面,因为不一样 Partition 可位于不一样机器,所以能够充分利用集群优点,实现机器间的并行处理。另外一方面,因为 Partition 在物理上对应一个文件夹,即便多个 Partition 位于同一个节点,也可经过配置让同一节点上的不一样 Partition 置于不一样的 disk drive 上,从而实现磁盘间的并行处理,充分发挥多磁盘的优点。
Kafka 每个 partition 目录下的文件被平均切割成大小相等(默认一个文件是 500 兆,能够手动去设置)的数据文件,
每个数据文件都被称为一个段(segment file), 每一个 segment 都采用 append 的方式追加数据。
Kafka 如何保证高可用?
经过副原本保证数据的高可用,producer ack、重试、自动 Leader 选举,Consumer 自平衡
Kafka 的交付语义?
交付语义通常有at least once
、at most once
和exactly once
。kafka 经过 ack 的配置来实现前两种。
Replic 的做用?
实现数据的高可用
什么是 AR,ISR?
AR:Assigned Replicas。AR 是主题被建立后,分区建立时被分配的副本集合,副本个 数由副本因子决定。
ISR:In-Sync Replicas。Kafka 中特别重要的概念,指代的是 AR 中那些与 Leader 保 持同步的副本集合。在 AR 中的副本可能不在 ISR 中,但 Leader 副本自然就包含在 ISR 中。关于 ISR,还有一个常见的面试题目是如何判断副本是否应该属于 ISR。目前的判断 依据是:Follower 副本的 LEO 落后 Leader LEO 的时间,是否超过了 Broker 端参数 replica.lag.time.max.ms 值。若是超过了,副本就会被从 ISR 中移除。
Kafka 中的 HW 表明什么?
高水位值 (High watermark)。这是控制消费者可读取消息范围的重要字段。一 个普通消费者只能“看到”Leader 副本上介于 Log Start Offset 和 HW(不含)之间的 全部消息。水位以上的消息是对消费者不可见的。
Kafka 为保证优越的性能作了哪些处理?
partition 并发、顺序读写磁盘、page cache 压缩、高性能序列化(二进制)、内存映射 无锁 offset 管理、Java NIO 模型
本文并无深刻 Kafka 的实现细节和源码分析,但 Kafka 确实是一个 优秀的开源系统,不少优雅的架构设计和源码设计都值得咱们学习,十分建议感兴趣的同窗更加深刻的去了解一下这个开源系统,对于自身架构设计能力,编码能力,性能优化都会有很大的帮助。
如下几篇文章阅读量与读者反馈都很好,推荐你们阅读: