Apach Kafka 是一款分布式流处理框架,用于实时构建流处理应用。它有一个核心 的功能广为人知,即 作为企业级的消息引擎被广泛使用
kafka设计
Kafka 将消息以 topic 为单位进行归纳 将向 Kafka topic 发布消息的程序成为 producers. 将预订 topics 并消费消息的程序成为 consumer. Kafka 以集群的方式运行,可以由一个或多个服务组成,每个服务叫做一个 broker. producers 通过网络将消息发送到 Kafka 集群,集群向消费者提供消息
为什么使用MQ?MQ的优点?
主要是:解耦、异步、削峰。
1、解耦:A 系统发送数据到 BCD 三个系统,通过接口调用发送。如果 E 系统也要这个数据呢?那如果 C 系统现在不需要了呢?A 系统负责人几乎崩溃…A 系统跟其它各种乱七八糟的系统严重耦合,A 系统产 生一条比较关键的数据,很多系统都需要 A 系统将这个数据发送过来。如果使用 MQ,A 系统产生一条 数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消费。如果新系统需要数据,直接从 MQ 里消费即可;如果某个系统不需要这条数据了,就取消对 MQ 消息的消费即可。这样下来,A 系统 压根儿不需要去考虑要给谁发送数据,不需要维护这个代码,也不需要考虑人家是否调用成功、失败超 时等情况。 就是一个系统或者一个模块,调用了多个系统或者模块,互相之间的调用很复杂,维护起来很麻烦。但 是其实这个调用是不需要直接同步调用接口的,如果用 MQ 给它异步化解耦。
2、异步:A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s,用户感觉搞个什么东西,慢死了慢死了。用户通过浏览器发起请求。如果使用 MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应 给用户,总时长是 3 + 5 = 8ms。
削峰:减少高峰时期对服务器压力。
但是引入MQ以后要注意一下三个问题
3、系统可用性降低
本来系统运行好好的,现在你非要加入个消息队列进去,那消息队列挂了,你的系统不是呵呵了。
1、系统可用性会降低
系统复杂度提高 加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保 证消息可靠性传输等。因此,需要考虑的东西更多,复杂性增大。
2、一致性问题
A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那 里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。 所以消息队列实际是一种非常复杂的架构,你引入它有很多好处,但是也得针对它带来的坏处做各种额 外的技术方案和架构来规避掉,做好之后,你会发现,妈呀,系统复杂度提升了一个数量级,也许是复 杂了 10 倍。但是关键时刻,用,还是得用的。
什么是消费组?
1、定义:即消费者组是 Kafka 提供的可扩展且具有容错性的消费者机制。 2、原理:在 Kafka 中,消费者组是一个由多个消费者实例 构成的组。多个实例共同订阅若干个主题, 实现共同消费。同一个组下的每个实例都配置有 相同的组 ID,被分配不同的订阅分区。当某个实例挂 掉的时候,其他实例会自动地承担起 它负责消费的分区。
在 Kafka 中,ZooKeeper 的作用是什么?
Kafka 使用 ZooKeeper 存放集群元数据、成员管理、Controller 选举,以及其他一些管理类任 务。之后,等 KIP-500 提案完成后,Kafka 将完全不再依赖 于 ZooKeeper。
“存放元数据”是指主题 分区的所有数据 都保存在 ZooKeeper 中,且以它保存的数据为权威,其他“人”都要与它 保持对齐。
“成员管理”是指 Broker 节点的注册、注销以及属性变更,等 等。“Controller 选举”是指选举集群 Controller,而其他管 理类任务包括但不限于主题 删除、参数配置等。
解释下 Kafka 中位移(offset)的作用?
在 Kafka 中,每个 主题分区下的每条消息都被赋予了一个唯一的 ID 数值,用于标识它在分区中的位 置。这个 ID 数值,就被称为位移,或者叫偏移量。一旦消息被写入到分区日志,它的位移值将不能 被 修改。
__consumer_offsets 是做什么用的?
它的主要作用是负责注册消费者以及保存位移值。可能你对保存位移值的功能很熟悉, 但其实该主题也 是保存消费者元数据的地方。千万记得把这一点也回答上。另外,这里 的消费者泛指消费者组和独立消 费者,而不仅仅是消费者组。 Kafka 的 GroupCoordinator 组件提供对该主题完整的管理功能,包括该主题的创建、 写入、读取和 Leader 维护等。
Kafka 为什么不支持读写分离?
场景不适用。读写分离适用于那种读负载很大,而写操作相对不频繁的场景,可 Kafka 不属于这 样的场景。
同步机制。Kafka 采用 PULL 方式实现 Follower 的同步,因此,Follower 与 Leader 存 在不一致 性窗口。如果允许读 Follower 副本,就势必要处理消息滞后(Lagging)的问题。
Kafka 能手动删除消息吗?
其实,Kafka 不需要用户手动删除消息。它本身提供了留存策略,能够自动删除过期消息。
对于设置了 Key 且参数 cleanup.policy=compact 的主题而言,我们可以构造一条 的 消息发送给 Broker,依靠 Log Cleaner 组件提供的功能删除掉该 Key 的消息。 对于普通主题而言,我们可以使用 kafka-delete-records 命令,或编写程序调用 Admin.deleteRecords 方法来删除消息。这两种方法殊途同归,底层都是调用 Admin 的 deleteRecords 方法,通过将分区 Log Start Offset 值抬高的方式间接删除消息。
LEO、LSO、AR、ISR、HW 都表示什么含义?
LEO:Log End Offset。日志末端位移值或末端偏移量,表示日志下一条待插入消息的 位移值。举 个例子,如果日志有 10 条消息,位移值从 0 开始,那么,第 10 条消息的位 移值就是 9。此时, LEO = 10。
LSO:Log Stable Offset。这是 Kafka 事务的概念。如果你没有使用到事务,那么这个 值不存在(其 实也不是不存在,只是设置成一个无意义的值)。该值控制了事务型消费 者能够看到的消息范围。 它经常与 Log Start Offset,即日志起始位移值相混淆,因为 有些人将后者缩写成 LSO,这是不对 的。在 Kafka 中,LSO 就是指代 Log Stable Offset。 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 中移除。
HW:高水位值(High watermark)。这是控制消费者可读取消息范围的重要字段。一 个普通消费者 只能“看到”Leader 副本上介于 Log Start Offset 和 HW(不含)之间的 所有消息。水位以上的消息是 对消费者不可见的。关于 HW,问法有很多,我能想到的 最高级的问法,就是让你完整地梳理下 Follower 副本拉取 Leader 副本、执行同步机制 的详细步骤。
分区 Leader 选举策略有几种?
分区的 Leader 副本选举对用户是完全透明的,它是由 Controller 独立完成的。你需要回答的是,在哪 些场景下,需要执行分区 Leader 选举。每一种场景对应于一种选举策略。当前,Kafka 有 4 种分区 Leader 选举策略。
OfflinePartition Leader 选举:每当有分区上线时,就需要执行 Leader 选举。所谓的分区上线, 可能是创建了新分区,也可能是之前的下线分区重新上线。这是最常见的分区 Leader 选举场景。 ReassignPartition Leader 选举:当你手动运行 kafka-reassign-partitions 命令,或者是调用 Admin 的 alterPartitionReassignments 方法执行分区副本重分配时,可能触发此类选举。假设原 来的 AR 是[1,2,3],Leader 是 1,当执行副本重分配后,副本集 合 AR 被设置成[4,5,6],显 然,Leader 必须要变更,此时会发生 Reassign Partition Leader 选举。
PreferredReplicaPartition Leader 选举:当你手动运行 kafka-preferred-replica- election 命 令,或自动触发了 Preferred Leader 选举时,该类策略被激活。所谓的 Preferred Leader,指的 是 AR 中的第一个副本。比如 AR 是[3,2,1],那么, Preferred Leader 就是 3。 ControlledShutdownPartition Leader 选举:当 Broker 正常关闭时,该 Broker 上 的所有 Leader 副本都会下线,因此,需要为受影响的分区执行相应的 Leader 选举。
Kafka 消息是采用 Pull 模式,还是 Push 模式?
Kafka 最初考虑的问题是,customer 应该从 brokes 拉取消息还是 brokers 将消息推送到 consumer,也就是 pull 还 push。在这方面,Kafka 遵循了一种大部分消息系统共同的传统 的设计:producer 将消息推送到 broker,consumer 从 broker 拉取消息 一些消息系统比如 Scribe 和 Apache Flume 采用了 push 模式,将消息推送到下游的 consumer。 这样做有好处也有坏处:由 broker 决定消息推送的速率,对于不同消费速率的consumer 就不太好处理了。消息系统都致力于让 consumer 以最大的速率最快速的消费消 息,但不幸的是,push 模式下,当 broker 推送的速率远大于 consumer 消费的速率时, consumer 恐怕就要崩溃了。 最终, Kafka 还是选取了传统的 pull 模式。
Pull 模式的另外一个好处是 consumer 可以自主决定是否批量的从 broker 拉取数据。Push 模式必须在不知道下游 consumer 消费能力和消费策略的情况下决定是立即推送每条消息还 是缓存之后批量推送。如果为了避免 consumer 崩溃而采用较低的推送速率,将可能导致一 次只推送较少的消息而造成浪费。Pull 模式下,consumer 就可以根据自己的消费能力去决 定这些策略 Pull 有个缺点是,如果 broker 没有可供消费的消息,将导致 consumer 不断在循环中轮询, 直到新消息到 t 达。为了避免这点,Kafka 有个参数可以让 consumer 阻塞知道新消息到达 (当然也可以阻塞知道消息的数量达到某个特定的量这样就可以批量Pull)
Kafka 存储在硬盘上的消息格式是什么?
消息由一个固定长度的头部和可变长度的字节数组组成。头部包含了一个版本号和 CRC32 校验码。
kafka 的 ack 机制
acks=0:此模式下,生产者在发送消息后不会等待任何来自Broker的确认响应。这意味着一旦消息被发送出去,即使Broker没有成功写入磁盘,生产者也会继续处理其他任务。这种模式适用于对延迟要求极高且可以容忍一定数据丢失的场景,但如果Broker发生故障,可能会导致消息丢失。
acks=1:在此模式下,生产者需要等待Leader副本成功将消息写入本地日志文件后才返回确认。这种模式提供了一定的可靠性保证,因为至少有一个副本已经保存了消息。如果Leader副本在follower副本同步之前崩溃,消息可能会丢失。这种模式适用于大多数应用场景,能够在可接受的延迟范围内提供较好的消息可靠性。
acks=all或acks=-1:在此模式下,生产者需要等待所有在ISR(In-Sync Replicas)中的副本都成功写入消息后才返回确认。这种模式提供了最高的消息可靠性保证,因为只有当所有副本都成功写入消息时,生产者才认为消息已经成功发送。这种模式适用于对消息可靠性要求极高的场景,但相应的延迟也会增加。这确保了消息的可靠性,但会导致更长的延迟。
Kafka 的消费者如何消费数据
消费者每次消费数据的时候,消费者都会记录消费的物理偏移量(offset)的位置 等到下次消费时,他会接着上次位置继续消费.
partition 的数据如何保存到硬盘
topic 中的多个 partition 以文件夹的形式保存到 broker,每个分区序号从 0 递增, 且消息有序 Partition 文件下有多个 segment(xxx.index,xxx.log) segment 文件里的 大小和配置文件大小一致可以根据要求修改 默认为 1g 如果大小大于 1g 时,会滚动一个新的 segment 并且以上一个 segment 最后一条消息的偏移量命名.
Kafka 新建的分区会在哪个目录下创建
在启动 Kafka 集群之前,我们需要配置好 log.dirs 参数,其值是 Kafka 数据的存放目录, 这个参数可以配置多个目录,目录之间使用逗号分隔,通常这些目录是分布在不同的磁盘 上用于提高读写性能。 当然我们也可以配置 log.dir 参数,含义一样。只需要设置其中一个即可。 如果 log.dirs 参数只配置了一个目录,那么分配到各个 Broker 上的分区肯定只能在这个 目录下创建文件夹用于存放数据。
但是如果 log.dirs 参数配置了多个目录,那么 Kafka 会在哪个文件夹中创建分区目录呢?
答案是:Kafka 会在含有分区目录最少的文件夹中创建新的分区目录,分区目录名为 Topic 名+分区 ID。注意,是分区文件夹总数最少的目录,而不是磁盘使用量最少的目录!也就 是说,如果你给 log.dirs 参数新增了一个新的磁盘,新的分区目录肯定是先在这个新的磁 盘上创建直到这个新的磁盘目录拥有的分区目录不是最少为止。
Kafka 创建 Topic 时如何将分区放置到不同的 Broker中
副本因子不能大于 Broker 的个数;
第一个分区(编号为 0)的第一个副本放置位置是随机从 brokerList 选择的;
其他分区的第一个副本放置位置相对于第 0 个分区依次往后移。也就是如果我们有 5 个 Broker,5 个分区,假设第一个分区放在第四个 Broker 上,那么第二个分区将会放在第五 个 Broker 上;第三个分区将会放在第一个 Broker 上;第四个分区将会放在第二个 Broker 上,依次类推;
剩余的副本相对于第一个副本放置位置其实是由 nextReplicaShift 决定的,而这个数也是 随机产生的.剩余的副本相对于第一个副本放置位置其实是由 nextReplicaShift 决定的,而这个数也是 随机产生的
Kafka的数据有序
一个消费者组里它的内部是有序的,消费者组与消费者组之间是无序的。
Kafka数据传输的事务定义有哪三种?
数据传输的事务定义通常有以下三种级别:
(1)最多一次: 消息不会被重复发送,最多被传输一次,但也有可能一次不传输
(2)最少一次: 消息不会被漏发送,最少被传输一次,但也有可能被重复传输.
(3)精确的一次(Exactly once): 不会漏传输也不会重复传输,每个消息都传输被一次而 且仅仅被传输一次,这是大家所期望的。
Kafka 判断一个节点是否还活着有那两个条件?
(1)节点必须可以维护和 ZooKeeper 的连接,Zookeeper 通过心跳机制检查每个节点的连接。(2)如果节点是个 follower,他必须能及时的同步 leader 的写操作,延时不能太久。
监控 Kafka 的框架都有哪些?
1. Kafka Manager:应该算是最有名的专属 Kafka 监控框架了,是独立的监控系统。
2. Kafka Monitor:LinkedIn 开源的免费框架,支持对集群进行系统测试,并实时监控测 试结果。 3. CruiseControl:也是 LinkedIn 公司开源的监控框架,用于实时监测资源使用率,以及 提供常用运 维操作等。无 UI 界面,只提供 REST API。
4. JMX 监控:由于 Kafka 提供的监控指标都是基于 JMX 的,因此,市面上任何能够集成 JMX 的框架 都可以使用,比如 Zabbix 和 Prometheus。
5. 已有大数据平台自己的监控体系:像 Cloudera 提供的 CDH 这类大数据平台,天然就提 供 Kafka 监 控方案。
6. JMXTool:社区提供的命令行工具,能够实时监控 JMX 指标。答上这一条,属于绝对 的加分项,因 为知道的人很少,而且会给人一种你对 Kafka 工具非常熟悉的感觉。如果 你暂时不了解它的用 法,可以在命令行以无参数方式执行一下kafka-run-class.sh kafka.tools.JmxTool,学习下它的用 法。
通过Kafka的AdminClient的监控消费堆积情况.
如何设置 Kafka 能接收的最大消息的大小?
如 果 Producer 都不能向 Broker 端发送数据很大的消息,又何来消费一说呢? 因此,你需要同时设置 Broker 端参数和 Consumer 端参数。
Broker 端参数:message.max.bytes、max.message.bytes(主题级别)和 replica.fetch.max.bytes。 Consumer 端参数:fetch.message.max.bytes。 Broker 端的最后一个参数比较容易遗漏。我们必须调整 Follower 副本能够接收的最大消 息的大小,否 则,副本同步就会失败。
Kafka分区分配策略
在Kafka内部存在两种默认的分区分配策略:Range和RoundRobin。
Range是默认策略。Range是对每个Topic而言的(即一个Topic一个Topic分),首先对同一个Topic里面的分区按序号进行排序,并对消费者按照字母顺序进行排序。然后用Partition分区的个数除以消费者总线程数来决定每个消费者线程消费几个分区的数据。如果除不尽,那前几个消费者线程会多消费一个分区。