00 开篇词 | 为什么要学习Kafka?
01 | 消息引擎系统ABC
Apache Kafka 是一款开源的消息引擎系统。
定义
官方:根据维基百科的定义,消息引擎系统是一组规范。企业利用这组规范在不同系统之间传递语义准确的消息,实现松耦合的异步式数据传递。
民间:系统 A 发送消息给消息引擎系统,系统 B 从消息引擎系统中读取 A 发送的消息。
格式
消息格式:使用的是纯二进制的字节序列。
传输协议
点对点模型:也叫消息队列模型。系统 A发送的消息只能被系统B接收,其他任何系统都不能读取 A 发送的消息。
发布 / 订阅模型:与上面不同的是,它有一个主题(Topic)的概念。该模型也有发送方和接收方,发送方也称为发布者(Publisher),接收方称为订阅者(Subscriber)。和点对点模型不同的是,这个模型可能存在多个发布者向相同的主题发送消息,而订阅者也可能存在多个,它们都能接收到相同的消息。
02 | 一篇文章带你快速搞定Kafka术语
服务器端:Kafka 的服务器端由被称为 Broker 的服务进程构成,即一个 Kafka 集群由多个 Broker 组成,Broker 负责接收和处理客户端发送过来的请求,以及对消息进行持久化。
客户端:生产者、消费者
高可用:Kafka 定义了两类副本:领导者副本(LeaderReplica)和追随者副本(Follower Replica)。前者对外提供服务,这里的对外指的是与客户端程序进行交互;而后者只是被动地追随领导者副本而已,不能与外界进行交互。追随者副本,它只做一件事:向领导者副本发送请求,请求领导者把最新生产的消息发给它,这样它能保持与领导者的同步。
伸缩性:Kafka 中的分区机制指的是将每个主题划分成多个分区(Partition),每个分区是一组有序的消息日志。生产者生产的每条消息只会被发送到一个分区中。
位置:生产者向分区写入消息,每条消息在分区中的位置信息由一个叫位移(Offset)的数据来表征。
持久化:Kafka 使用消息日志(Log)来保存数据,一个日志就是磁盘上一个只能追加写(Append-only)消息的物理文件。在 Kafka 底层,一个日志又近一步细分成多个日志段,消息被追加写到当前最新的日志段中,当写满了一个日志段后,Kafka 会自动切分出一个新的日志段,并将老的日志段封存起来。Kafka 在后台还有定时任务会定期地检查老的日志段是否能够被删除,从而实现回收磁盘空间的目的。
P2P:所谓的消费者组,指的是多个消费者实例共同组成一个组来消费一组主题。这组主题中的每个分区都只会被组内的一个消费者实例消费,其他消费者实例不能消费它。
一个broker上会有几个分区,这里的分区都是指leader分区,同时follower分区也在不同的broker上
03 | Kafka只是消息引擎系统吗?
Apache Kafka 是消息引擎系统,也是一个分布式流处理平台(Distributed Streaming Platform)。
今天 Apache Kafka 是和 Apache Storm、Apache Spark 和 Apache Flink 同等级的实时流处理平台。
04 | 我应该选择哪种Kafka?
Apache Kafka,也称社区版 Kafka。优势在于迭代速度快,社区响应度高,使用它可以让你有更高的把控度;缺陷在于仅提供基础核心组件,缺失一些高级的特性。
Confluent Kafka,Confluent 公司提供的 Kafka。优势在于集成了很多高级特性且由Kafka 原班人马打造,质量上有保证;缺陷在于相关文档资料不全,普及率较低,没有太多可供参考的范例。
CDH/HDP Kafka,大数据云公司提供的 Kafka,内嵌 Apache Kafka。优势在于操作简单,节省运维成本;缺陷在于把控度低,演进速度较慢。
05 | 聊聊Kafka的版本号
规则:如2.1.1,前面的 2 表示大版本号Major Version;中间的 1 表示小版本号或次版本号,即 Minor Version;最后的 1 表示修订版本号,也就是 Patch 号
06 | Kafka线上集群部署方案怎么做?
主流的 I/O 模型通常有 5 种类型:阻塞式 I/O、非阻塞式 I/O、I/O 多路复用、信号驱动I/O 和异步 I/O。每种 I/O 模型都有各自典型的使用场景,比如 Java 中 Socket 对象的阻塞模式和非阻塞模式就对应于前两种模型;而 Linux 中的系统调用 select 函数就属于 I/O多路复用模型;大名鼎鼎的 epoll 系统调用则介于第三种和第四种模型之间;至于第五种模型,其实很少有 Linux 系统支持,反而是 Windows 系统提供了一个叫 IOCP 线程模型属于这一种。
07 | 最最最重要的集群参数配置(上)
首先 ZooKeeper 是做什么的呢?它是一个分布式协调框架,负责协调管理并保存 Kafka 集群的所有元数据信息,比如集群都有哪些Broker 在运行、创建了哪些 Topic,每个 Topic 都有多少分区以及这些分区的 Leader 副本都在哪些机器上等信息。
08 | 最最最重要的集群参数配置(下)
Topic 级别参数会覆盖全局Broker 参数的值,而每个 Topic 都能设置自己的参数值,这就是所谓的 Topic 级别参数。
09 | 生产者消息分区机制原理剖析
Kafka 的消息组织方式实际上是三级结构:主题 - 分区 - 消息。
分区的作用:提供负载均衡能力,为了实现系统的高伸缩性(Scalability)
所谓分区策略是决定生产者将消息发送到哪个分区的算法。
分区策略:轮询策略、随机策略、按消息键保序策略( Key-ordering)、基于地理位置的分区策略
10 | 生产者压缩算法面面观
压缩作用:时间换空间,希望以较小的 CPU 开销带来更少的磁盘占用或更少的网络 I/O 传输
Kafka 的消息层次都分为两层:消息集合(message set)以及消息(message)。一个消息集合中包含若干条日志项(record item),而日志项才是真正封装消息的地方。Kafka 底层的消息日志由一系列消息集合日志项组成。Kafka 通常不会直接操作具体的一条条消息,它总是在消息集合这个层面上进行写入操作。
压缩:生产者端和 Broker 端
解压: Consumer 自行解压缩还原成之前的消息
Producer 端压缩、Broker 端保持、Consumer端解压缩
11 | 无消息丢失配置怎么实现?
Kafka 只对“已提交”的消息(committed message)做有限度的持久化保证。
配置方案:
1.不要使用 producer.send(msg),而要使用 producer.send(msg, callback)。记住,一定要使用带有回调通知的 send 方法。
2.设置 acks = all。acks 是 Producer 的一个参数,代表了你对“已提交”消息的定义。如果设置成 all,则表明所有副本 Broker 都要接收到消息,该消息才算是“已提交”。这是最高等级的“已提交”定义。
3.设置 retries 为一个较大的值。这里的 retries 同样是 Producer 的参数,对应前面提到的 Producer 自动重试。当出现网络的瞬时抖动时,消息发送可能会失败,此时配置了retries > 0 的 Producer 能够自动重试消息发送,避免消息丢失。
4.设置 unclean.leader.election.enable = false。这是 Broker 端的参数,它控制的是哪些 Broker 有资格竞选分区的 Leader。如果一个 Broker 落后原先的 Leader 太多,那么它一旦成为新的 Leader,必然会造成消息的丢失。故一般都要将该参数设置成 false,即不允许这种情况的发生。
5.设置 replication.factor >= 3。这也是 Broker 端的参数。其实这里想表述的是,最好将消息多保存几份,毕竟目前防止消息丢失的主要机制就是冗余。
6.设置 min.insync.replicas > 1。这依然是 Broker 端参数,控制的是消息至少要被写入到多少个副本才算是“已提交”。设置成大于 1 可以提升消息持久性。在实际环境中千万不要使用默认值 1。
7.确保 replication.factor > min.insync.replicas。如果两者相等,那么只要有一个副本挂机,整个分区就无法正常工作了。我们不仅要改善消息的持久性,防止数据丢失,还要在不降低可用性的基础上完成。推荐设置成 replication.factor = min.insync.replicas +1。
8.确保消息消费完成再提交。Consumer 端有个参数 enable.auto.commit,最好把它设置成 false,并采用手动提交位移的方式。就像前面说的,这对于单 Consumer 多线程处理的场景而言是至关重要的。
12 | 客户端都有哪些不常见但是很高级的功能?
拦截器:其基本思想就是允许应用程序在不修改逻辑的情况下,动态地实现一组可插拔的事件处理逻辑链。
Kafka 拦截器分为生产者拦截器和消费者拦截器。生产者拦截器允许你在发送消息前以及消息提交成功后植入你的拦截器逻辑;而消费者拦截器支持在消费消息前以及提交位移后编写特定逻辑。
13 | Java生产者是如何管理TCP连接的?
创建时机:
- 在创建 KafkaProducer 实例时,生产者应用会在后台创建并启动一个名为 Sender 的线程,该 Sender 线程开始运行时首先会创建与 Broker 的连接。
- TCP 连接还可能在两个地方被创建:一个是在更新元数据后(Sender线程向某一台 Broker 发送了METADATA 请求,尝试获取集群的元数据信息),另一个是在消息发送时。
关闭时机:
Producer 端关闭 TCP 连接的方式有两种:一种是用户主动关闭;一种是 Kafka 自动关闭。
14 | 幂等生产者和事务生产者是一回事吗?
消息交付可靠性(指 Kafka 对 Producer 和 Consumer 要处理的消息提供什么样的承诺):
最多一次(at most once):消息可能会丢失,但绝不会被重复发送。
至少一次(at least once):消息不会丢失,但有可能被重复发送。
精确一次(exactly once):消息不会丢失,也不会被重复发送。
幂等性 Producer:
首先,它只能保证单分区上的幂等性,即一个幂等性Producer 能够保证某个主题的一个分区上不出现重复消
息,它无法实现多个分区的幂等性。
其次,它只能实现单会话上的幂等性,不能实现跨会话的幂等性。
事务型 Producer:
Kafka 自 0.11 版本开始也提供了对事务的支持,目前主要是在 read committed 隔离级别上做事情。它能保证多条消息原子性地写入到目标分区,同时也能保证 Consumer 只能看到事务成功提交的消息。
15 | 消费者组到底是什么?
Consumer Group 是 Kafka 提供的可扩展且具有容错性的消费者机制。
Consumer Group 下所有实例订阅的主题的单个分区,只能分配给组内的某个 Consumer 实例消费。这个分区当然也可以被其他的 Group 消费。
Kafka 仅仅使用Consumer Group 这一种机制,却同时实现了传统消息引擎系统的两大模型:如果所有实例都属于同一个 Group,那么它实现的就是消息队列模型;如果所有实例分别属于不同的 Group,那么它实现的就是发布 / 订阅模型。
Rebalance 本质上是一种协议,规定了一个 ConsumerGroup 下的所有 Consumer 如何达成一致,来分配订阅Topic 的每个分区。
即两个独立consumer可以订阅并消费相同的分区
16 | 揭开神秘的“位移主题”面纱
__consumer_offsets是内部主题
将 Consumer 的位移数据作为一条条普通的 Kafka 消息,提交到 __consumer_offsets 中。可以这么说,__consumer_offsets 的主要作用是保存 Kafka 消费者的位移信息。
位移主题的 Key 中应该保存 3 部分内容:<GroupID,主题名,分区号 >
17 | 消费者组重平衡能避免吗?
所谓协调者,在 Kafka 中对应的术语是 Coordinator,它专门为 Consumer Group 服务,负责为 Group 执行Rebalance 以及提供位移管理和组成员管理等。
目前,Kafka 为某个 Consumer Group 确定 Coordinator 所在的 Broker 的算法有 2 个步骤。
第 1 步:确定由位移主题的哪个分区来保存该 Group 数据:partitionId=Math.abs(groupId.hashCode() % offsetsTopicPartitionCount)。
第 2 步:找出该分区 Leader 副本所在的 Broker,该 Broker 即为对应的 Coordinator。
所有Broker 都有各自的 Coordinator 组件
第一类非必要 Rebalance 是因为未能及时发送心跳,导致 Consumer 被“踢出”Group而引发的。因此,你需要仔细地设置session.timeout.ms 和 heartbeat.interval.ms的值。
第二类非必要 Rebalance 是 Consumer 消费时间过长导致的。
18 | Kafka中位移提交那些事儿
Consumer 的消费位移,它记录了Consumer 要消费的下一条消息的位移
即Consumer 需要为分配给它的每个分区提交各自的位移数据。
提交位移主要是为了表征 Consumer 的消费进度,这样当 Consumer 发生故障重启之后,就能够从 Kafka 中读取之前提交的位移值,然后从相应的位移处继续消费,从而避免整个消费过程重来一遍。
从顺序上来说,poll 方法的逻辑是先提交上一批消息的位移,再
处理下一批消息,因此它能保证不出现消费丢失的情况。但自动提交位移的一个问题在于,它可能会出现重复消费。
推荐你使用手动提交机制,因为它更加可控,也更加灵活。另外,建议你同时采用同步提交和异步提交两种方式,这样既不影响 TPS,又支持自动重试,改善 Consumer 应用的高可用性。
19 | CommitFailedException异常怎么处理?
所谓 CommitFailedException,顾名思义就是 Consumer 客户端在提交位移时出现了错误或异常,而且还是那种不可恢复的严重异常。
20 | 多线程开发消费者实例
所谓用户主线程,就是你启动 Consumer 应用程序 main 方法的那个线程,而新引入的心跳线程(Heartbeat Thread)只负责定期给对应的 Broker 机器发送心跳请求,以标识消费者应用的存活性(liveness)。
21 | Java 消费者是如何管理TCP连接的?
TCP 连接是在调用 KafkaConsumer.poll 方法时被创建的。
22 | 消费者组消费进度监控都怎么实现?
所谓滞后程度,就是指消费者当前落后于生产者的程度。
23 | Kafka副本机制详解
Kafka只对已提交消息做持久化保证。如果你设置了最高等级的持久化需求(比如acks=all),那么follower副本没有同步完成前这条消息就不算已提交,也就不算丢失了。
24 | 请求是怎么被处理的?
Acceptor 线程采用轮询的方式将入站请求公平地发到所有网络线程中,因此,在实际使用过程中,这些线程通常都有相同的几率被分配到待处理请求。
当网络线程拿到请求后,它不是自己处理,而是将请求放入到一个共享请求队列中。Broker 端还有个 IO 线程池,负责从该队列中取出请求,执行真正的处理。如果是PRODUCE 生产请求,则将消息写入到底层的磁盘日志中;如果是 FETCH 请求,则从磁盘或页缓存中读取消息。
Kafka 社区把 PRODUCE 和 FETCH 这类请求称为数据类请求,把 LeaderAndIsr、StopReplica 这类请求称为控制类请求。
25 | 消费者组重平衡全流程解析
重平衡流程,它的作用是让组内所有的消费者实例就消费哪些主题分区达成一致。重平衡需要借助 Kafka Broker 端的 Coordinator 组件,在Coordinator 的帮助下完成整个消费者组的分区重分配。
重平衡的通知机制正是通过心跳线程来完成的。当协调者决定开启新一轮重平衡后,它将“REBALANCE_IN_PROGRESS”封装进心跳请求的响应中,发还给消费者实例。当消费者实例发现心跳响应中包含了“REBALANCE_IN_PROGRESS”,就能立马知道重平衡又开始了,这就是重平衡的通知机制。
在该请求中,每个成员都要将自己订阅的主题上报,这样协调者就能收集到所有成员的订阅信息。一旦收集了全部成员的JoinGroup 请求后,协调者会从这些成员中选择一个担任这个消费者组的领导者。
26 | 你一定不能错过的Kafka控制器
控制器组件(Controller),是 Apache Kafka 的核心组件。它的主要作用是在 Apache ZooKeeper 的帮助下管理和协调整个 Kafka 集群。集群中任意一台 Broker 都能充当控制器的角色,但是,在运行过程中,只能有一个 Broker 成为控制器,行使其管理和协调的职责。换句话说,每个正常运转的 Kafka 集群,在任意时刻都有且只有一个控制器。
Broker 在启动时,会尝试去 ZooKeeper 中创建 /controller 节点。Kafka 当前选举控制器的规则是:第一个成功创建 /controller 节点的 Broker 会被指定为控制器。
故障转移指的是,当运行中的控制器突然宕机或意外终止时,Kafka 能够快速地感知到,并立即启用备用控制器来代替之前失败的控制器。
27 | 关于高水位和Leader Epoch的讨论
定义:在时刻 T,任意创建时间(Event Time)为 T’,且 T’≤T 的所有事件都已经到达或被观测到,那么 T 就被定义为水位。
今天我也会统一使用“高水位”或它的缩写 HW 来进行讨论。值得注意的是,Kafka 中也有低水位(Low Watermark),它是与 Kafka 删除消息相关联的概念。
在 Kafka 中,高水位的作用主要有 2 个。
1.定义消息可见性,即用来标识分区下的哪些消息是可以被消费者消费的。
2.帮助 Kafka 完成副本同步。
还有一个日志末端位移的概念,即 Log End Offset,简写是 LEO。
故事讲到这里似乎很完美,依托于高水位,Kafka 既界定了消息的对外可见性,又实现了异步的副本同步机制。
资料
- 为什么kafka不支持主从分离?
- 什么是流式计算?
- failover
- Kafka常见问题
- kafka中的ISR、AR又代表什么?ISR伸缩又是什么?
- (04)kafka多机多Broker(集群)的基本配置
- kafka多个消费者消费一个topic
- 怎么理解 Kafka 消费者与消费组之间的关系?
- Kafka官网
- Kafka中文社区
- Kafka消息是采用Pull模式,还是Push模式?
- Kafka RocketMQ 是推还是拉?
问题
- leader分区坏了怎么办? - 选举
- 搭建一套系统、讲述结构是怎样的、实现一个实时日志收集系统并报警
- kafka,消息写的流程,生产者、消费者、消息之间、broker、topic之间的关系
- 一个topic,可以让多个消费者消费吗?
- 整个流程 启动建立控制器 建、写(写到哪个分区)、不丢失、连、落、压缩、同步(副本)、读、连、不丢失、提交 重平衡、选举
- 消费者与消费者组有什么区别
- 消息集合和消息是啥关系,集合是什么时候用的?