kafka-一些我在学习中的理解

组件结构

  • 定位:流式处理平台
  • 做用:消息中间件、存储系统、实时流处理
  • kafka组件:消费者、生产者、topic、broker、streams、connecter
  • 一个典型的Kafka集群中包含若干Producer(能够是web前端产生的Page View,或者是服务器日志,系统CPU、Memory等),若干broker(Kafka支持水平扩展,通常broker数量越多,集群吞吐率越高),若干Consumer Group,以及一个Zookeeper集群。Kafka经过Zookeeper管理集群配置,选举leader,以及在Consumer Group发生变化时进行rebalance。Producer使用push模式将消息发布到broker,Consumer使用pull模式从broker订阅并消费消息。
  • broker : 经纪人,至关于一个kafka服务器,管理该服务器中的全部不一样topic 的分区
  • topic:至关于一个消息队列,能够将topic进行分区,全部分区组合起来为一个topic的全部消息。分区能够分布在不一样的服务器也能够分布在同一服务器。
  • 分区(partition):topic的物理上的分区,每一个partition是一个有序的队列,每一个分区又会有leader 分区 和 follower 分区,全部的消费请求所有由leader处理,follower被动备份leader中的数据分布在kafka集群中不一样的服务器中,当leader挂了以后,在follower中选择一个做为leader提供服务。partition由多个 segment文件组成(log文件)。消费者能够指定分区,生产者也能够指定分区,这种设计风格,让消费者能够对敏感性的消息进行局部处理。
  • offset:partition中的每一个消息都有一个连续的序列号叫作offset,用于partition惟一标识一条消息.
  • segment文件:partition物理上由segment文件组成,
  • 消费模式:点对点模式(队列模式,一个消费者对应一个消息队列,每一个消费队列也只能对应一个),发布订阅模式(topic 与 消费者为多多对应关系 )
  • kafka中的消费模式实现,kafka为这两种的消费模型提供了统一的消费者抽象模型:消费者组
    • 点对点模式:消费组的概念,假设一个topic被消费,全部的消费这个topic的消费者都在一个消费组中,那么就能够看做是点对点模式了
    • 发布订阅模式:一个topic被消费,全部消费这个topic的消费者再也不一个组中,多个组消费同一个topic 那么就是该模型
  • 消费者组:每一个消费者都有消费者组标识,标识本身属于哪个消费者组,消费者组去订阅topic,topic的数据被消费者组的消费者均分,一个分区对应一个消费者。若是一个消费者组有3个实例,一个topic有2个分区,则会有一个消费者永远获取不到数据。 一个消费者组只能对应一个topic,组中的每一个消费者对应topic的一个分区,在初始化阶段,消费者随机选择分区(也能够手动分配不过较复杂)。一个topic能够被多个消费者组消费。topic和消费者组是一对多的关系。因此,注意相同的消费者组中不能有比分区更多的消费者,不然多出的消费者一直处于空等待,不会收到消息。
  • streams:负责处理消息在kafka中的流转,信息流的处理直接使用producer和consumer API进行简单的处理。对于复杂的转换,Kafka提供了更强大的Streams API。可构建聚合计算或链接流到一块儿的复杂应用程序。完成实时流处理。 Sterams API在Kafka中的核心:使用producer和consumer API做为输入,利用Kafka作状态存储,使用相同的组机制在stream处理器实例之间进行容错保障。
  • connecter:负责将kafka链接到不一样的数据存储系统,好比mysql数据库,txt文件等
  • 消息顺序性:kafka只能保证一个topic中一个分区的消息顺序性,一个topic中的多个分区没法保证顺序一致性,要想保证一个topic的顺序一致性只能将topic 设定为一个分区。
  • 复制因子: 是相对于topic的分区来定义的,若是一个topic的复制因子设置为N,分区的leader+follower的数量为N,则该topic容许N-1服务器宕机而不丢失任何已经提交(committed)的消息。

存储结构

  • 文件系统具体看另外一篇笔记
  • kafka文件系统:指的是partition中segment文件(log、index)的存储结构
  • kafka使用文件系统并依赖页缓存(page cache)来保证在宕机缓存保持可用、存储大量消息的状况下的常数复杂度获取消息数据。
  • 每一个topic的partition是一个大文件夹,里面有许多segment文件夹,
  • 页缓存是将磁盘中的对应的数据页加载到预先分配好的内存中等待进程使用,具备预读和替换的功能。
  • 当内存空间耗尽时,能够将消息数据 flush到磁盘中,而没必要要尽量的把数据维持在内存中。
  • kafka的存储是以页缓存为中心进行设计的
  • 设计存储结构的主要目的:提升磁盘利用率和消息处理性能。
  • 事实上,kafka无需任何性能损失既能够访问几乎无限制的磁盘空间,这意味着能够提供通常消息传递系统没法提供的特性。 例如,在Kafka中,消息被消费后不是立马被删除,咱们能够保留消息相对较长的时间(例如一个星期)。 这将为消费者带来很大的灵活性
  • 如何保证常数时间复杂度获取消息
    • 选择消费的topic
    • 负载均衡找到对应的partition,非初次则找到该消费线程对应的partition
    • 根据记录的offset二分法查找partition对应segment文件(log file and index file),并将其读入到页缓存中,采用零拷贝的方式将所需数据发送到网卡缓冲区 O(1)
    • 查找对应index文件,在index文件中找到对应的物理地址,找到消息

高吞吐量

Kafka 高吞吐依赖的主要有三点:前端

  1. micro-batch处理方式,也就是当前Spark Streaming(实时流处理框架)所使用的模式,不是一条条的发送消息,而是一小批一小批的处理。经过微乎其微的延时消耗换取吞吐量几百倍的提高。这种方式也更让Kafka像是一个流处理框架,而且如今Kafka也已经被用于一些流处理的场景了。 Kafka经过递归消息集来支持这一点。 一批消息能够一块儿压缩并以此形式发送到服务器。 这批消息将以压缩形式写入,并将在日志中保持压缩,而且只能由消费者解压缩。Kafka支持GZIP和Snappy压缩协议
  2. 使用追加写的方式(顺序写):这一点相当重要,咱们知道在普通的机械硬盘中随机读写和顺序读写速度差别彻底不是一个数量级的,SSD顺序读、机械硬盘顺序读的速度甚至比内存的随机读速度还要高。熟知操做系统的话,都很清楚磁盘读写操做的主要时间消耗是由于机械操做的循道等消耗。
  3. Linux中的sendfile的零拷贝加持,所谓的零拷贝其实就是本来一份数据的IO是须要通过屡次copy操做&内核态与用户态的上下文切换,读内核态缓存到应用程序缓存再从应用程序缓存到Socket缓存完成具体的IO操做,而sendFile系统调用零拷贝就是避免了上下文切换带来的copy操做,同时利用直接存储器访问技术(DMA)执行IO操做,避免了内核缓冲区以前的数据拷贝操做。上升到上层的语言操做,就是使用的Java中的FileChannel.transferTo方法进行实现的。(Kafka 1版本使用的是Scala,2版本开始就是使用Java 了这二者都是在JVM上执行的,本质.class 文件解析执行阶段实际上是一致的)

非零拷贝:用户进程获取数据而且将数据经过网络发送到调用者方的过程须要四次数据拷贝,两次系统调用,两次用户态内核态上下文切换: 1:操做系统经过DMA将数据从磁盘拷贝到内核空间的页缓存中 2:经过系统调用将页缓存的数据拷贝到用户进程的空间缓存中 3:用户进程要经过网络将数据发送到目标方,则须要经过系统调用将用户进程的缓存数据发送到内核空间中的socket缓存中 4:内核空间中操做系统经过DMA将socket 缓存中的数据发送到网卡缓冲区中mysql

零拷贝(zero-copy):kafka使用sendfile()方式,只有消费(pull)消息时才会适用零拷贝,push消息时可能会对消息进行一些处理,这必需要将数据拷贝到用户态进行处理。 数据传送只发生的内核空间,没有上下文切换,容许操做系统直接将页缓存中的数据发送到网络中,过程为: 1:操做系统经过DMA将数据从磁盘拷贝到内核空间的页缓存中 2:将带有文件位置和长度信息的缓冲区描述符添加socket缓冲区,这一步不复制页缓存中的数据 3:操做系统经过描述符信息直接将页缓存中的数据发送到网卡缓冲区 零拷贝技术有多种,每一种有其适用场景和局限性,好比上述kafka适用的零拷贝技术就是使用的sendfile,而且须要硬件已经驱动程序支持(好比上述的第三步就须要硬件和驱动程序来支持了),其余的还有mmap、splice等具体请看:linux中零拷贝技术笔记linux

  1. 标准化二进制数据格式,在consumer、products、broker中间的流转的消息数据块采用同一种二进制格式,减小格式转换,提升吞吐量
  2. 数据压缩传输,kafka支持多种数据压缩格式。

负载均衡&故障转移

  • 负载均衡nginx

    • kafka是一种分布式的消息系统,要作负载均衡,也就是要作到均匀分配到全部参与工做的服务器。这里Kafka使用的是分区只能领导者选举,也就是来均匀的选择分区,保证各个分区收到的请求消息都是大体均匀的。
    • Kafka中有一个叫作partition的概念,也就是分区选择器,默认使用的是murmur2Hash 算法计算消息key值的hash值,而后对于总分区数进行求模获得对应的目标分区号,murmur2Hash是一种比较先进的Hash算法,而且在有规律的输入时也能保证分布较为均匀,使用这个算法的还有redis(当字典被用做数据库的底层实现或者hash键的底层实现时,来计算键的哈希值)、nginx、Hadoop。除此以外,使用者能够自定义对应的
  • 故障转移web

    • 常见的故障转移实现策略的关键一般是故障发现,Kafka依赖的是zk的 心跳检测机制,当一台Kafka服务器启动后将会话注册到Zookeeper中,
    • zk不停的对节点进行心跳检测,故障发生时与Zookeeper的会话没法维持致使链接超时从而发现故障,此时请求就再也不打到这台机器,而且选举出一台新的Kafka服务器来替代这台故障的Kafka服务器。 另一种状况,若是节点为一个slave,那么不能落后leader太多。这也会致使将该节点断定为故障,这里的落后太多可能两个缘由致使一个是网络太慢致使复制太慢从而落后太多,另一个就是卡主好屡次leader 向slave复制都没有做用。 落后是经过replica.lag.max.messages配置控制,卡住是经过replica.lag.time.max.ms配置控制的。

伸缩性

如何轻易的向kafka集群中增长计算资源,而且保证计算资源尽量的线形叠加。在分布式系统中伸缩性一直是一个较大的问题,由于仅仅是增长机器资源一般会由于一些隐藏的单点瓶颈致使没法线线形扩容,好比说最大的因素就是服务状态的保存。“状态的处理”好比一致性,须要维持状态的一致性就须要浪费大量的cpu资源,因此为了下降这种消耗,Kafka将绝大部分的状态保存及维持相关的交给kafka controller(被zk选举出来的broker) 统一管理。Kafka 服务器内部仅维持少许暂时须要的状态。redis

每一条消息被发送到Kafka中,其会根据必定的规则选择被存储到哪个partition中。若是规则设置的合理,全部的消息能够均匀分布到不一样的partition里,这样就实现了水平扩展算法

消费与生产消息

  • 消费者消费消息所采用的方式:pull或者push?
    • 这里的pull和push都是相对于消费者来讲的
    • 第一种是服务器push给消费者,优势是一点服务端数据有变消费者能够立马感知到变化,缺点是没法预估消费者消费能力可能形成消息堆积
    • 第二种消费者主动pull服务器,优势能够适应消费者自身的消费速度还能够消费者指定消费消息量批处理传输消息,缺点是若是服务器没有数据,则消费者会一直轮询服务器形成计算机资源浪费,优化的手段能够采用long poll长轮询。
    • 在kafka中使用的是pull加long poll的方式
  • 如何保证消费者与broker消费的消息达成一致?
    • kafka也没法达成彻底一致,可是对一致性作了轻量化处理,其处理方式为,每一个topic的partition彻底有序,每个partition只对应消费组中的一个消费者,这样消费者在每一个分区中的位置只须要一个整数(offset)便可。这可使得已经消费到哪里位置的状态变得特别小,每一个分区只有一个数字,能够进行按期检查,这样的设计使得消息的应答(消费者消费消息的确认)更加轻量。
    • 这种非彻底一致性可能致使消息的重复消费,好比:消费者消费了数据,可是应答数据在网络中丢失,这就会致使offset不是最新的,致使消息重复消费
  • kafka对于消费者和生产者默认支持的是“至少一次(at lwast once)”语义
    • 读取消息->处理消息->ack到broker->修改offset
    • 只要“ack到broker”这步丢失,那么消息可能会重复消费,这也知足最少一次语义。
  • broker如何保证生产者消息不重复?
    • 在版本0.11以后,kafka提供幂等性机制,broker为每一个生产者分配一个ID,并经过生产者发送的序列号为每一个消息进行去重。即便生产者push消息后“收到确认”在网络中丢失致使从新发送message,在broker中也不会保存重复的message。

若是您不一样理解,请在评论出指出,共同窗习!sql

若是感受这篇文章对您有所帮助,请点击一下“喜欢”或者“关注”博主,您的喜欢和关注将是我前进的最大动力!数据库

相关文章
相关标签/搜索