kafka面试八股文

0、kafka的基本名词

        topic:划分message的逻辑概念,一个topic的数据分布在多个broker上

        partition:每个topic的数据,被切分至一个或多个partition中

        offset:消息在partition的编号,不跨partition

        consumer:从broker获取message

        producer:向broker生产message

        replication:kafka支持以partition位单位的冗余,每个partition至少有一个replication

        leader:每个partition的replication集合中,有一个leader,该partition所有读写请求由leader处理,其他replication同步。近似MySQL的binlog同步

        broker:kafka的broker接受producer和consumer的读写请求。kafka集群会在所有broker中选一个作为controller,负责partition的leader的选举,协调partition数据的迁移。

        ISR:是每个partition的replication的一个子集,表示目前处于alive(通过zk确认一个节点是否alive)并且与leader同步的集合。每个partition生产的数据,首先都是落在leader上,然后ISR同步后,认为这次数据成功写入了。ISR是动态变化的,延迟的时间、延迟的记录数,都会导致某个replication被踢出ISR。

1、kafka broker怎么选leader

        依赖zk实现,基本原理是:集群中所有broker都向zk的contoller注册临时节点,第一个成功的就成为leader broker,其余是watcher broker。

        如果leader broker崩溃或下线,其他watcher broker会立刻感知,重新发起选leader。

2、kafka的数据模型

        kafka的数据是按topic分组,存在partition上,使用主从模式。每个partition,都有主本副本。

        创建topic时自动创建一个AR集合,并另有一个ISR集合,ISR代表了和主本数据保持同步的集合,这个ISR是随环境变化的,跟不上的会被踢出。

3、kafka的数据存储模型

        kafka之所以是高吞吐,其数据的存储方式也是原因之一:

        

  • .log 日志文件,用于存储具体的消息数据。另外每个log文件大小是有限制的,在达到指定大小后会创建新的日志文件,文件名也是以当前log中最早的消息的offset来命名的比如00000000000000000000.log。
  • .index 偏移量索引文件,和log文件一一对应,文件名与日志文件的名字是一样的,只是文件扩展名为.index。index文件中并没有为数据文件中的每条Message 建立索引,而是采用了稀疏存储的方式(稀疏索引),每隔一定字节的数据建立一条索引。这样避免了索引文件占用过多的空间,从而可以将索引文件保留在内存中。
  • .timeindex 时间戳索引文件,和log文件一一对应,文件名与日志文件的名字是一样的,只是文件扩展名为.timeindex。注意,该文件是在0.8版本之后才有的。

        kafka是直接写磁盘文件的,但是是以顺序追加的形式写在文件的末尾,这种方式性能是随机读写的几十倍。

        除了这个顺序追加。Kafka还使用到了页缓存Page Cache零拷贝Zero-Copy等技术来进一步提升写性能。也就是写的只是文件缓存,由操作系统的fsync,异步的刷盘。

        利用LogSegment+有序offset+稀疏索引+二分查找+顺序查找 可以快速查找指定的消息;
顺序追加+页缓存+零拷贝 提升写性能

4、kafka的数据写入

        对于Kafka来说写过程就是集群如何把生产者发送过来的数据写入到本地日志文件中的

5、kafka数据的消费

         Partition是最小并发粒度。

        多Consumer消费同一个Topic时,同一条消息只会被同一Consumer Group内的一个Consumer所消费。而数据并非按消息为单位分配,而是以Partition为单位分配,也即同一个Partition的数据只会被一个Consumer所消费。

        如果Consumer的个数多于Partition的个数,那么会有部分Consumer无法消费该Topic的任何数据,也即当Consumer个数超过Partition后,增加Consumer并不能增加并行度

Kafka Consumer

        如上图,Topic 2只包含3个Partition,故group2中的Consumer 3、Consumer 4、Consumer 5 可分别消费1个Partition的数据,而Consumer 6消费不到Topic 2的任何数据。 

6、ISR实现CAP中,可用性A和数据一致性C的动态平衡

        CAP理论是指,分布式系统中,一致性、可用性和分区容忍性最多只能同时满足两个。

        首先看一下CAP理论,以及常见的C和A怎么做平衡:

        一致性

  • 通过某个节点的写操作结果对后面通过其它节点的读操作可见
  • 如果更新数据后,并发访问情况下后续读操作可立即感知该更新,称为强一致性
  • 如果允许之后部分或者全部感知不到该更新,称为弱一致性
  • 若在之后的一段时间(通常该时间不固定)后,一定可以感知到该更新,称为最终一致性

        可用性

  • 任何一个没有发生故障的节点必须在有限的时间内返回合理的结果

        分区容忍性

  • 部分节点宕机或者无法与其它节点通信时,各分区间还可保持分布式系统的功能

        一般而言都要求保证分区容忍性。所以在CAP理论下,更多的是需要在可用性和一致性之间做权衡。

        

        常用数据复制及一致性方案

        Master-Slave

  • RDBMS的读写分离即为典型的Master-Slave方案
  • 同步复制可保证强一致性但会影响可用性
  • 异步复制可提供高可用性但会降低一致性

        再看看kafka如何实现的C和A的平衡:

        Kafka的数据复制方案接近于上文所讲的Master-Slave方案。不同的是,Kafka既不是完全的同步复制,也不是完全的异步复制,而是基于ISR的动态复制方案

        每个Partition的Leader都会维护这样一个列表,该列表中,包含了所有与之同步的Replica(包含Leader自己)。每次数据写入时,只有ISR中的所有Replica都复制完,Leader才会将其置为Commit,它才能被Consumer所消费

        这种方案,与同步复制非常接近。但不同的是,这个ISR是由Leader动态维护的。如果Follower不能紧“跟上”Leader,它将被Leader从ISR中移除,待它又重新“跟上”Leader后,会被Leader再次加加ISR中。每次改变ISR后,Leader都会将最新的ISR持久化到Zookeeper中。

        

        使用ISR方案的原因

  • 由于Leader可移除不能及时与之同步的Follower,故与同步复制相比可避免最慢的Follower拖慢整体速度,也即ISR提高了系统可用性。
  • ISR中的所有Follower都包含了所有Commit过的消息,而只有Commit过的消息才会被Consumer消费,故从Consumer的角度而言,ISR中的所有Replica都始终处于同步状态,从而与异步复制方案相比提高了数据一致性。
  • ISR可动态调整,极限情况下,可以只包含Leader,极大提高了可容忍的宕机的Follower的数量。与Majority Quorum方案相比,容忍相同个数的节点失败,所要求的总节点数少了近一半

7、kafka如何高吞吐(页缓存 + 零拷贝)

        页缓存:

        Broker收到数据后,写磁盘时只是将数据写入Page Cache,并不保证数据一定完全写入磁盘。

        从这一点看,可能会造成机器宕机时,Page Cache内的数据未写入磁盘从而造成数据丢失。但是这种丢失只发生在机器断电等造成操作系统不工作的场景,而这种场景完全可以由Kafka层面的Replication机制去解决。

        如果为了保证这种情况下数据不丢失而强制将Page Cache中的数据Flush到磁盘,反而会降低性能。

        零拷贝:

        Kafka中存在大量的网络数据持久化到磁盘(Producer到Broker)和磁盘文件通过网络发送(Broker到Consumer)的过程。这一过程的性能直接影响Kafka的整体吞吐量。

        传统模式下的四次拷贝与四次上下文切换:

        buffer = File.read
        Socket.send(buffer)

        这一过程实际上发生了四次数据拷贝。首先通过系统调用将文件数据读入到内核态Buffer(DMA拷贝),然后应用程序将内核态Buffer数据读入到用户态Buffer(CPU拷贝),接着用户程序通过Socket发送数据时将用户态Buffer数据拷贝到内核态Buffer(CPU拷贝),最后通过DMA拷贝将数据拷贝到NIC Buffer。同时,还伴随着四次上下文切换,如下图所示。

        

BIO 四次拷贝 四次上下文切换

 

        sendfile和transferTo实现零拷贝:

        数据通过DMA拷贝到内核态Buffer后,直接通过DMA拷贝到NIC Buffer,无需CPU拷贝。这也是零拷贝这一说法的来源。除了减少数据拷贝外,因为整个读文件-网络发送由一个sendfile调用完成,整个过程只有两次上下文切换。

BIO 零拷贝 两次上下文切换

 

8、kafka的其他高效

        批处理

        批处理是一种常用的用于提高I/O性能的方式。对Kafka而言,批处理既减少了网络传输的Overhead,又提高了写磁盘的效率。

        由于每次网络传输,除了传输消息本身以外,还要传输非常多的网络协议本身的一些内容(称为Overhead),所以将多条消息合并到一起传输,可有效减少网络传输的Overhead,进而提高了传输效率。

        数据压缩降低网络负载

        Kafka从0.7开始,即支持将数据压缩后再传输给Broker。除了可以将每条消息单独压缩然后传输外,Kafka还支持在批量发送时,将整个Batch的消息一起压缩后传输。数据压缩的一个基本原理是,重复数据越多压缩效果越好。因此将整个Batch的数据一起压缩能更大幅度减小数据量,从而更大程度提高网络传输效率。

        高效的序列化方式

        Kafka消息的Key和Payload(或者说Value)的类型可自定义,只需同时提供相应的序列化器和反序列化器即可。因此用户可以通过使用快速且紧凑的序列化-反序列化方式(如Avro,Protocal Buffer)来减少实际网络传输和磁盘存储的数据规模,从而提高吞吐率。

10、kafka如何保证数据不丢失、不重复

使用同步模式的时候,有3种状态保证消息被安全生产,在配置为1(只保证写入leader成功)的话,如果刚好leader partition挂了,数据就会丢失。
还有一种情况可能会丢失消息,就是使用异步模式的时候,当缓冲区满了,如果配置为0(还没有收到确认的情况下,缓冲池一满,就清空缓冲池里的消息),
数据就会被立即丢弃掉
在数据生产时避免数据丢失的方法:
就是说在同步模式的时候,确认机制设置为-1,也就是让消息写入leader和所有的副本。
还有,在异步模式下,如果消息发出去了,但还没有收到确认的时候,缓冲池满了,在配置文件中设置成不限制阻塞超时的时间,也就说让生产端一直阻塞,这样也能保证数据不会丢失。

11、kafka什么时候丢数据

        1、确认机制没有设置为-1

        这种情况下,如果写请求发出后,忽然kafka宕机,那么数据就丢失了,因为客户端认为已经写入。

        解决:确认机制设置为-1,确保ISR成员都写入后,才给客户端producer发送commit。

        2、kafka的异步刷盘时忽然宕机

        fsync还没来得及将文件缓存的数据落盘时忽然宕机,那么数据可能丢失。

        解决:无。如果设置为同步落盘,那么大大影响效率。

        3、consumer设置为自动提交

        自动的提交了commit,结果consumer出现了异常。

        解决:改为手动提交,不处理成果,不给broker发送commit。

        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值