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和storm1.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。![image.png](/img/bVcSl2y)- 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切换,会导致丢数据。                                  ![image.png](/img/bVcSl4b)                                  - 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条数据。                                                                                                                                                                                       https://www.cnblogs.com/cxxjohnson/p/8921661.html