摘要

上一讲解我们讲解了kafka的具备的一些特点:相比于传统的消息队列来说,kafka可以做到分布式存储,具备高可用,高性能的特点,我们这一讲主要讲解:Kafka实现高性能、高可用、分布式存储的的基本原理。主线主要从吞吐量到延时引出kafka是高吞吐量、低延时的架构;根据这个高吞吐量低延时原理从而引出kafka如果实现单机几十万并发数据写入、以及如何实现高性能数据读取;然后如何将写入的数据进行极致压缩利用磁盘效率,进而在数据写入读取,以及数据存取方式都知道的情况下,kafka如何实现分布式存储、分布式负载均衡;分布式数据存储已经做完之后,怎样保证存储的数据实现高可用,然后如何保证存储进去的数据不会丢失;这些都讲解完毕之后;最后讲解下kafka架构里面的服务弹性伸缩以及节点新发现跟故障感知。从简到繁,一步一步层层递进。

思维导图

image.png

内容

1、吞吐量跟延时

1、吞吐量跟延时

由于kafka是高吞吐量跟低延时的架构,所以在讲解kafka时候需要先了解吞吐量跟延时概念。

假如处理完一条数据需要1毫秒,并且一条数据的大小是1kb;那么1秒中就可以处理1000条数据,1000kb数据大小;上面场景中吞吐量就是:1000条、1000kb;

吞吐量:单位时间内处理数据大小。
延时:Kafka一次请求接收消息到消息处理完成所消耗的时间。

2、Spark Streaming要采取微批处理技术实现流式计算

与kafka类似的Spark大数据框架,为什么需要使用微批处理技术实现流式计算?

假如我们处理完一条数据需要1毫秒,那么我们的延时是:1ms 系统的吞吐量是:1000条数据。

我们采用微批处理机制,先花9毫秒收集完1000条数据,然后通过1毫秒进行数据流式计算,那么本次一起数据请求执行完毕的延时10毫秒 吞吐量是10万条数据。吞吐量量提高了100倍,延时增加了10倍。

因为处理1条或者1000条数据耗时相等,为了节省每条数据都需要启动新的计算资源:网络开销或者磁盘开销比如处理1条数据需要1毫秒,吞吐量是:1000条数据/s;如果9毫秒收集1000条数据,然后1毫秒处理数据,那么系统吞吐量10万条;系统吞吐量增大了100倍数,但是延时增加了10倍。

其实也类似于我们对数据库进行多条数据插入时候,使用批量插入而不是一次插入一条;主要是节约新资源的网络开销。

3、与Spark Streaming高吞吐量高延时不一样,Kafka如何实现高吞吐量低延时?

kafka实现高吞吐量低延时主要是基于kafka的数据写入机制跟数据读取机制。在下面讲解。

image.png

2、Kafka如何实现单机几十万并发写入

前面讲解了Spark Streaming技术是使用:batch微批处理,实现高吞吐高延迟。但是kafka相反,高吞吐低延迟。

常见消息队列rabbitmq如何写入数据?
常见的消息队列数据数据是直接将数据写入到内存,然后将内存里面的数据再写入到磁盘,这样的花就会耗用机器更多的内存,如果是基于JVM机制的还需要分配更多的对内存空间保证数据写入高效。

image.png

kafka数据写入
os cache+磁盘顺序写:kafka数据写入是直接写磁盘;写磁盘的时候 实先写入到page cache;page cache是基于os cache。并且数据写入磁盘的时候是磁盘顺序写的。逻辑架构图如下:

image.png

3、kafka如何实现高效数据读取

kafka基于:零拷贝+页缓存技术

不使用零拷贝技术读取数据:
image.png

consumer端消费数据时候,先是经过Kafka应用从os cache里面读取数据,如果有数据直接返回到操作系统的网卡通过socket将数据发送给consumer系统,如果os cache里面没有数据的花,从磁盘里面读取数据到os cache然后到操作系统网卡上通过socket返回给consumer,中间牵涉到kafka Broker跟os操作系统的上下文切换。

使用零拷贝技术读取数据:
image.png
使用零拷贝技术,就是linux的sendfile,就可以直接把操作交给os,os看page cache里是否有数据,如果没有就从磁盘上读取,如果有的话直接把os cache里的数据拷贝给网卡了,中间不用走那么多步骤了,省略读取数据到kafka broker里面。

4、底层数据存储结构

底层数据存储结构

kafka底层数据存储是以partition日志文件存储,写入的每一个数据都有一个序号:offset代表了这个消息在日志文件partition里面的位置

Kafka如何设计消息格式节省磁盘开销?

kafka通过NIO的ByteBuffer将消息以二进制形式存储到partition日志中,二进制形式比java对象要节约近40%的空间。消息大小通过offset标示,消息内容是一个log entry:消息总长度、时间戳增量、offset增量、key长度、key、value长度、value、header个数、header。
image.png

5、如何保证TB数据分布式存储

假如一个Topic的数据大小为TB级别,不可能将TB级别数据存储到一台Kafka Broker机器上,kafka将一个逻辑上的Topic数据 拆分成多个分区partition,不同的分区部署到不同的机器上。从而实现分布式数据存储。

一个Topic你可以认为是逻辑上的数据集合。

每个topic都有很多个partition,你认为是数据分区,或者是数据分片,就是说这个topic假设有10TB的数据量需要存储在磁盘上,此时你给他分配了5个partition,那么每个partition都可以存放2TB的数据。如下图将topic数据写入到不同的partition机器上,消费数据时候根据主题从不同partition上消费数据。
image.png

6、如何保证kafka的高可用

如上图所示:每台机器上都保留了一个partition;但是这里就有一个问题了,如果Kafka某台机器宕机了,那么一个topic就丢失了一个partition的数据,此时不就导致数据丢失了吗?所以对数据做多副本冗余,也就是每个parttion都有副本。

比如最基本的就是每个partition做一个副本,副本放在另外一台机器上

然后呢kafka自动从一个partition的多个副本中选举出来一个leader partition,这个leader partition就负责对外提供这个partiton的数据读写,接收到写过来的数据,就可以把数据复制到副本partition上去

这个时候如果说某台机器宕机了,上面的leader partition没了,此时怎么办呢?通过zookeeper来维持跟每个kafka的会话,如果一个kafka进程宕机了,此时kafka集群就会重新选举一个leader partition,就是用他的某个副本partition即可

通过副本partition可以继续体统这个partition的数据写入和读取,这样就可以实现容错了,这个副本partition的专业术语叫做follower partition,所以每个partitino都有多个副本,其中一个是leader,是选举出来的,其他的都是follower partition

多副本冗余的机制,就可以实现Kafka高可用架构。如下所示:
image.png

7、如何保证kafka写入数据不丢失

1.Replica
kafka的broker端每个partition都会有多个副本(replica),至少有一个leader领导者副本以及多个follower追随者副本(可配置),分区接收消息以及消费消息都会在leader中进行,而follower副本的作用就是备份leader中的消息,它们会定时的从leader中拉取最新数据,从而尽可能的保证和leader的同步。

2.什么是ISR?
分区中的所有副本统称为AR(Assigned Replicas)。所有与leader副本保持一定程度同步的副本(包括leader)组成ISR(in-sync replicas)。而与leader副本同步滞后过多的副本(不包括leader),组成OSR(out-sync replicas),所以,AR = ISR + OSR。在正常情况下,所有的follower副本都应该与leader副本保持一定程度的同步,即AR = ISR,OSR集合为空。

leader副本负责维护和跟踪ISR中所有follower的滞后状态,当follower落后太多或者长时间没有向leader发起同步请求,leader副本就会认为它出问题了,会把它从ISR中移除,这时候这个follower就会放入OSR集合中,直到某个时候这个follower同步跟上了leader,然后这个副本又会被加入到ISR中。此外,当leader副本挂了,只有ISR中的follower副本才有资格成为leader,OSR中的则没有资格。(可以通过修改对应的参数配置)。

3、kafka何时扩充ISR?
随着follower副本不断进行消息同步,follower副本LEO也会逐渐后移,并且最终赶上leader副本,这个时候follower副本就有资格进入ISR集合,判断是否追上leader副本的判定准则是这个副本的LEO是否小于leader副本HW,并不是和leader副本LEO相比。ISR扩充后会同样更新zookeeper和isrChangeSet,之后的步骤就和ISR收缩的时候相同。

多冗余副本机制是否可以保证数据不丢失了?比如2台kafka broker机器,2个分区,每个分区一个副本 假如数据写入到一台机器的partition里面去后,就认为写入成功的话,等待此partition数据同步到其对应的folower parition上,但是很不巧,在开始同步之前,机器宕机了,然后partition对应的follower partition成为你leader partition,消费这消费数据时候将会发小数据丢失。所以多副本冗余机制不能保证数据不丢失,要想保证数据不丢失就需要判断在什么条件下才 认为数据写入成功。

Kafka保证数据不都是采用了ISR列表机制。ISR:In-Sync-Replica数据同步副本follower;满足3个条件:
1、ISR列表构成:leader partition有一个ISR列表,里面至少有一个副本follower;如果一个leader里面的ISR列表里面没有follower的话,是不允许其他应用往Kafka里面写数据的
2、写成功标记:当一条数据写入到leader partition的时候,此数据需要同步给其下ISR列表里面的所有follower partition才算成功
3、leader选举:当leader parition所以broker机器宕机,通过zk进行leader选举时候,只能从ISR列表里面选举新的leader(因其保存了最新的数据)

8、集群数据写入时候如何实现负载均衡效果

集群数据写入时候是针对于某一个业务逻辑的Topic主题,然后数据会写入到Topic对应的partition上实现分布式存储,要实现写入时候负载均衡效果,就是需要将topic的多个分区partition均匀部署在不同的机器上。由于kafka写入读取数据的是操作的leader partition;所以请求会发往leader parition,所以我们需要将kafka的leader partition尽可能地分布在不同的机器上来实现请求负载均衡。

9、kafka无状态的架构如何实现

什么叫做无状态

kafka基本的元数据:topic信息,partition信息,broker信息,ISR列表等信息存储到自己独享的内存,这样的话是有状态的。简言之就是共享数据不应该保存到自己的JVM内存中。

如何实现kafka的无状态伸缩

有状态的kafka在进行架构扩容伸缩的时候,需要在各个JVM进程同步数据,这个将会极度扩容,通过将kafka broker维护的元数据存储在zk中,扩容时候,从zk读取数据实现弹性伸缩。

10、kafka如何实现节点发现跟故障感知

要想实现kafka节点发现以及故障感知需要将所以集群的kafka有一个注册中心,这个注册中心可以提供服务发现,故障感知,并且 跟每一个集群的kafka broker保持心跳连接。其实就是一个注册中心的概念:新加入kafka时候,将其注册到zk上,然后其他kafka就可以实现新节点服务发现;如果某一台kafka宕机,zk将会感知到宕机,然后通知其他kafka进行leader partition选举,从而实现了基于zookeeper:上线、下线、故障感知。

image.png


startshineye
91 声望26 粉丝

我在规定的时间内,做到了我计划的事情;我自己也变得自信了,对于外界的人跟困难也更加从容了,我已经很强大了。可是如果我在规定时间内,我只有3分钟热度,哎,我不行,我就放弃了,那么这个就是我自己的问题,因为你自己...