Kafka基础

  Kafka是一个分布式的基于发布/订阅模式的消息引擎系统

  1. 削峰填谷
  2. 应用解耦
  3. 异步处理
  4. 高吞吐
  5. 高性能

 

kaFka的模式:

 

  1. 点对点模式
  2. 发布/订阅模式

 

术语

⽣产者:Producer。向主题发布新消息的应⽤程序。

消费者:Consumer。从主题订阅新消息的应⽤程序。消息:Record。Kafka是消息引擎嘛,这⾥的消息就是指Kafka处理的主要对象。

主题:Topic。主题是承载消息的逻辑容器,在实际使⽤中多⽤来区分具体的业务。

分区:Partition。⼀个有序不变的消息序列。每个主题下可以有多个分区。

消息位移:Offset。表示分区中每条消息的位置信息,是⼀个单调递增且不变的值。

副本:Replica。Kafka中同⼀条消息能够被拷⻉到多个地⽅以提供数据冗余,这些地⽅就是所谓的副本。副本还分为领导者副本和追随者副本,各⾃有不同的⻆⾊划分。副本是在分区层级下的,即每个分区可配置多个副本实现⾼可⽤。

消费者位移:Consumer Offset。表征消费者消费进度,每个消费者都有⾃⼰的消费者位移。

消费者组:Consumer Group。多个消费者实例共同组成的⼀个组,同时消费多个分区以实现⾼吞吐。

重平衡:Rebalance。消费者组内某个消费者实例挂掉后,其他消费者实例⾃动重新分配订阅主题分区的过程。Rebalance是Kafka消费者端实现⾼可⽤的重要⼿段。

 

Producer推数据到Kafka,Consumer从Kafka里面拉取数据,这么做的原因是:

Kafka的QPS能达到好几十万,如果Kafka从Producer里面拉取数据或者推数据到Consumner,但凡Producer或Consumer的能力达不到要求,Kafka的吞吐量也达不到这么高,容易把Consumer打挂,和消息的堆积,严重的话会影响业务.

 

消息的发送和拉取都是以Topic为准的,一个Topic可以有多个Partition,一个Partition会有多个副本(Replica),并且每个副本存放到不同的broker里面,这样做的原因是为了高可用,一个消费者组可以消费多个Topic,一个Topic的一个Partition只能被消费者组里的一个Consumer消费,消费者组里面的一台机器可以消费多个Partition,最理想的状态是消费者组的消费者与Partition的比例是1:1,这样就能很好的体现高吞吐;

 

如果需要重复消费某一条信息,可以设置Offset重新消费

 

Rebalance,重新计算有多少个Partition,还剩几个存活的Consumer,然后重新分配,

 

分区的消费是有序的,如果要保证全局有序,最简单的方法是一个Topic一个分区,多个分区只能保证局部有序;分区不是越多越好,过多的分区反而会影响性能

 

Offset是记录在Kafka里面的,记录Consumer消费到哪里,如果Rebalance后,换了Consumer,那么可以读取这个Offset继续消费

 

Producer发送信息到Kafka,Kafka确认收到消息的设置:

  requet.requil.ack=0 -1 1

  0:Producer只管发,不需要知道Kafka是否收到,这样是能达到最大吞吐量的,但是不能保证数据的高可用性.

  -1:Producer发送数据,需要ISR中的所有副本都成功写入信息后才算是成功收到数据.

  1:Producer发送数据,Leader收到了就算是成功收到数据.

 

Kafka在2.8之后就去zookeeper了,但是Kafka2.8还没有普及

 

Kafka特性深入  

日志存储

Kafka 中的消息是以主题为基本单位进⾏归类的,各个主题在逻辑上相互独⽴。每个主题⼜可以分为⼀个或多个分区,分区的数量可以在主题创建的时候指定,也可以在之后修改。每条消息在发送的时候会根据分区规则被追加到指定的分区中,分区中的每条消息都会被分配⼀个唯⼀的序列号,也就是通常所说的偏移量(offset)。

不考虑多副本的情况,⼀个分区对应⼀个⽇志(Log)。为了防⽌ Log 过⼤,Kafka ⼜引⼊了⽇志分段(LogSegment)的概念,将 Log 切分为多个 LogSegment,相当于⼀个巨型⽂件被平均分配为多个相对较⼩的⽂件,这样也便于消息的维护和清理。而每个LogSegment的命名是根据本LogSegment最小的Offset来的,在查找指定的offset的Message的时候,用二分查找来定位该Message在哪个段中

为数据文件建索引

数据文件分段使得可以在一个较小的数据文件中查找对应offset的Message了,但是这依然需要顺序扫描才能找到对应offset的Message。为了进一步提高查找的效率,Kafka为每个分段后的数据文件建立了索引文件,文件名与数据文件的名字是一样的,只是文件扩展名为.index。
索引文件中包含若干个索引条目,每个条目表示数据文件中一条Message的索引。索引包含两个部分(均为4个字节的数字),分别为相对offset和position。

  • 相对offset:因为数据文件分段以后,每个数据文件的起始offset不为0,相对offset表示这条Message相对于其所属数据文件中最小的offset的大小。举例,分段后的一个数据文件的offset是从20开始,那么offset为25的Message在index文件中的相对offset就是25-20 = 5。存储相对offset可以减小索引文件占用的空间。
  • position,表示该条Message在数据文件中的绝对位置。只要打开文件并移动文件指针到这个position就可以读取对应的Message了。

index文件中并没有为数据文件中的每条Message建立索引,而是采用了稀疏存储的方式,每隔一定字节的数据建立一条索引。这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中。但缺点是没有建立索引的Message也不能一次定位到其在数据文件的位置,从而需要做一次顺序扫描,但是这次顺序扫描的范围就很小了。

 一个LogSegment包括".log 日志文件",".index偏移量索引文件",".timeindex时间索引文件","其他文件"

 

分区副本剖析

Kafka 通过多副本机制实现故障⾃动转移,在 Kafka 集群中某个 broker 节点失效的情况下仍然保证服务可⽤。

 

第⼀,副本分成两类:领导者副本(Leader Replica)和追随者副本(Follower Replica)。

第⼆,Follower副本是不对外提供服务的。这就是说,任何⼀个追随者副本都不能响应消费者和⽣产者的读写请求。所有的请求都必须由领导者副本来处理,或者说,所有的读写请求都必须发往领导者副本所在的Broker,由该Broker负责处理。

第三,当领导者副本挂掉了,或者说领导者副本所在的Broker宕机时,Kafka依托于ZooKeeper提供的监控功能能够实时感知到,并⽴即开启新⼀轮的领导者选举,从追随者副本中选⼀个作为新的领导者。⽼Leader副本重启回来后,只能作为追随者副本加⼊到集群中

 

ISR与AR

分区中的所有副本统称为 AR,⽽ ISR 是指与 leader 副本保持同步状态的副本集合,当然 leader副本本身也是这个集合中的⼀员。

 

失效副本

正常情况下,分区的所有副本都处于 ISR 集合中,但是难免会有异常情况发⽣,从⽽某些副本被剥离出ISR 集合中。在 ISR 集合之外,也就是处于同步失效或功能失效(⽐如副本处于⾮存活状态)的副本统称为失效副本,失效副本对应的分区也就称为同步失效分区,即 under-replicated 分区。

 

leader副本挂了之后从ISR里面去选举一个新的leader,Kafka还有一个配置是如果leader和ISR集合里的机器都挂了就从AR集合里面去选举leader,但是从AR里面选举,数据做不到高可用性.

 

ISR如何做到数据高可用性:  

LEO与HW

LEO 标识每个分区中最后⼀条消息的下⼀个位置,分区的每个副本都有⾃⼰的 LEO,ISR 中最⼩的 LEO即为 HW,俗称⾼⽔位,消费者只能拉取到 HW 之前的消息。

Kafka的主题 kafka订阅主题_缓存

 

 

leader与副本同步数据的时候,副本们会把自己的LEO发送给Leader,Leader再从拿到的LEO中去最小值设置成HW,再讲HW发给副本们同步 

 

Kafka的主题 kafka订阅主题_Kafka的主题_02

 

 

ISR什么时候会去加副本/踢副本

当某个副本因为网络问题而一直影响性能的话,ISR会把这个副本踢掉,直到它的网络恢复正常,并且数据量跟上了leader的时候才会把它加进来

如果HW比LEO低很多的时候,低HW的副本突然挂掉,数据不会丢掉,而是等待重发

 

磁盘顺序读写

kafak采⽤的是磁盘顺序读写⽅式,极⼤提升了读写性能。

 

高性能页缓存

  1. ⽤户调⽤标准 C 库进⾏ I/O 操作,数据流为:应⽤程序 buffer→C 库标准 IObuffer→⽂件系统⻚缓存→通过具体⽂件系统到磁盘。
  2. ⽤户调⽤⽂件 I/O,数据流为:应⽤程序 buffer→⽂件系统⻚缓存→通过具体⽂件系统到磁盘。
  3. ⽤户打开⽂件时使⽤ O_DIRECT,绕过⻚缓存直接读写磁盘。
  4. ⽤户使⽤类似 dd ⼯具,并使⽤ direct 参数,绕过系统 cache与⽂件系统直接写磁盘。

零拷贝

所谓的零拷⻉是指将数据直接从磁盘⽂件复制到⽹卡设备中,⽽不需要经由应⽤程序之⼿。零拷⻉⼤⼤提⾼了应⽤程序的性能,减少了内核和⽤户模式之间的上下⽂切换。

Kafka的主题 kafka订阅主题_数据文件_03

(不使用零拷贝技术)

1. 调⽤ read() 时,⽂件 A 中的内容被复制到了内核模式下的 Read Buffer 中。

2. CPU 控制将内核模式数据复制到⽤户模式下。

3. 调⽤ write() 时,将⽤户模式下的内容复制到内核模式下的 Socket Buffer 中。

4. 将内核模式下的 Socket Buffer 的数据复制到⽹卡设备中传送。

 

Kafka的主题 kafka订阅主题_缓存_04

(使用零拷贝技术)

面试重点

- 高性能 - 循序读写 - 页缓存 - 零拷贝 - 高可用 - ISR、AR - ack 1, 0, -1 - ISR选主