Kafka知识盘点【贰】_broker

Kafka知识盘点【壹】_生产者

 

kafka broker这部分,可能是kafka系列知识的核心所在。好好总结。

 

1.消息的存储

1.1 存储文件

在上文曾经介绍过,kafka的消息都是由partition为维度保存的。实际情况下,每个partition正是broker上的一个文件夹,文件夹下保存了segment和index两种文件。

segment文件分为日志文件和索引文件。日志文件后缀名为.log,保存在/${topicName}-${partitionid}/路径下,是实际保存消息的日志文件。每个文件最大不超过1G,超过后将新建文件继续保存。文件名命名规则是64位long大小,19位数字字符长度,不足用0填充,数字是上一个log文件的最后一个offset值+1。

索引文件保存路径与.log文件一致。索引文件的分段逻辑默认和log文件一样,同时也支持单独配置。索引不会针对每条消息都创建,而是当log文件每隔一定的字节数(由log.index.interval.bytes配置,默认4KB)再创建。索引文件可分为偏移量索引(offset index)和时间戳索引(timestamp index)两种。

偏移量索引:后缀名为.index。每条索引占8个字节,包含relativeOffset和position两部分。relativeOffset是相对偏移量占用4个字节,表示消息相对于日志分段文件名的偏移量(relativeOffset = 消息偏移量messageOffset - 消息所在日志分段文件的开始偏移量baseOffset)。position是消息所在具体的日志分段文件的位置,占用4个字节,。

时间戳索引:后缀名为.timeindex。每条索引占12个字节,包含timestamp(8字节)和relativeOffset两部分。timestamp是当前日志分段文件最大时间戳,递增保存;relativeOffset是时间戳对应的消息先对偏移量。查找思路就是先根据消息时间戳对应的时间戳索引文件找到相对偏移量,再到上面相应的偏移量索引文件中查找。

Kafka知识盘点【贰】_broker_第1张图片

1.2存储方式

大家都说kafka的性能高除了以上合理的消息存储设计,还有使用了页缓存及零拷贝技术。页缓存即pagecache,操作系统会先查看待读取的数据以页为单位加载到页缓存中。后续进程读取数据时,会先判断页缓存中是否存在,如存在则直接获取返回,而不用再去读取磁盘。这里只做简单介绍,下面我们说一下零拷贝。

首先说,linux系统传统的数据拷贝是如何完成的:

Kafka知识盘点【贰】_broker_第2张图片

可以看到在linux系统的用户态和内核态中间的数据拷贝需要cpu来完成,产生性能消耗。为了优化这个问题,linux提供了零拷贝技术。这里需要注意的是,零拷贝指的是没有用户态和内核态直接的数据拷贝。

Kafka知识盘点【贰】_broker_第3张图片

kafka采用的是调用sendFile()方式,数据通过DMA读取到内核缓冲区。内核缓冲区中的数据通过DMA聚合网络缓冲区,然后一齐发送到网卡。

扩展一下rocketMQ也应用了零拷贝技术,不过使用的是Mmap方式。mmap先在内存申请一块区域,然后把文件映射到虚拟内存,从而省去了从read buffer复制到用户缓存的步骤,减少了一次cpu拷贝。rocketMQ还做了空间预分配和数据预热来优化性能。

 

2.高可用机制

2.1 副本replica

Kafka知识盘点【贰】_broker_第4张图片

replica(上图中绿色节点)可理解为消息分区日志(红色节点)的副本,由于kafka broker一般以集群方式部署,因此分区日志的副本一般会创建在其他broker上。和其他分布式中间件的设计一样,副本也分为leader和follower两种角色。但是kafka对消息都是主写主读。

默认情况下,所有的分区的副本都处于ISR(in-sync replica)集合中,通过zk来维护。当kafka生产者发送消息的配置acks是all时,只有当ISR中所有replica都收到消息,消息才认为发送成功。如果某replica滞后同步一定程度(replica.lag.time.max.ms),则将其踢出ISR集合,当其追上后再将其加入。

当leader挂掉后,kafka从ISR集合中的follower选出一个作为新的leader,这个选举操作由controller完成。选取的思路就是,先获取所有副本的集合,按副本id升序获取第一个同时也在ISR集合中的副本,作为新的leader。

那么controller是什么角色呢?

 

2.2 Controller

其实就是broker集群中的一台,会负责管理整个集群素有分区和副本的状态。和ISR一样,controller也是通过zk来维护,竞选成功的broker会在zk中创建/controller临时节点,记录自己的brokerId和version。每个broker启动的时候都会尝试去竞选controller,当获取/controller临时节点的brokerId发现不是-1时,说明controller已经存在,则不再竞选,并把broker保存到内存中。

/controller临时节点中的version,是通过zk另一个/controller_epoch持久节点维护,用于记录controller发生变更的次数,记录这是第几代controller。kafka正是通过这个值来保证controller的唯一性(kafka的leader选举也有类似设计)。

说白了,controller的竞选,就是争取创建zk的/controller临时节点。

 

下一篇:Kafka知识盘点【叁】_消费者

 

你可能感兴趣的:(消息队列)