Kafka原理分析

在基础篇中我们介绍MQ的一些基础原理:这篇文章,我们针对kafka进行较深入的分析:

上篇文章中我们提到了kafka中一个名词broker,其实broker可以理解成为一台kafa服务器。

kafka的特性和功能:

在kafka设计之初是为了实时计算大数据量的场景:例如:

  • 运营活动场景:记录用户的浏览、搜索、点击、活跃度等行为。
  • 系统运维场景:监控服务器的 CPU、内存、请求耗时等性能指标。

 Kafka 从 0.8 版本开始,就已经在提供一些和数据处理有关的组件了,比如:

1、Kafka Streams:一个轻量化的流计算库,性质类似于 Spark、Flink。

2、Kafka Connect:一个数据同步工具,能将 Kafka 中的数据导入到关系数据库、Hadoop、搜索引擎中。

Kafka 的官网介绍提到的 3 种能力,也不难理解了:

1、数据的发布和订阅能力(消息队列)

2、数据的分布式存储能力(存储系统)

3、数据的实时处理能力(流处理引擎)

这样kafka的一些功能就比较清晰了。

kafka的消息模型:

我们尝试分析下 Kafka 的消息模型,看看它究竟是如何演化来的?

首先,为了将一份消息数据分发给多个消费者,并且每个消费者都能收到全量的消息,很自然的想到了广播。

一个生产者生产消息并发送到消息队列,由多个消费者消费队列中的消息。消息被消费后,被删除。

 针对广播的消息模型:如果遇到这样的场景、

比如说消息队列中有6条信息:

消费者1只想消费第1.3.5信息。消费者2只想消费2.4.6消息、

此时,MQ 想到了一个很聪明的办法:它将难题直接抛给了生产者,要求生产者在发送消息时,对消息进行逻辑上的分类,因此就演进出了我们熟知的 Topic 以及发布-订阅模型。

为了降低MQ的设计复杂度。Kafka引入topic的概念。

主要的目标:就是为了解决不同消费者消费不同消息类型的场景:

kafka引入topic(主题):由生产者将不同的消息进行分类:类型不同的消息,存放在不同的topic中。这样消费者就可以针对不同的消息类型,去消费不同topic数据。

假如现在又有了如下的应用场景:

针对上述设计方案:如果针对同一个消息类型即同一个Topic,有多个消费者需要去消费他:

此时如果利用单纯的单播模式,肯定满足不了要求:

有同学就会想到这种场景,复制同样的一个队列给消费者消费:这样设计有一个问题是随着消费者的数据增多,必然会引起队列的性能问题,kafka本身就是为了解决高并发的。显然这种设计不适合kafka的设计:此时kafka就想到了一个聪明的解决方案:

它将所有消息进行了持久化存储,由消费者自己各取所需,想取哪个消息,想什么时候取都行,只需要传递一个消息的 offset 即可。

这样消息就不会被删除。而是被持久化的存储。这也是为什么官方会将 Kakfa 同时定义成存储系统的原因。

从上面的信息我们可以得到的总结是:

  • Kafka 为实时日志流而生,要处理的并发和数据量非常大。可见,Kafka 本身就是一个高并发系统,它必然会遇到高并发场景下典型的三高挑战:高性能、高可用和高扩展
  • 为了简化实现的复杂度,Kafka 最终采用了很巧妙的消息模型:它将所有消息进行了持久化存储,让消费者自己各取所需,想取哪个消息,想什么时候取都行,只需要传递一个消息的 offset 进行拉取即可。

kafka的存储方案

  上面我们已经分析到为了解决多个消费者消费同一个Topic的问题、kafka设计成为存储系统。

那么接下来我们分析下kafka的存储方案。

面对海量数据,单机的存储容量和读写性能肯定有限,大家很容易想到一种存储方案:对数据进行分片存储这种方案在我们实际工作中也非常常见:

kafka为了解决存储的压力:也因此引入了Partition的概念:将数据进行物理分片。

其实partition是针对不同的topic进行细分。将topic的海量数据。均匀地分布在集群中的每台机器上,从而很好地解决了存储的扩展性问题。这里的均匀分布指的是同一个topic在MQ的集群中每台服务器中只会存在一个分区。

Partition便是kafka的最小部署单元、

  • Partition 是存储的关键所在,MQ「一发一存一消费」的核心流程必然围绕它展开。
  • Kafka 高并发设计中最难的三高问题都能和 Partition 关联起来。

那我们再看看消费端,它又是如何跟 Partition 结合并做到并行处理的?

从消费者来看,首先要满足两个基本诉求:

1、广播消费能力:同一个 Topic 可以被多个消费者订阅,一条消息能够被消费多次。

2、集群消费能力:当消费者本身也是集群时,每一条消息只能分发给集群中的一个消费者进行处理。

 为了满足这两点要求,Kafka 引出了消费组的概念,每个消费者都有一个对应的消费组,组间进行广播消费,组内进行集群消费。此外,Kafka 还限定了:每个 Partition 只能由消费组中的一个消费者进行消费。

如果要加快消息的处理速度,该如何做呢?也很简单,向消费组 2 中增加新的消费者即可,Kafka 将以 Partition 为单位重新做负载均衡。当增加到 4 个消费者时,每个消费者仅需处理 1 个 Partition,处理速度将提升两倍。

在 Kafka 集群中,每台机器都存储了一些 Partition,一旦某台机器宕机,上面的数据不就丢失了吗?

此时,你一定会想到对消息进行持久化存储,但是持久化只能解决一部分问题,它只能确保机器重启后,历史数据不丢失。但在机器恢复之前,这部分数据将一直无法访问。这对于高并发系统来说,是无法忍受的。

所以 Kafka 必须具备故障转移能力才行,当某台机器宕机后仍然能保证服务可用。

没错,Kafka 正是通过 Partition 的多副本机制解决了高可用问题。在 Kafka 集群中,每个 Partition 都有多个副本,同一分区的不同副本中保存的是相同的消息。

副本之间是 “一主多从” 的关系,其中 leader 副本负责读写请求,follower 副本只负责和 leader 副本同步消息,当 leader 副本发生故障时,它才有机会被选举成新的 leader 副本并对外提供服务,否则一直是待命状态。

现在,我假设 Kafka 集群中有 4 台服务器,主题 A 和主题 B 都有两个 Partition,且每个 Partition 各有两个副本,那最终的多副本架构将如下图所示:

  • Producer:生产者,负责创建消息,然后投递到 Kafka 集群中,投递时需要指定消息所属的 Topic,同时确定好发往哪个 Partition。
  • Consumer:消费者,会根据它所订阅的 Topic 以及所属的消费组,决定从哪些 Partition 中拉取消息。
  • Broker:消息服务器,可水平扩展,负责分区管理、消息的持久化、故障自动转移等。
  • Zookeeper:负责集群的元数据管理等功能,比如集群中有哪些 broker 节点以及 Topic,每个 Topic 又有哪些 Partition 等。

很显然,在 Kafka 整体架构中,Partition 是发送消息、存储消息、消费消息的纽带。吃透了它,再去理解整体架构,脉络会更加清晰。

总结上述:

  • Kafka 通过巧妙的模型设计,将自己退化成一个海量消息的存储系统。
  • 为了解决存储的扩展性问题,Kafka 对数据进行了水平拆分,引出了 Partition(分区),这是 Kafka 部署的基本单元,同时也是 Kafka 并发处理的最小粒度。
  • 对于一个高并发系统来说,还需要做到高可用,Kafka 通过 Partition 的多副本冗余机制进行故障转移,确保了高可靠。

Kafa副本同步机制:

Kafka每个topic的partition有N个副本,其中N是topic的复制因子。Kafka通过多副本机制实现故障自动转移,当Kafka集群中一个Broker失效情况下仍然保证服务可用。在Kafka中发生复制时确保partition的预写式日志有序地写到其他节点上。N个replicas中。其中一个replica为leader,其他都为follower,leader处理partition的所有读写请求,与此同时,follower会被动定期地去复制leader上的数据。


Kafka必须提供数据复制算法保证,如果leader发生故障或挂掉,一个新leader被选举并接收客户端的消息成功写入。Kafka确保从同步副本列表中选举一个副本为leader,或者换句话说,follower追赶leader数据。leader负责维护和跟踪ISR中所有follower滞后状态。当生产者发送一条消息到Broker,leader写入消息并复制到所有follower。消息提交之后才被成功复制到所有的同步副本。消息复制延迟受最慢的follower限制,重要的是快速检测慢副本,如果follower”落后”太多或者失效,leader将会把它从replicas从ISR移除。

是什么原因导致分区的副本与leader不同步


一个副本可以不同步Leader有如下几个原因
慢副本:在一定周期时间内follower不能追赶上leader。最常见的原因之一是I / O瓶颈导致follower追加复制消息速度慢于从leader拉取速度。
卡住副本:在一定周期时间内follower停止从leader拉取请求。follower replica卡住了是由于GC暂停或follower失效或死亡。
新启动副本:当用户给主题增加副本因子时,新的follower不在同步副本列表中,直到他们完全赶上了leader日志。
一个partition的follower落后于leader足够多时,被认为不在同步副本列表或处于滞后状态。在Kafka-0.8.2.x中,副本滞后判断依据是副本落后于leader最大消息数量(replica.lag.max.messages)或replicas响应partition leader的最长等待时间(replica.lag.time.max.ms)。前者是用来检测缓慢的副本,而后者是用来检测失效或死亡的副本


副本配置规则


笔者认为真正重要的事情是检测卡或慢副本,这段时间follower replica是“out-of-sync”落后于leader。在服务端现在只有一个参数需要配置replica.lag.time.max.ms。这个参数解释replicas响应partition leader的最长等待时间。检测卡住或失败副本的探测——如果一个replica失败导致发送拉取请求时间间隔超过replica.lag.time.max.ms。Kafka会认为此replica已经死亡会从同步副本列表从移除。检测慢副本机制发生了变化——如果一个replica开始落后leader超过replica.lag.time.max.ms。Kafka会认为太缓慢并且会从同步副本列表中移除。除非replica请求leader时间间隔大于replica.lag.time.max.ms,因此即使leader使流量激增和大批量写消息。Kafka也不会从同步副本列表从移除该副本。
 

参考文章:大佬的文章图文解释:

《吃透 MQ 系列》之扒开 Kafka 的神秘面纱

《吃透 MQ 系列》之 Kafka 架构设计的任督二脉

《吃透 MQ 系列》之 Kafka 存储选型的奥秘

 https://blog.csdn.net/lizhitao/article/details/51718185

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值