kafka学习(三):kakfa消息处理、索引、零拷贝

1、Kafka的消息流处理

kafka学习(三):kakfa消息处理、索引、零拷贝_第1张图片

1.1、消息路由

        producer 发送消息到 broker 时,会根据分区算法选择将其存储到哪一个 partition。

其路由机制为:

1. 指定了 patition,则直接使用

2. 未指定 patition 但指定 key,通过对 key 的 value 进行hash 选出一个 patition。

3. patition 和 key 都未指定,使用轮询选出一个 patition

1.2、消息流程:

  1. producer要向kafka生产数据,需要先通过zookeeper获取leader的位置信息。
  2. Producer向leader发送数据。
  3. Leader收到数据后,将数据写入到分区目录下的log文件。
  4. Follower从leader同步数据,将数据写入到分区目录下的log文件中,如果同步成功(将数据写入自己log文件成功),则向leader返回ACK(确认机制)
  5. leader向producer返回ACK

细节补充:

Kafka引入了一个ISR机制(概念):

比如:①副本-follower ②副本-leader ③副本-follower

        在follower和leader数据同步过程中,①②同步,③出现故障没有跟上,此时①②是同一个ISR成员,③不是。只有③恢复后,将数据同步成功,才会加入ISR成员中。

        如果后续leader挂掉了,则kafka会从leader的ISR组中随机选择一个follower作为leader。

        Kafka底层有一个同步超时时间(默认:10s),即一个follower在超时时间内没有反馈ACK,则认为同步失败

补充概念说明:

        ISR 的全称: In-Sync Replicas (同步副本集), 我们可以理解为和 leader 保持同步的所有副本的集合。
        AR :Assigned Repllicas,一个分区的所有副本集合。

        OSR :Out-Sync Relipcas,与 leader-replica 未能保持同步的副本集。

        因此我们就能得到这么一个表示:AR = ISR + OSR,翻译一下就是一个分区的副本集分为同步集合和非同步集合两部分。

 【当所有副本都不工作时,有两种可行的方案】:

        ①等待ISR中的任意一个副本活过来,并选它作为leader。可保证数据不丢失,但时间可能相对较长。

        ②选择第一个活过来的副本(不一定是ISR成员)作为leader。无法保证数据不丢失,但相对不可用时间较短。

        Kafka默认使用的是第②种。

2、Kafka的索引机制

        Kafka为了提高数据的读取效率,引入了索引机制,为分区目录下的log文件创建一个对应的index文件。

         kafka学习(三):kakfa消息处理、索引、零拷贝_第2张图片

        一个log文件对应一个index索引文件,名字一样。

        索引文件中包含若干个索引条目,每个条目表示数据文件中一条message的索引,即message在数据文件中的绝对位置。分析图如下:

kafka学习(三):kakfa消息处理、索引、零拷贝_第3张图片

 

        Kafka的索引并不是为每条数据建立索引,这种索引称为 稀疏索引,因为稀疏索引占用的空间小,所以可以完全将稀疏索引加载到内存中,避免从磁盘上读取索引文件数据,减少磁盘I/O,进一步提高性能。

        Kafka的索引机制可以概括为:稀疏索引 + 加载内存 + 二分查找 

        Kafka的每个log文件默认是1G生成一个新的log文件,比如 新的log文件中第一条消息的offset 16933,则此log文件的命名为:00000000000000016933.log。此外,每生成一个log文件,就会生成一个对应的索引(index)文件。这样在查找指定offset的message的时候,用二分查找 就可以定位到该message在哪个段中。

 3、kafka数据传输的可靠性保障

       数据传输的可靠性保障 共有三种:

  1. at most once 至多一次
  2. at least once 至少一次
  3. exactly once 精确一次

3.1、at most once 至多一次

kafka学习(三):kakfa消息处理、索引、零拷贝_第4张图片

 

如上图所示,在发送数据时,可能由于各种故障或异常,导致没有收到数据,即产生数据丢失。

对应的是 at most once 至多一次语义,即同一条数据至多只发送一次,所以这一层语义可能造成数据传输的丢失,也可以认为是没有可靠性保障的委婉说法。

3.2、at least once 至少一次

kafka学习(三):kakfa消息处理、索引、零拷贝_第5张图片

        为了能确保数据不丢失,我们可以引入ACK确认机制 超时时间,如果在指定的超时时间内没有收到ACK,则认为接收失败,则将数据重新发送。

上图对应的语义:at least once 至少一次, 同一条数据至少发送一次,也可能发送多次,能确保数据不丢失,但可能会造成同一条数据的重复处理(比如在返回ACK时超时了,有这种可能,但在实际生产环境下概率较低)。

3.3、exactly once 精确一次

kafka学习(三):kakfa消息处理、索引、零拷贝_第6张图片

        要想实现精确一次,需要在至少一次语义的基础上来实现,即确保数据不丢失(ACK+超时机制),此外,为数据分配一个全局唯一的id,利用这个id可以实现幂等性操作幂等性操作指的是:代码执行多次和执行一次的结果是一样的)。从而避免同一条数据被重复处理。

即:exactly once 精确一次 :确保数据不丢失,且精确处理(不重复处理)。

 3.4、总结

        综上,这三层语义,没有好坏之分,主要看具体的应用场景。

例:

        允许数据丢失,但追求高性能,使用 at most once 至多一次。

        对数据精度要求非常高,一条不能丢并且结果严格正确,使用exactly once。

        很多框架默认是第二种(折中的),如何降低数据重复处理的可能行呢?

        可以适当调高超时时间,尤其是网络环境不好时。

3.5、​​​​​​​Kafka中设置可靠性

在kafka中,可以通过配置文件来进行设定,在server.properties文件:

#至多一次 
acks=0

#至少一次

acks=1 只接收leader的ACK ,这个常用

acks=2 接收leader的ACK和一个Follower的ACK。

acks=3 接收leader的ACK和两个Follower的ACK。

#精确一次

acks=1

enable.idempotence=true

 4、Zero copy (零拷贝技术)

        将A服务上的文件,通过网络发送到B服务器上。

kafka学习(三):kakfa消息处理、索引、零拷贝_第7张图片

 

        表面上一个简单的网络传输文件的过程,在OS(操作系统Operating System,简称OS)底层,会发现数据会被拷贝4次。 即:

  1. 磁盘 --- read buffer  
  2. read buffer --- 应用缓存
  3. 应用缓存 --- socket buffer
  4. socket buffer --- NIC buffer 网卡缓存

内核态:CPU可以访问内存所有数据,包括外围设备,例如磁盘、网卡。

用户态:只能受限的访问内存,且不能访问外围设备。

 上图中:

        如果要对文件数据修改,则只能在用户态的缓冲区修改,所以需要拷贝4次。

        但如果仅仅是发送文件数据,则 拷贝4次是没有意义的,并且还是产生4次内核态、用户态的切换,这些都需要耗费CPU的性能。

kafka学习(三):kakfa消息处理、索引、零拷贝_第8张图片

       上图为最新zero copy。两次拷贝即可。并且没有内核态、用户态的交互次数。

        综上,zero copy在通过网络传输文件数据时,可以减少拷贝次数、内核态和用户态的交互次数。

        Kafka底层就是用了zero copy技术。

5、小结

Kafka的写入性能高:因为底层是磁盘的顺序写。

Kafka的读取性能高:因为底层是索引机制。

Kafka的传输性能高:因为底层使用了zero copy技术。

你可能感兴趣的:(#,kafka,技术点,kafka)