kafka理论知识

Kafka简介

  • Kafka定义:Kafka 是一个高吞吐、分布式、基于发布订阅的消息系统,利用Kafka技术可在廉价PC Server上搭建起大规模消息系统。
  • Kafka应用场景:Kafka和其他组件比较,具有消息持久化、高吞吐、实时等特性,适用于离线和实时的消息消费,如聚合统计系统运营数据(监控数据)、日志收集等大量数据的数据收集场景。

Kafka结构

kafka理论知识

  • 一个典型的Kafka集群中包含若干Producer(可以是web前端产生的Page View,或者是服务器日志,系统CPU、Memory等),若干Broker(Kafka支持水平扩展,一般broker数量越多,集群吞吐率越高),若干Consumer,以及一个Zookeeper集群。
  • Kafka通过Zookeeper管理集群配置,选举Leader,以及在Consumer发生变化时进行rebalance。Producer使用push模式将消息发布到Broker,Consumer使用pull模式从Broker订阅并消费消息。
  • Broker:Kafka集群包含一个或多个服务实例,这些服务实例被称为Broker。
  • Producer:负责发布消息到Kafka Broker。
  • Consumer:消息消费者,从Kafka Broker读取消息的客户端。

Topics

kafka理论知识

Partition

  • 每个topic被分成多个partition(区),每个partition在存储层面对应一个log文件,log文件中记录了所有的消息数据。
  • 引入Partition机制,保证了Kafka的高吞吐能力,因为Topic的多个Partition分布在不同的Kafka节点上,这样一来多个客户端(Producer和Consumer)就可以并发访问不同的节点对一个Topic进行消息的读写。
  • Topic的Partition数量可以在创建时配置。
  • Partition数量决定了每个Consumer group中并发消费者的最大数量。

偏移量

  • 每条消息在文件中的位置称为offset(偏移量),offset是一个long型数字,它唯一标记一条消息。消费者通过(offset、partition、topic)跟踪记录。
  • 任何发布到此Partition的消息都会被直接追加到log文件的尾部。

Partition副本

  • 副本特性:
    1. 副本以分区为单位。每个分区都有各自的主副本和从副本。
    2. 主副本叫做Leader,从副本叫做Follower。Follower通过拉取的方式从Leader中同步数据。
    3. 消费者和生产者都是从Leader中读写数据,不与Follower交互。
  • 为了提高Kafka的容错性,Kafka支持Partition的复制策略,可以通过配置文件配置Partition的副本个数。Kafka针对Partition的复制同样需要选出一个Leader,同时由该Leader负责Partition的读写操作,其他的副本节点只是负责数据的同步。如果Leader失效,那么将会有其他follower来接管(成为新的Leader),如果由于Follower自身的性能,或者网络原因导致同步的数据落后Leader太多,那么当Leader失效后,就不会将这个Follower选为Leader。由于Leader的Server承载了全部的请求压力,因此从集群的整体考虑,Kafka会将Leader均横的分散在每个实例上,来确保整体的性能稳定。一个Kafka集群各个节点间可能互为Leader和Flower。
  • Kafka中partition replication之间同步数据,从partition的leader复制数据到follower只需要一个线程(ReplicaFetcherThread),实际上复制是follower(一个follower相当于consumer)主动从leader批量拉取消息的,这极大提高了吞吐量。
  • Kafka中每个Broker启动时都会创建一个副本管理服务(ReplicaManager),该服务负责维护ReplicaFetcherThread与其他Broker链路连接关系。该Broker中存在的Follower partitions对应的leader partitions分布在不同的Broker上,这些Broker创建相同数量的ReplicaFetcherThread线程同步对应partition数据。Kafka中partition间复制数据是由follower(扮演consumer角色)主动向leader获取消息, follower每次读取消息都会更新HW状态(High Watermark,用于记录当前最新消息的标识)。每当Follower的partitions发生变更而影响leader所在Broker时,ReplicaManager就会新建或销毁相应的ReplicaFetcherThread。简单的说就是,follower启动一线程用于同步leader数据。

Logs

kafka理论知识

  • Kafka把Topic中一个Parition大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。
  • 为了使得Kafka的吞吐率可以线性提高,物理上把Topic分成一个或多个Partition,每个Partition在物理上对应一个文件夹,该文件夹下存储这个Partition的所有消息和索引文件。
  • segment:
    1. segment file组成:由2大部分组成,分别为index file和data file,此2个文件一 一对应,成对出现,后缀“.index”和“.log”分别表示为segment索引文件、数据文件。
    2. segment文件命名规则:partion全局的第一个segment从0开始,后续每个segment文件名为上一个全局partion的最大offset(偏移message数)。数值最大为64位long大小,19位数字字符长度,没有数字用0填充。
  • Kafka的存储布局非常简单。Topic的每个分区对应一个逻辑日志。物理上,一个日志为相同大小的一组分段文件。每次生产者发布消息到一个分区,代理就将消息追加到最后一个段文件中。当发布的消息数量达到设定值或者经过一定的时间后,段文件真正写入磁盘中。写入完成后,消息公开给消费者。同一个topic下有不同分区,每个分区下面会划分为多个文件,只有一个当前文件在写,其他文件只读。当写满一个文件(写满的意思是达到设定值)后,新建一个空文件用来写,老的文件切换为只读。文件的命名以起始偏移量来命名。
  • 一个日志文件默认1G,当达到1G的时候,创建新的log文件和index文件。如果参数设置过小,则会产生大量的log文件和index文件,系统在启动时,需要加载大量index到内存,占用大量句柄。如果设置太大,分段文件比较少,不利于快速查找消息。
  • 通过索引信息可以快速定位message。
  • 使index元数据全部映射到memory,可以避免segment file的index数据IO磁盘操作。
  • 索引文件稀疏存储,可以大幅降低index文件元数据占用空间大小。稀疏存储,即将原来的完整数据,只间隔的选择多条进行存储。例如:针对100条数据,只存储了1、20、40、60、80条的数据位置,这样如果要查找第23条数据,则直接在index中找到20的位置,再偏移3条即得到。

删除信息

  • 对于传统的message queue而言,一般会删除已经被消费的消息,而Kafka集群会保留所有的消息,无论其被消费与否。当然,因为磁盘限制,不可能永久保留所有数据(实际上也没必要),因此Kafka提供两种策略删除旧数据。
  • 日志的清理方式有两种:delete 和 compact。
  • 删除的阈值有两种:过期的时间和分区内总日志大小。
配置参数 默认值 参数解释 取值范围
log.cleanup.policy delete 当日志过期时(超过了要保存的时间),采用的清除策略,可以取值为删除或者压缩。 delete或compact
log.retention.hours 168 日志数据文件保留的最长时间。单位:小时。 1 ~ 2147483647
log.retention.bytes -1 指定每个Partition上的日志数据所能达到的最大字节。默认情况下无限制。单位:字节。 -1 ~ 9223372036854775807

消息传输保障

消息传输保障通常有以下三种:

  • 最多一次(At Most Once)
    消息可能丢失。 消息不会重复发送和处理。
  • 最少一次(At Lease Once)
    消息不会丢失。消息可能会重复发送和处理。
  • 仅有一次(Exactly Once)
    消息不会丢失。消息仅被处理一次。

消息传输场景

  • 同步发送:client每写一条,发送一条到broker。可靠性高,常用。
  • 异步发送:client先将数据写入一buffer,待写入达到一定条数后,将buffer内数据一次性发送到broker。容易造成数据丢失,一般不用。
  • 同步复制、异步复制与同步发送、异步发送原理相同。常用同步发送带确认+同步复制。

写数据

Producer连接任意存活的Broker,请求制定Topic、Partition的Leader元数据信息,然后直接与对应的Broker直接连接,发布数据。

读数据

Consumer连接指定TopicPartition所在的LeaderBroker,用主动获取方式从Kafka中获取消息。