Kafka design

Kafka官方文档翻译以及扩展

官方文档

中文版本:https://www.cnblogs.com/coprince/p/5893066.html

其他参考:https://colobu.com/2017/11/02/kafka-replication/

4.1 Motivation

for handling all the real-time data feeds

  • high-throughput
  • large data backlogs 大量的数据积压
  • low-latency delivery 满足传统的队列的用法

4.2 Persistence

As a result the performance of linear writes on a JBOD configuration with six 7200rpm SATA RAID-5 array is about 600MB/sec but the performance of random writes is only about 100k/sec—a difference of over 6000X.

磁盘的顺序写和随机写,性能相差6000倍,sequential disk access can in some cases be faster than random memory access!

  • OS pagecache

    现代操作系统很乐于使用所有的空闲内存来做disk caching。所有的磁盘读写都会通过这些cache进行。

  • Furthermore, we are building on top of the JVM, and anyone who has spent any time with Java memory usage knows two things:

     The memory overhead of objects is very high, often doubling the size of the data stored (or worse).
    
    Java garbage collection becomes increasingly fiddly and slow as the in-heap data increases.
    

基于上面的两个原因, 得出的结论:

using the filesystem and relying on pagecache is superior to maintaining an in-memory cache

直接使用带pagecache的OS filesystem 甚至性能会比使用内存cache要更好。

This style of pagecache-centric design is described in an article on the design of Varnish

partition存储细节:

broker的机器上,xxx/message-folder为数据文件存储根目录,在这个目录下, 每个partition一个文件夹。

在partition的文件夹下,有多个segment:

  • segment file组成:由2大部分组成,分别为index file和data file,此2个文件一一对应,成对出现,后缀”.index”和“.log”分别表示为segment索引文件、数据文件.
  • segment文件命名规则:partion全局的第一个segment从0开始,后续每个segment文件名为上一个segment文件最后一条消息的offset值。数值最大为64位long大小,19位数字字符长度,没有数字用0填充。

image-20181105233252954

image-20181105233332064

segment data file由许多message组成,每个message物理结构如下:

image-20181105233407991

4.3 Efficiency

For more background on the sendfile and zero-copy support in Java, see this article.

4.4 The Producer

任意一个broker都保存着metadate,关于哪些节点是活着的,还有一个topic的partition的leader是谁?所以producer可以找到对应的leader,直接向其发送消息。

4.5 The Consumer

consumer执行‘fetch’操作,同时带着offset,来向leader拉去消息。

offset:

一般的队列都会在broker端记录consumer消费的位置,这样做可以及时的删除消费掉的消息,但是维护这个位置是很费事的,还需要consumer返回ack。

kafka也会记录一个offset,表示下一个可以消费的消息的位置,而且可以‘倒带’,即重现消费之前消费过的消息。

4.6 Message Delivery Semantics

4.7 Replication

  • The unit of replication is the topic partition

    relication的最小单位是topic的partition。

  • 支持automatic faiover

    TODO 怎么支持的

  • 不像其他队列,replication的作用就只有做副本,无副作用。例如不会提供读。

  • followers从leader消费数据,就好像是一个kafka的consumer一样。

  • 节点存活的定义

    1 A node must be able to maintain its session with ZooKeeper

    2 If it is a slave it must replicate the writes happening on the leader and not fall “too far” behind

  • leader 维护ISR (in sync replication)

    如果一个follower挂了,阻塞了或者落后了,leader会把他从ISR中删除。

  • kafka不解决拜占庭问题。

commit

定义:

所有的ISR的节点都提交了log之后,才说一个message被committed。只有committed message才会提供给consumer。

对于consumer来说:

consumer不会担心看到过的message 会因为leader切换而丢失。

对于producer:

可以选择是否要等待message被committed,是latency 和 durability之间的tradeoff。

The guarantee that Kafka offers is that a committed message will not be lost, as long as there is at least one in sync replica alive, at all times.

只要有一个ISR存活,就可以保障committed message 不会丢失。

Kafka will remain available in the presence of node failures after a short fail-over period, but may not remain available in the presence of network partitions.

kafka在节点短期失效的情况下可以保持可用,但是在存在网络分区的情况下,是不可用的。

TODO:怎么理解

Quorum algorithms( majority vote)

简单来说,一半以上的follower commit了才能保障选举出来的leader有最新的commit。

好处:latency只依赖于最快的node。因为只要有一半ack了,就是commit成功,最快的最先完成。

坏处:写的增多,整体吞吐量下降,使得他不适合于大量的写的情况。举个例子:如果为了可以容忍2个节点的实效,就必须要5份数据的copy。 这个坏处也就可以解释为什么 quorum算法被经常用于类似zk这样的配置共享集群,而很少用于data storage。

kafka没有使用quorum算法。

Instead of majority vote, Kafka dynamically maintains a set of in-sync replicas (ISR) that are caught-up to the leader.

作为替代,kafka维护了一个ISR,其中每个replication都和leader保持一致。这个ISR是被leader维护的,且会保存到zk上。

只有ISR的成员,才会是leader的候选人。

This ISR set is persisted to ZooKeeper whenever it changes.

这个IRS集合是被持久化到zk。

Another important design distinction is that Kafka does not require that crashed nodes recover with all their data intact

另外一个kafka的特点是,crashed的nodes恢复后,不用恢复所有的数据。

Unclean leader election

如果所有的ISR都挂了,怎么办?

  1. Wait for a replica in the ISR to come back to life and choose this replica as the leader (hopefully it still has all its data).
  2. Choose the first replica (not necessarily in the ISR) that comes back to life as the leader.

Replica Management

We attempt to balance partitions within a cluster in a round-robin fashion to avoid clustering all partitions for high-volume topics on a small number of nodes

平衡的将partition分布到不同的broker中,用round-robin的方式。

we elect one of the brokers as the “controller”. This controller detects failures at the broker level and is responsible for changing the leader of all affected partitions in a failed broker. If the controller fails, one of the surviving brokers will become the new controller.

为每个partition进行leader选举是非常低效的,因为部署单元是broker,所以选一个borker当controller,它会去在broker层面去检测失效,并且还会去负责为失效的broker中受影响的partitions去做leader选举。如果controller broker挂了,就会选出一个新的。

实际上,Kafka选举一个broker作为controller,这个controller通过 watch Zookeeper检测所有的broker failure,并负责为所有受影响的parition选举leader,再将相应的leader调整命令发送至受影响的broker。如果 controller失败了,幸存的所有broker都会尝试在Zookeeper中创建/controller->{this broker id},如果创建成功(只可能有一个创建成功),则该broker会成为controller,若创建不成功,则该broker会等待新 controller的命令。