
Kafak 核心原理
文章平均质量分 91
本位于 Kafka 核心原理实现的讲解,需要读者对 Kafka 有一定深度的认知,Kafka 小白慎入。
如果读者是学习完《Kafka实战基础》之后而来的,那么基本上可以很顺畅的对本专刊进行解读。
程序员山子
坚持着,总有一天你会站在最亮的地方活出自己曾经渴望的模样
展开
-
消息中间件选型分析(二十一)
消息中间件选型分析 消息中间件的选型是很多个人乃至公司都会面临的一个问题。 目前开源的消息中间件有很多,比如 ActiveMQ、RabbitMQ、Kafka、RocketMQ、ZeroMQ等。不管选择其中的哪一款,都会有用得不顺手的地方,毕竟不是为你量身定制的。有些“大厂”在长期的使用过程中积累了一定的经验,消息队列的使用场景也相对稳定固化,由于某种原因(比如目前市面上的消息中间件无法全部满足自身需求),并且它也具备足够的财力和人力而选择自研一款量身打造的消息中间件。但绝大多数公司还是选择不...原创 2022-01-04 08:48:30 · 523 阅读 · 0 评论 -
其他拓展应用(二十)
死信队列和重试队列 由于某些原因消息无法被正确地投递,为了确保消息不会被无故地丢弃,一般将其置于一个特殊角色的队列,这个队列一般称为死信队列。后续分析程序可以通过消费这个死信队列中的内容来分析当时遇到的异常情况,进而可以改善和优化系统。 与死信队列对应的还有一个“回退队列”的概念,如果消费者在消费时发生了异常,那么就不会对这一次消费进行确认,进而发生回滚消息的操作之后,消息始终会放在队列的顶部,然后不断被处理和回滚,导致队列陷入死循环。为了解决这个问题,可以为每个队列设置一个回...原创 2021-12-31 08:58:01 · 229 阅读 · 0 评论 -
延时队列(十九)
延时队列 队列是存储消息的载体,延时队列存储的对象是延时消息。所谓的“延时消息”是指消息被发送以后,并不想让消费者立刻获取,而是等待特定的时间后,消费者才能获取这个消息进行消费,延时队列一般也被称为“延迟队列”。注意延时与 TTL 的区别,延时的消息达到目标延时时间后才能被消费,而 TTL 的消息达到目标超时时间后会被丢弃。延时队列的使用场景有很多,比如:在订单系统中,一个用户下单之后通常有30分钟的时间进行支付,如果30分钟之内没有支付成功,那么这个订单将进行异常处理,这时就可以使用...原创 2021-12-31 08:53:46 · 1811 阅读 · 0 评论 -
过期时间(十八)
除了正常的消息发送和消费,在使用 Kafka 的过程中难免会遇到一些其他高级应用类的需求,比如消费回溯,这个可以通过原生 Kafka 提供的 KafkaConsumer.seek() 方法来实现,然而类似延时队列、消息轨迹等应用需求在原生 Kafka 中就没有提供了。我们在使用其他消息中间件时,比如 RabbitMQ,使用到了延时队列、消息轨迹的功能,如果我们将应用直接切换到 Kafka 中,那么只能选择舍弃它们。但这也不是绝对的,我们可以通过一定的手段来扩展 Kafka,从本节开始讲述的就...原创 2021-12-30 08:51:51 · 1275 阅读 · 0 评论 -
可靠性分析(十七)
日志同步机制 在分布式系统中,日志同步机制既要保证数据的一致性,也要保证数据的顺序性。虽然有许多方式可以实现这些功能,但最简单高效的方式还是从集群中选出一个 leader 来负责处理数据写入的顺序性。只要 leader 还处于存活状态,那么 follower 只需按照 leader 中的写入顺序来进行同步即可。 通常情况下,只要 leader 不宕机我们就不需要关心 follower 的同步问题。不过当 leader 宕机时,我们就要从 follower 中选举出一个新的 le...原创 2021-12-30 08:49:32 · 2434 阅读 · 0 评论 -
副本剖析(下)(十六)
Leader Epoch的介入 上一节的内容所陈述的都是在正常情况下的 leader 副本与 follower 副本之间的同步过程,如果 leader 副本发生切换,那么同步过程又该如何处理呢?在 0.11.0.0 版本之前,Kafka 使用的是基于 HW 的同步机制,但这样有可能出现数据丢失或 leader 副本和 follower 副本数据不一致的问题。 首先我们来看一下数据丢失的问题,如上图所示,Replica B 是当前的 leader 副本(用 L...原创 2021-12-29 09:12:57 · 253 阅读 · 0 评论 -
副本剖析(上)(十五)
Kafka 中采用了多副本的机制,这是大多数分布式系统中惯用的手法,以此来实现水平扩展、提供容灾能力、提升可用性和可靠性等。我们对此可以引申出一系列的疑问:Kafka 多副本之间如何进行数据同步,尤其是在发生异常时候的处理机制又是什么?多副本间的数据一致性如何解决,基于的一致性协议又是什么?如何确保 Kafka 的可靠性?Kafka 中的可靠性和可用性之间的关系又如何? 本节开始从副本的角度切入来深挖 Kafka 中的数据一致性、数据可靠性等问题,主要包括副本剖析、日志同步机...原创 2021-12-29 09:02:24 · 578 阅读 · 0 评论 -
事务(十四)
消息传输保障一般而言,消息中间件的消息传输保障有3个层级,分别如下。at most once:至多一次。消息可能会丢失,但绝对不会重复传输。 at least once:最少一次。消息绝不会丢失,但可能会重复传输。 exactly once:恰好一次。每条消息肯定会被传输一次且仅传输一次。Kafka 的消息传输保障机制非常直观。当生产者向 Kafka 发送消息时,一旦消息被成功提交到日志文件,由于多副本机制的存在,这条消息就不会丢失。如果生产者发送消息到 Kafka 之后,遇到了网络问题而造成原创 2021-12-28 08:44:36 · 796 阅读 · 0 评论 -
consumer_offsets深度剖析(十三)
consumer_offsets深度剖析 位移提交是使用消费者客户端过程中一个比较“讲究”的操作。位移提交的内容最终会保存到 Kafka 的内部主题 __consumer_offsets 中,对于主题 __consumer_offsets 的深度掌握也可以让我们更好地理解和使用好位移提交。 一般情况下,当集群中第一次有消费者消费消息时会自动创建主题 __consumer_offsets,不过它的副本因子还受 offsets.topic.replication.factor 参数...原创 2021-12-26 16:58:54 · 1190 阅读 · 0 评论 -
消费者协调器和组协调器(十二)
消费者协调器和组协调器 了解了 Kafka 中消费者的分区分配策略之后是否会有这样的疑问:如果消费者客户端中配置了两个分配策略,那么以哪个为准呢?如果有多个消费者,彼此所配置的分配策略并不完全相同,那么以哪个为准?多个消费者之间的分区分配是需要协同的,那么这个协同的过程又是怎样的呢?这一切都是交由消费者协调器(ConsumerCoordinator)和组协调器(GroupCoordinator)来完成的,它们之间使用一套组协调协议进行交互。旧版消费者客户端的问题 消费者协调...原创 2021-12-26 16:55:39 · 976 阅读 · 0 评论 -
消费端分区分配策略(十一)
消费端分区分配策略 Kafka 提供了消费者客户端参数 partition.assignment.strategy 来设置消费者与订阅主题之间的分区分配策略。默认情况下,此参数的值为 org.apache.kafka.clients.consumer.RangeAssignor,即采用 RangeAssignor 分配策略。除此之外,Kafka 还提供了另外两种分配策略:RoundRobinAssignor 和 StickyAssignor。消费者客户端参数 partition.assig...原创 2021-12-24 09:03:27 · 1591 阅读 · 0 评论 -
服务端参数解密(十)
服务端参数解密 如果 broker 端没有显式配置 listeners(或 advertised.listeners)使用 IP 地址,那么最好将 bootstrap.server 配置成主机名而不要使用 IP 地址,因为 Kafka 内部使用的是全称域名(Fully Qualified Domain Name)。如果不统一,则会出现无法获取元数据的异常。broker.id broker.id 是 broker 在启动之前必须设定的参数之一,在 Kafka 集群中,每个 ...原创 2021-12-24 08:58:57 · 1520 阅读 · 0 评论 -
控制器(九)
控制器 在 Kafka 集群中会有一个或多个 broker,其中有一个 broker 会被选举为控制器(Kafka Controller),它负责管理整个集群中所有分区和副本的状态。当某个分区的 leader 副本出现故障时,由控制器负责为该分区选举新的 leader 副本。当检测到某个分区的 ISR 集合发生变化时,由控制器负责通知所有broker更新其元数据信息。当使用 kafka-topics.sh 脚本为某个 topic 增加分区数量时,同样还是由控制器负责分区的重新分配。控...原创 2021-12-23 08:48:48 · 570 阅读 · 0 评论 -
磁盘存储(五)
磁盘存储 Kafka 依赖于文件系统(更底层地来说就是磁盘)来存储和缓存消息。在我们的印象中,对于各个存储介质的速度认知大体同下图所示的相同,层级越高代表速度越快。很显然,磁盘处于一个比较尴尬的位置,这不禁让我们怀疑 Kafka 采用这种持久化形式能否提供有竞争力的性能。在传统的消息中间件 RabbitMQ 中,就使用内存作为默认的存储介质,而磁盘作为备选介质,以此实现高吞吐和低延迟的特性。然而,事实上磁盘可以比我们预想的要快,也可能比我们预想的要慢,这完全取决于我们如何使用它。...原创 2021-12-22 08:43:30 · 281 阅读 · 0 评论 -
时间轮(七)
时间轮 Kafka 中存在大量的延时操作,比如延时生产、延时拉取和延时删除等。Kafka 并没有使用 JDK 自带的 Timer 或 DelayQueue 来实现延时的功能,而是基于时间轮的概念自定义实现了一个用于延时功能的定时器(SystemTimer)。JDK 中 Timer 和 DelayQueue 的插入和删除操作的平均时间复杂度为 O(nlogn) 并不能满足 Kafka 的高性能要求,而基于时间轮可以将插入和删除操作的时间复杂度都降为 O(1)。时间轮的应用并非 Kafka 独有...原创 2021-12-22 08:36:20 · 530 阅读 · 0 评论 -
协议设计(六)
协议设计 在实际应用中,Kafka 经常被用作高性能、可扩展的消息中间件。Kafka 自定义了一组基于 TCP 的二进制协议,只要遵守这组协议的格式,就可以向 Kafka 发送消息,也可以从 Kafka 中拉取消息,或者做一些其他的事情,比如提交消费位移等。 在目前的 Kafka 2.0.0 中,一共包含了43种协议类型,每种协议类型都有对应的请求(Request)和响应(Response),它们都遵守特定的协议模式。每种类型的 Request 都包含相同结构的协议请求头(R...原创 2021-12-21 08:51:37 · 884 阅读 · 0 评论 -
日志清理(四)
日志清理Kafka 将消息存储在磁盘中,为了控制磁盘占用空间的不断增加就需要对消息做一定的清理操作。Kafka 中每一个分区副本都对应一个 Log,而 Log 又可以分为多个日志分段,这样也便于日志的清理操作。Kafka 提供了两种日志清理策略:日志删除(Log Retention):按照一定的保留策略直接删除不符合条件的日志分段。 日志压缩(Log Compaction):针对每个消息的 key 进行整合,对于有相同 key 的不同 value 值,只保留最后一个版本。我们可以通过 broke原创 2021-12-20 08:37:07 · 1585 阅读 · 0 评论 -
日志索引(三)
日志索引 前面章节就提及了每个日志分段文件对应了两个索引文件,主要用来提高查找消息的效率。偏移量索引文件用来建立消息偏移量(offset)到物理地址之间的映射关系,方便快速定位消息所在的物理文件位置;时间戳索引文件则根据指定的时间戳(timestamp)来查找对应的偏移量信息。 Kafka 中的索引文件以稀疏索引(sparse index)的方式构造消息的索引,它并不保证每个消息在索引文件中都有对应的索引项。每当写入一定量(由 broker 端参数 log.index.inte...原创 2021-12-18 09:54:06 · 396 阅读 · 0 评论 -
日志格式的演变(二)
日志格式的演变 对一个成熟的消息中间件而言,消息格式(或者称为“日志格式”)不仅关系功能维度的扩展,还牵涉性能维度的优化。随着 Kafka 的迅猛发展,其消息格式也在不断升级改进,从0.8.x版本开始到现在的2.0.0版本,Kafka 的消息格式也经历了3个版本:v0 版本、v1 版本和v2 版本。 每个分区由内部的每一条消息组成,如果消息格式设计得不够精炼,那么其功能和性能都会大打折扣。比如有冗余字段,势必会不必要地增加分区的占用空间,进而不仅使存储的开销变大、网络传输的开销变...原创 2021-12-17 09:09:03 · 736 阅读 · 0 评论 -
开篇暨日志存储(一)
在学习完Kafka实战基础之后,基本上来说,我们可以较好地使用 Kafka 来完成基本的开发任务了。不过,如果能够了解Kafka内部的一些细节,则可以让我们扬其长、避其短,进而可以更好地利用 Kafka。 我们不妨先从 Kafka 日志存储相关的知识点开始入手。我们知道 Kafka 中的消息是存储在磁盘上的,那么为什么要使用磁盘作为存储介质?具体消息的存储格式又是什么呢?怎么样能够快速检索到指定的消息?消息不可能无限制存储,那么清理规则又是什么呢?带着这些疑问,我们来一探究竟...原创 2021-12-17 09:03:24 · 481 阅读 · 0 评论