kafka核心概念讲解

1、borker

broker能够理解成一个kafka服务node,是一个运行的kafka服务。broker与broker之间是平等的关系,任意broker均可以down机而不影响其余broker正常工做。kafaka在启动的时候,会将本身的信息同步到zk上。数据存储使用了zk的零时节点,broker须要经过心跳机制维护与zk的注册关系,一旦broker宕机,zk上面对应的零时节点也会被删除。

kafka Controller

咱们能够把controller当成集群的管理者,集群中borker启动时若是没有controller回主动的去zk上注册znode节点来抢夺controller的位置,注册成功的broker会被当选为kafka controller。若当前的controller宕机其余borker会从从新进入controller争抢流程,从而选出新的controller。controller主要的功能以下:html

  • UpdateMetadataRequest:更新元数据请求。topic分区状态常常会发生变动(好比leader从新选举了或副本集合变化了等)。因为当前clients只能与分区的leader broker进行交互,那么一旦发生变动,controller会将最新的元数据广播给全部存活的broker。具体方式就是给全部broker发送UpdateMetadataRequest请求
  • CreateTopics: 建立topic请求。当前不论是经过API方式、脚本方式抑或是CreateTopics请求方式来建立topic,作法几乎都是在Zookeeper的/brokers/topics下建立znode来触发建立逻辑,而controller会监听该path下的变动来执行真正的“建立topic”逻辑。
  • DeleteTopics:删除topic请求。和CreateTopics相似,也是经过建立Zookeeper下的/admin/delete_topics/<topic>节点来触发删除topic,controller执行真正的逻辑
  • 分区重分配:即kafka-reassign-partitions脚本作的事情。一样是与Zookeeper结合使用,脚本写入/admin/reassign_partitions节点来触发,controller负责按照方案分配分区
  • Preferred leader分配:preferred leader选举当前有两种触发方式:1. 自动触发(auto.leader.rebalance.enable = true);2. kafka-preferred-replica-election脚本触发。二者“玩法”相同,向Zookeeper的/admin/preferred_replica_election写数据,controller提取数据执行preferred leader分配
  • 分区扩展:即增长topic分区数。标准作法也是经过kafka-reassign-partitions脚本完成,不过用户可直接往Zookeeper中写数据来实现,好比直接把新增分区的副本集合写入到/brokers/topics/<topic>下,而后controller会为你自动地选出leader并增长分区
  • 集群扩展:新增broker时Zookeeper中/brokers/ids下会新增znode,controller自动完成服务发现的工做
  • broker崩溃处理:一样地,controller经过Zookeeper可实时侦测broker状态。一旦有broker挂掉了,controller可当即感知并为受影响分区选举新的leader
  • ControlledShutdown:broker除了崩溃,还能“优雅”地退出。broker一旦自行终止,controller会接收到一个ControlledShudownRequest请求,而后controller会妥善处理该请求并执行各类收尾工做
  • Controller leader选举:controller必然要提供本身的leader选举以防这个全局惟一的组件崩溃宕机致使服务中断。这个功能也是经过Zookeeper的帮助实现的。

2、topic & partiton

Topic至关于传统消息系统MQ中的一个队列queue,能够把topic当成是消息的分类。partiton能够当作是topic的一个分区,目的是突破IO瓶颈。kafka在存储topic日志的时候,将topic分开存储,这样就能将同一个消息的写压力分配到不一样的分区,这样能够提高kafka的总体吞吐能力。为了保证数据的高可用,kafka使用partiton-Replica进行数据备份,若partition leader挂了,kafka controller会自动从partiton-Replica选举新的leader。提到备份不得不提到ISR,这是一个同步备份列表,每当用户添加新的消息时,分区leader成功写入日志后,后必须保证ISR列表里面的备份也成功写入日志后,才能给客户端相应成功。所以ISR列表的备份的日志老是和leader保持一致,在leader宕机的时候,可使用ISR列表的备份取代leader的位置。node

3、log & segment

kafka最终的数据承载是经过log的方式进行,kafka会按照请求的顺序将消息存储到log中。咱们知道一个topic可能会被分配到到个分区partiton来减轻单点负载。每一个partiton实际上在写log的时候也会存在,单个文件大小物理极限的问题。所以kafka引入了segment解决方案,即将日志分段存储。不一样的segment log组合起来的数据就是分区的存储消息数据。为了方便经过offset定位消息,segment log使用first-offset格式进行文件命名,first-offset是该文件存储的第一条消息的offset。这样就能经过消费者提供的offset很快定位到文件,而后经过offset偏移量能够快速定位消息的存储位置。apache

4、producer消息/数据生产者

生产者负责消息的发送,生产者须要指定消息的topic来区分不一样消息。kafka收到消息后经过loadbalance策略,使用hash(message) % topic分片数 决定将数据存储到哪个分片。 而后将message发送到制定分片的leader,leader收到消息后,将消息保存下来,接着等待ISR(a set of in-sync replicas,该列表的备份数据时刻保持和leader数据一致)中的replica消费消息并发送ack,若ISR列表中的备份分区都已经确认收到消息并保存成功后,leader将成功的消息返回给producer以代表,消息被妥善保存。并发

5、consumer [group]消息/数据消费者&offset

与其余消息系统不一样的是:kafka不会复制去保存客服端以前消费了那条消息,以及下一条应当消费那条消息,kafka将这些工做交给了消费客服端来作,所以kafka在消息消费能够作到无状态。offset就是用来保存某个消费组(consumer group)消费的在当前分区日志下的偏移量的。一般状况下,多个客服端在同时消费同一个消息分区消息的时候会存在并发问题,对于offset的控制就会出现问题,这样就会出现消费重复的状况,kafka使用无锁机制解决这个问题。kafka规定,同一个分区(partition)下的数据只能被通一个consumer group中的一个线程消费,这样就避免了不一样线程之间争夺通一个资源,经过这种设计kafka作到了无锁,这样能够避免锁竞争形成效率降低。所以建议consumer group里面的线程数应当和分区数保持一致,这样作能够有效的利用线程资源,线程多了会被浪费掉,少了一个线程可能会处理多个分区的数据。若是你须要多个业务消费同一个消息,因为不一样的consumer group对赞成主题分区的offset是分开存储的,咱们能够建立多个consumer group实现多个线程来消费同一个消息的目的。.net

kafaka如何常量时间复杂度?

写数据:经过上面消息的存储过程能够发现,除了数据存储和备份操做,并无其余耗时操做。路由分区->leader写数据->数据复制,这些操做都和现有数据规模没有任何关系。每次写数据只会在原来的基础上作追加存储。因为kafka使用了顺序存储而不是非随机存储(听说磁盘的顺序存储效率远高于磁盘的随机存储、有时候甚至比内存的随机写效率还高),同时kafka还使用了批量存储的方式减小了对io的操做,提高了io效率。
读数据:consumer在消费某个topic的时候,消费者会将全部的分区数据消费完,kafka要求,同一时刻对同一分区的数据只会被一个线程消费,这样避免了锁操做。同时经过consumer group提供的offset数据,经过kafka的文件存储机制能够快速的定位到一个segment文件,而且经过计算offset偏移量能够快速定位到数据。从整个消费流程来看,数据规模对每一个过程效率是不敏感的。线程

kafaka如何作到高可用的&动态扩展

高可用的解决方案一般是采用数据冗余以及快速恢复来解决的。kafka经过分区数据备份(partition replica)&分区数据分散到不一样的机器以及kafka controller能够快速检测到宕机节点,经过读取节点的分区数据,能够快速从新选取分区leader,以恢复故障。同时在故障的处理过程当中,就算该分区不可用,不往分区写入数据便可,对kafka的数据读取也是没有影响的。kafka使用hash 取余的目的在于均衡负载,并不在于为了经过message能够快速的查找到这个message所在位置,这个不是kafka关注的业务。kafka经过数据复制和快速恢复作到了高可用,同时基于message不关注经过某个具体message的具体存存储位置,所以在扩展kafka的时候,或者在扩展消息分区的时候,不须要进行额为的数据复制操做,下降了扩展时候的成本。设计

引用

更多文章能够访问jframe.cn日志

相关文章
相关标签/搜索