Kafka是最后由Linkedin公司开发,是一个分布式、反对分区的(partition)、多正本的(replica),基于zookeeper协调的分布式音讯零碎,它的最大的个性就是能够实时的解决大量数据以满足各种需要场景:比方基于hadoop的批处理零碎、低提早的实时零碎、storm/Spark流式解决引擎,web/nginx日志、拜访日志,音讯服务等等,用scala语言编写,Linkedin于2010年奉献给了Apache基金会并成为顶级开源我的项目。

1.前言
音讯队列的性能好坏,其文件存储机制设计是掂量一个音讯队列服务技术水平和最要害指标之一。上面将从Kafka文件存储机制和物理构造角度,剖析Kafka是如何实现高效文件存储,及理论利用成果。

1.1 Kafka的个性:

  • 高吞吐量、低提早:kafka每秒能够解决几十万条音讯,它的提早最低只有几毫秒,每个topic能够分多个partition, consumer group 对partition进行consume操作。
  • 可扩展性:kafka集群反对热扩大
  • 持久性、可靠性:音讯被长久化到本地磁盘,并且反对数据备份避免数据失落
  • 容错性:容许集群中节点失败(若正本数量为n,则容许n-1个节点失败)
  • 高并发:反对数千个客户端同时读写

1.2 Kafka的应用场景:

  • 日志收集:一个公司能够用Kafka能够收集各种服务的log,通过kafka以对立接口服务的形式凋谢给各种consumer,例如hadoop、Hbase、Solr等。
  • 音讯零碎:解耦和生产者和消费者、缓存音讯等。
  • 用户流动跟踪:Kafka常常被用来记录web用户或者app用户的各种流动,如浏览网页、搜寻、点击等流动,这些流动信息被各个服务器公布到kafka的topic中,而后订阅者通过订阅这些topic来做实时的监控剖析,或者装载到hadoop、数据仓库中做离线剖析和开掘。
  • 经营指标:Kafka也常常用来记录经营监控数据。包含收集各种分布式应用的数据,生产各种操作的集中反馈,比方报警和报告。
  • 流式解决:比方spark streaming和storm

1.3 Kakfa的设计思维

  • Kakfa Broker Leader的选举:Kakfa Broker集群受Zookeeper治理。所有的Kafka Broker节点一起去Zookeeper上注册一个长期节点,因为只有一个Kafka Broker会注册胜利,其余的都会失败,所以这个胜利在Zookeeper上注册长期节点的这个Kafka Broker会成为Kafka Broker Controller,其余的Kafka broker叫Kafka Broker follower。(这个过程叫Controller在ZooKeeper注册Watch)。这个Controller会监听其余的Kafka Broker的所有信息,如果这个kafka broker controller宕机了,在zookeeper下面的那个长期节点就会隐没,此时所有的kafka broker又会一起去Zookeeper上注册一个长期节点,因为只有一个Kafka Broker会注册胜利,其余的都会失败,所以这个胜利在Zookeeper上注册长期节点的这个Kafka Broker会成为Kafka Broker Controller,其余的Kafka broker叫Kafka Broker follower。例如:一旦有一个broker宕机了,这个kafka broker controller会读取该宕机broker上所有的partition在zookeeper上的状态,并选取ISR列表中的一个replica作为partition leader(如果ISR列表中的replica全挂,选一个幸存的replica作为leader; 如果该partition的所有的replica都宕机了,则将新的leader设置为-1,期待复原,期待ISR中的任一个Replica“活”过去,并且选它作为Leader;或抉择第一个“活”过去的Replica(不肯定是ISR中的)作为Leader),这个broker宕机的事件,kafka controller也会告诉zookeeper,zookeeper就会告诉其余的kafka broker。
  • Consumergroup:各个consumer(consumer 线程)能够组成一个组(Consumer group ),partition中的每个message只能被组(Consumer group )中的一个consumer(consumer 线程)生产,如果一个message能够被多个consumer(consumer 线程)生产的话,那么这些consumer必须在不同的组。 Kafka不反对一个partition中的message由两个或两个以上的同一个consumer group下的consumer thread来解决,除非再启动一个新的consumer group。所以如果想同时对一个topic做生产的话,启动多个consumer group就能够了,然而要留神的是,这里的多个consumer的生产都必须是程序读取partition外面的message,新启动的consumer默认从partition队列最头端最新的中央开始阻塞的读message。 当启动一个consumer group去生产一个topic的时候,无论topic外面有多个少个partition,无论咱们consumer group外面配置了多少个consumer thread,这个consumer group上面的所有consumer thread肯定会生产全副的partition;即使这个consumer group下只有一个consumer thread,那么这个consumer thread也会去生产所有的partition。因而,最优的设计就是,consumer group下的consumer thread的数量等于partition数量,这样效率是最高的。 同一partition的一条message只能被同一个Consumer Group内的一个Consumer生产。不可能一个consumer group的多个consumer同时生产一个partition。
  • Consumer Rebalance的触发条件:(1): Consumer减少或删除会触发 Consumer Group的Rebalance(2)Broker的减少或者缩小都会触发 Consumer Rebalance。
  • Consumer:Consumer解决partition外面的message的时候是o(1)程序读取的。所以必须保护着上一次读到哪里的offsite信息。high level API,offset存于Zookeeper中,low level API的offset由本人保护。一般来说都是应用high level api的。Consumer的delivery gurarantee,默认是读完message先commmit再解决message,autocommit默认是true,这时候先commit就会更新offsite+1,一旦解决失败,offsite曾经+1,这个时候就会丢message;也能够配置成读完音讯解决再commit,这种状况下consumer端的响应就会比较慢的,须要等解决完才行。如果producer的流量增大,以后的topic的parition数量=consumer数量,这时候的应答形式就是很想扩大:减少topic下的partition,同时减少这个consumer group下的consumer。
  • Delivery Mode: Kafka producer 发送message不必保护message的offsite信息,因为这个时候,offsite就相当于一个自增id,producer就只管发送message就好了。然而Consumer端是须要保护这个partition以后生产到哪个message的offsite信息的,这个offsite信息,high level api是保护在Zookeeper上,low level api是本人的程序保护。当应用high level api的时候,先拿message解决,再定时主动commit offsite+1(也能够改成手动), 并且kakfa解决message是没有锁操作的。因而如果解决message失败,此时还没有commit offsite+1,当consumer thread重启后会反复生产这个message。然而作为高吞吐量高并发的实时处理零碎,at least once的状况下,至多一次会被解决到,是能够容忍的。如果无奈容忍,就得应用low level api来本人程序保护这个offsite信息,那么想什么时候commit offsite+1就本人搞定了。
  • Topic & Partition:Topic相当于传统音讯零碎MQ中的一个队列queue,producer端发送的message必须指定是发送到哪个topic,然而不须要指定topic下的哪个partition,因为kafka会把收到的message进行load balance,平均的散布在这个topic下的不同的partition上( hash(message) % [broker数量] )。 在物理构造上,每个partition对应一个物理的目录(文件夹),文件夹命名是[topicname]_[partition]_[序号],一个topic能够有有数多的partition,依据业务需要和数据量来设置。 在kafka配置文件中可随时更高num.partitions参数来配置更改topic的partition数量,在创立Topic时通过参数指定parittion数量。Topic创立之后通过Kafka提供的工具也能够批改partiton数量。 一般来说,(1)一个Topic的Partition数量大于等于Broker的数量,能够进步吞吐率。(2)同一个Partition的Replica尽量扩散到不同的机器,高可用。 当add a new partition的时候,partition外面的message不会从新进行调配,原来的partition外面的message数据不会变,新加的这个partition刚开始是空的,随后进入这个topic的message就会从新参加所有partition的load balance。
  • Partition Replica:每个partition能够在其余的kafka broker节点上存正本,以便某个kafka broker节点宕机不会影响这个kafka集群。存replica正本的形式是依照kafka broker的程序存。例如有5个kafka broker节点,某个topic有3个partition,每个partition存2个正本,那么partition1存broker1,broker2,partition2存broker2,broker3。。。以此类推(replica正本数目不能大于kafka broker节点的数目,否则报错。这里的replica数其实就是partition的正本总数,其中包含一个leader,其余的就是copy正本)。这样如果某个broker宕机,其实整个kafka内数据仍然是残缺的。然而,replica正本数越高,零碎尽管越稳固,然而回来带资源和性能上的降落;replica正本少的话,也会造成零碎丢数据的危险。
    (1)怎么传送音讯:producer先把message发送到partition leader,再由leader发送给其余partition follower。
    (2)在向Producer发送ACK前须要保障有多少个Replica曾经收到该音讯:依据ack配的个数而定。
    (3)怎么解决某个Replica不工作的状况:如果这个部工作的partition replica不在ack列表中,就是producer在发送音讯到partition leader上,partition leader向partition follower发送message没有响应而已,这个不会影响整个零碎,也不会有什么问题。如果这个不工作的partition replica在ack列表中的话,producer发送的message的时候会期待这个不工作的partition replca写message胜利,然而会等到time out,而后返回失败因为某个ack列表中的partition replica没有响应,此时kafka会主动的把这个部工作的partition replica从ack列表中移除,当前的producer发送message的时候就不会有这个ack列表下的这个部工作的partition replica了。
    (4)怎么解决Failed Replica复原回来的状况:如果这个partition replica之前不在ack列表中,那么启动后从新受Zookeeper治理即可,之后producer发送message的时候,partition leader会持续发送message到这个partition follower上。如果这个partition replica之前在ack列表中,此时重启后,须要把这个partition replica再手动加到ack列表中。(ack列表是手动增加的,呈现某个部工作的partition replica的时候主动从ack列表中移除的)
  • Partition leader与follower:partition也有leader和follower之分。leader是主partition,producer写kafka的时候先写partition leader,再由partition leader push给其余的partition follower。partition leader与follower的信息受Zookeeper管制,一旦partition leader所在的broker节点宕机,zookeeper会冲其余的broker的partition follower上抉择follower变为parition leader。
  • Topic调配partition和partition replica的算法:(1)将Broker(size=n)和待调配的Partition排序。(2)将第i个Partition调配到第(i%n)个Broker上。(3)将第i个Partition的第j个Replica调配到第((i + j) % n)个Broker上。
  • Partition ack:当ack=1,示意producer写partition leader胜利后,broker就返回胜利,无论其余的partition follower是否写胜利。当ack=2,示意producer写partition leader和其余一个follower胜利的时候,broker就返回胜利,无论其余的partition follower是否写胜利。当ack=-1[parition的数量]的时候,示意只有producer全副写胜利的时候,才算胜利,kafka broker才返回胜利信息。这里须要留神的是,如果ack=1的时候,一旦有个broker宕机导致partition的follower和leader切换,会导致丢数据。
  • message状态:在Kafka中,音讯的状态被保留在consumer中,broker不会关怀哪个音讯被生产了被谁生产了,只记录一个offset值(指向partition中下一个要被生产的音讯地位),这就意味着如果consumer解决不好的话,broker上的一个音讯可能会被生产屡次。
  • message长久化:Kafka中会把音讯长久化到本地文件系统中,并且放弃o(1)极高的效率。咱们家喻户晓IO读取是十分耗资源的性能也是最慢的,这就是为了数据库的瓶颈常常在IO上,须要换SSD硬盘的起因。然而Kafka作为吞吐量极高的MQ,却能够十分高效的message长久化到文件。这是因为Kafka是程序写入o(1)的工夫复杂度,速度十分快。也是高吞吐量的起因。因为message的写入长久化是程序写入的,因而message在被生产的时候也是按程序被生产的,保障partition的message是程序生产的。个别的机器,单机每秒100k条数据。
  • message有效期:不同的版本不一样,目前默认保留7天。
  • Produer:Producer向Topic发送message,不须要指定partition,间接发送就好了。kafka通过partition ack来管制是否发送胜利并把信息返回给producer,producer能够有任意多的thread,这些kafka服务器端是不care的。Producer端的delivery guarantee默认是At least once的。也能够设置Producer异步发送实现At most once。Producer能够用主键幂等性实现Exactly once。
  • Kafka高吞吐量: Kafka的高吞吐量体现在读写上,分布式并发的读和写都十分快,写的性能体现在以o(1)的工夫复杂度进行程序写入。读的性能体现在以o(1)的工夫复杂度进行程序读取, 对topic进行partition分区,consume group中的consume线程能够以很高能性能进行程序读。
  • Kafka delivery guarantee(message传送保障):(1)At most once音讯可能会丢,相对不会反复传输;(2)At least once 音讯相对不会丢,然而可能会反复传输;(3)Exactly once每条信息必定会被传输一次且仅传输一次,这是用户想要的。
  • 冗余: replica有多个正本,保障一个broker node宕机后不会影响整个服务。
  • 扩展性: broker节点能够程度扩大,partition也能够程度减少,partition replica也能够程度减少。
  • 峰值: 在访问量剧增的状况下,kafka程度扩大, 利用依然须要持续发挥作用。
  • 可恢复性: 零碎的一部分组件生效时,因为有partition的replica正本,不会影响到整个零碎。
  • 程序保障性:因为kafka的producer的写message与consumer去读message都是程序的读写,保障了高效的性能。
  • 缓冲:因为producer那面可能业务很简略,而后端consumer业务会很简单并有数据库的操作,因而必定是producer会比consumer处理速度快,如果没有kafka,producer间接调用consumer,那么就会造成整个零碎的处理速度慢,加一层kafka作为MQ,能够起到缓冲的作用。
  • 异步通信:作为MQ,Producer与Consumer异步通信。

2:kafka一些原理概念

  • 长久化:kafka应用文件存储音讯(append only log),这就间接决定kafka在性能上重大依赖文件系统的自身个性.且无论任何OS下,对文件系统自身的优化是十分艰巨的.文件缓存/间接内存映射等是罕用的伎俩.因为kafka是对日志文件进行append操作,因而磁盘检索的开销是较小的;同时为了缩小磁盘写入的次数,broker会将音讯临时buffer起来,当音讯的个数(或尺寸)达到肯定阀值时,再flush到磁盘,这样缩小了磁盘IO调用的次数.对于kafka而言,较高性能的磁盘,将会带来更加间接的性能晋升.
  • 性能:除磁盘IO之外,咱们还须要思考网络IO,这间接关系到kafka的吞吐量问题.kafka并没有提供太多高超的技巧;对于producer端,能够将音讯buffer起来,当音讯的条数达到肯定阀值时,批量发送给broker;对于consumer端也是一样,批量fetch多条音讯.不过音讯量的大小能够通过配置文件来指定.对于kafka broker端,仿佛有个sendfile零碎调用能够潜在的晋升网络IO的性能:将文件的数据映射到零碎内存中,socket间接读取相应的内存区域即可,而无需过程再次copy和替换(这里波及到"磁盘IO数据"/"内核内存"/"过程内存"/"网络缓冲区",多者之间的数据copy)。
    其实对于producer/consumer/broker三者而言,CPU的开销应该都不大,因而启用消息压缩机制是一个良好的策略;压缩须要耗费大量的CPU资源,不过对于kafka而言,网络IO更应该须要思考.能够将任何在网络上传输的音讯都通过压缩.kafka反对gzip/snappy等多种压缩形式
  • 负载平衡:kafka集群中的任何一个broker,都能够向producer提供metadata信息,这些metadata中蕴含"集群中存活的servers列表"/"partitions leader列表"等信息(请参看zookeeper中的节点信息). 当producer获取到metadata信息之后, producer将会和Topic下所有partition leader放弃socket连贯;音讯由producer间接通过socket发送到broker,两头不会通过任何"路由层".
    异步发送,将多条音讯暂且在客户端buffer起来,并将他们批量发送到broker;小数据IO太多,会拖慢整体的网络提早,批量提早发送事实上晋升了网络效率;不过这也有肯定的隐患,比方当producer生效时,那些尚未发送的音讯将会失落。
  • Topic模型:其余JMS实现,音讯生产的地位是有prodiver保留,以便防止反复发送音讯或者将没有生产胜利的音讯重发等,同时还要管制音讯的状态.这就要求JMS broker须要太多额定的工作.在kafka中,partition中的音讯只有一个consumer在生产,且不存在音讯状态的管制,也没有简单的音讯确认机制,可见kafka broker端是相当轻量级的.当音讯被consumer接管之后,consumer能够在本地保留最初音讯的offset,并间歇性的向zookeeper注册offset.由此可见,consumer客户端也很轻量级。
    kafka中consumer负责保护音讯的生产记录,而broker则不关怀这些,这种设计不仅进步了consumer端的灵活性,也适度的加重了broker端设计的复杂度;这是和泛滥JMS prodiver的区别.此外,kafka中音讯ACK的设计也和JMS有很大不同,kafka中的音讯是批量(通常以音讯的条数或者chunk的尺寸为单位)发送给consumer,当音讯生产胜利后,向zookeeper提交音讯的offset,而不会向broker交付ACK.或者你曾经意识到,这种"宽松"的设计,将会有"失落"音讯/"音讯重发"的危险。
  • 音讯传输统一:Kafka提供3种音讯传输一致性语义:最多1次,起码1次,恰好1次。
    起码1次:可能会重传数据,有可能呈现数据被反复解决的状况;
    最多1次:可能会呈现数据失落状况;
    恰好1次:并不是指真正只传输1次,只不过有一个机制。确保不会呈现“数据被反复解决”和“数据失落”的状况。
    at most once: 消费者fetch音讯,而后保留offset,而后解决音讯;当client保留offset之后,然而在音讯处理过程中consumer过程生效(crash),导致局部音讯未能持续解决.那么尔后可能其余consumer会接管,然而因为offset曾经提前保留,那么新的consumer将不能fetch到offset之前的音讯(只管它们尚没有被解决),这就是"at most once".
    at least once: 消费者fetch音讯,而后解决音讯,而后保留offset.如果音讯解决胜利之后,然而在保留offset阶段zookeeper异样或者consumer生效,导致保留offset操作未能执行胜利,这就导致接下来再次fetch时可能取得上次曾经解决过的音讯,这就是"at least once".
    "Kafka Cluster"到消费者的场景中能够采取以下计划来失去“恰好1次”的一致性语义:起码1次+消费者的输入中额定减少已解决音讯最大编号:因为已解决音讯最大编号的存在,不会呈现反复解决音讯的状况。
  • 正本:kafka中,replication策略是基于partition,而不是topic;kafka将每个partition数据复制到多个server上,任何一个partition有一个leader和多个follower(能够没有);备份的个数能够通过broker配置文件来设定。leader解决所有的read-write申请,follower须要和leader放弃同步.Follower就像一个"consumer",生产音讯并保留在本地日志中;leader负责跟踪所有的follower状态,如果follower"落后"太多或者生效,leader将会把它从replicas同步列表中删除.当所有的follower都将一条音讯保留胜利,此音讯才被认为是"committed",那么此时consumer能力生产它,这种同步策略,就要求follower和leader之间必须具备良好的网络环境.即便只有一个replicas实例存活,依然能够保障音讯的失常发送和接管,只有zookeeper集群存活即可.
    抉择follower时须要兼顾一个问题,就是新leader server上所曾经承载的partition leader的个数,如果一个server上有过多的partition leader,意味着此server将接受着更多的IO压力.在选举新leader,须要思考到"负载平衡",partition leader较少的broker将会更有可能成为新的leader.
  • 分布式:kafka应用zookeeper来存储一些meta信息,并应用了zookeeper watch机制来发现meta信息的变更并作出相应的动作(比方consumer生效,触发负载平衡等)。
    Broker node registry: 当一个kafka broker启动后,首先会向zookeeper注册本人的节点信息(长期znode),同时当broker和zookeeper断开连接时,此znode也会被删除.
    Broker Topic Registry: 当一个broker启动时,会向zookeeper注册本人持有的topic和partitions信息,依然是一个长期znode.
    Consumer and Consumer group: 每个consumer客户端被创立时,会向zookeeper注册本人的信息;此作用次要是为了"负载平衡".一个group中的多个consumer能够交织的生产一个topic的所有partitions;简而言之,保障此topic的所有partitions都能被此group所生产,且生产时为了性能思考,让partition绝对平衡的扩散到每个consumer上.
    Consumer id Registry: 每个consumer都有一个惟一的ID(host:uuid,能够通过配置文件指定,也能够由系统生成),此id用来标记消费者信息.
    Consumer offset Tracking: 用来跟踪每个consumer目前所生产的partition中最大的offset.此znode为长久节点,能够看出offset跟group_id无关,以表明当group中一个消费者生效,其余consumer能够持续生产.
    Partition Owner registry: 用来标记partition正在被哪个consumer生产.长期znode。此节点表白了"一个partition"只能被group下一个consumer生产,同时当group下某个consumer生效,那么将会触发负载平衡(即:让partitions在多个consumer间平衡生产,接管那些"游离"的partitions)。
    当consumer启动时,所触发的操作:
    A) 首先进行"Consumer id Registry";
    B) 而后在"Consumer id Registry"节点下注册一个watch用来监听以后group中其余consumer的"leave"和"join";只有此znode path下节点列表变更,都会触发此group下consumer的负载平衡.(比方一个consumer生效,那么其余consumer接管partitions).
    C) 在"Broker id registry"节点下,注册一个watch用来监听broker的存活状况;如果broker列表变更,将会触发所有的groups下的consumer从新balance.
    总结:
    1) Producer端应用zookeeper用来"发现"broker列表,以及和Topic下每个partition leader建设socket连贯并发送音讯.
    2) Broker端应用zookeeper用来注册broker信息,曾经监测partition leader存活性.
    3) Consumer端应用zookeeper用来注册consumer信息,其中包含consumer生产的partition列表等,同时也用来发现broker列表,并和partition leader建设socket连贯,并获取音讯。
  • Leader的抉择:Kafka的外围是日志文件,日志文件在集群中的同步是分布式数据系统最根底的因素。
    如果leaders永远不会down的话咱们就不须要followers了!一旦leader down掉了,须要在followers中抉择一个新的leader.然而followers自身有可能延时太久或者crash,所以必须抉择高质量的follower作为leader.必须保障,一旦一个音讯被提交了,然而leader down掉了,新选出的leader必须能够提供这条音讯。大部分的分布式系统采纳了少数投票法令抉择新的leader,对于少数投票法令,就是依据所有正本节点的情况动静的抉择最适宜的作为leader.Kafka并不是应用这种办法。
    Kafka动静保护了一个同步状态的正本的汇合(a set of in-sync replicas),简称ISR,在这个汇合中的节点都是和leader放弃高度一致的,任何一条音讯必须被这个汇合中的每个节点读取并追加到日志中了,才回告诉内部这个音讯曾经被提交了。因而这个汇合中的任何一个节点随时都能够被选为leader.ISR在ZooKeeper中保护。ISR中有f+1个节点,就能够容许在f个节点down掉的状况下不会失落音讯并失常提供服。ISR的成员是动静的,如果一个节点被淘汰了,当它从新达到“同步中”的状态时,他能够重新加入ISR.这种leader的抉择形式是十分疾速的,适宜kafka的利用场景。
    如果所有节点都down掉了怎么办?Kafka对于数据不会失落的保障,是基于至多一个节点是存活的,一旦所有节点都down了,这个就不能保障了。
    理论利用中,当所有的正本都down掉时,必须及时作出反应。能够有以下两种抉择:
    1:期待ISR中的任何一个节点复原并负责leader。
    2:抉择所有节点中(不只是ISR)第一个复原的节点作为leader.
    这是一个在可用性和连续性之间的衡量。如果期待ISR中的节点复原,一旦ISR中的节点起不起来或者数据都是了,那集群就永远复原不了了。如果期待ISR意外的节点复原,这个节点的数据就会被作为线上数据,有可能和实在的数据有所出入,因为有些数据它可能还没同步到。Kafka目前抉择了第二种策略,在将来的版本中将使这个策略的抉择可配置,能够依据场景灵便的抉择。
    这种困境不只Kafka会遇到,简直所有的分布式数据系统都会遇到。
  • 正本治理:以上仅仅以一个topic一个分区为例子进行了探讨,但实际上一个Kafka将会治理成千上万的topic分区.Kafka尽量的使所有分区平均的散布到集群所有的节点上而不是集中在某些节点上,另外主从关系也尽量平衡这样每个几点都会负责肯定比例的分区的leader.
    优化leader的抉择过程也是很重要的,它决定了零碎产生故障时的空窗期有多久。Kafka抉择一个节点作为“controller”,当发现有节点down掉的时候它负责在游泳分区的所有节点中抉择新的leader,这使得Kafka能够批量的高效的治理所有分区节点的主从关系。如果controller down掉了,活着的节点中的一个会备切换为新的controller.
  • Leader与正本同步:
    对于某个分区来说,保留正分区的"broker"为该分区的"leader",保留备份分区的"broker"为该分区的"follower"。备份分区会齐全复制正分区的音讯,包含音讯的编号等附加属性值。为了放弃正分区和备份分区的内容统一,Kafka采取的计划是在保留备份分区的"broker"上开启一个消费者过程进行生产,从而使得正分区的内容与备份分区的内容保持一致。个别状况下,一个分区有一个“正分区”和零到多个“备份分区”。能够配置“正分区+备份分区”的总数量,对于这个配置,不同主题能够有不同的配置值。留神,生产者,消费者只与保留正分区的"leader"进行通信。
    Kafka容许topic的分区领有若干正本,这个数量是能够配置的,你能够为每个topic配置正本的数量。Kafka会主动在每个正本上备份数据,所以当一个节点down掉时数据仍然是可用的。
    Kafka的正本性能不是必须的,你能够配置只有一个正本,这样其实就相当于只有一份数据。
    创立正本的单位是topic的分区,每个分区都有一个leader和零或多个followers.所有的读写操作都由leader解决,个别分区的数量都比broker的数量多的多,各分区的leader平均的散布在brokers中。所有的followers都复制leader的日志,日志中的音讯和程序都和leader中的统一。followers向一般的consumer那样从leader那里拉取音讯并保留在本人的日志文件中。
    许多分布式的音讯零碎主动的解决失败的申请,它们对一个节点是否着(alive)”有着清晰的定义。Kafka判断一个节点是否活着有两个条件:
  • 节点必须能够保护和ZooKeeper的连贯,Zookeeper通过心跳机制查看每个节点的连贯。
  • 如果节点是个follower,他必须能及时的同步leader的写操作,延时不能太久。
    合乎以上条件的节点精确的说应该是“同步中的(in sync)”,而不是含糊的说是“活着的”或是“失败的”。Leader会追踪所有“同步中”的节点,一旦一个down掉了,或是卡住了,或是延时太久,leader就会把它移除。至于延时多久算是“太久”,是由参数replica.lag.max.messages决定的,怎么算是卡住了,怎是由参数replica.lag.time.max.ms决定的。
    只有当音讯被所有的正本退出到日志中时,才算是“committed”,只有committed的音讯才会发送给consumer,这样就不必放心一旦leader down掉了音讯会失落。Producer也能够抉择是否期待音讯被提交的告诉,这个是由参数acks决定的。
    Kafka保障只有有一个“同步中”的节点,“committed”的音讯就不会失落。