Kafka是一个高吞吐量、分布式的发布—订阅消息系统,定义为分布式流式处理平台。
- 主题:将一组消息抽象归纳为一个主题(Topic),一个主题对应着消息的一个分类。
- 消息:消息是kafka通信的基本单位,由一个固定长度的消息头和可变长度的消息体构成。
- 分区(Partition):一组消息归纳为主题,而每个主题又被分成一个或多个分区,每个分区由一些列有序、不可变的消息组成,是一个有序队列。每个分区在物理上对应为一个文件夹,分区的命名规则为主题名称后接“—”连接符,之后再接分区编号,分区编号从0开始,编号最大值为分区的总数减1
- 副本(Replica):每一个分区又有一个或多个副本,分区的副本分布在不同集群的不同代理上,以提高可用性,分区的副本可抽象为一个日志对象,即分区的副本与日志对象是一一对于的。
分区使kafka在并发处理上更加高效,同时也保证消息被顺序消费以及对消息进行负载均衡,只能保证同一分区的消息有序性,跨分区消息不能保证有序性,每条消息被追加到相应的分区中,是顺序写磁盘,因此效率非常高,这是Kafka高吞吐率的一个重要保证。当然kafka不会立即删除已消费的消息,会存在磁盘。提供两种删除的策略:1.基于消息存储的时间长度。2.基于分区的大小
- Leader副本和Follower副本:由于副本的存在,就需要保证一个分区和多个副本之间的数据一致性,kafka会选择该分区的一个副本作为leader,只有leader副本才会负载处理客户端的读写请求,follower只负责从leader同步数据,
- 偏移量:任何发布到分区的消息会被追加到日志文件的尾部,而每条消息在日志文件中的位置都会对应一个按序递增的偏移量。可以控制消息偏移量来对消息进行消费,不会影响文件中的偏移量,消费的偏移量保存在kafka内置主题中。
- 日志段:一个日志又被划分为多个日志段,是日志对象分片的最小单位。日志段对应磁盘上一个具体日志文件和两个索引文件。日志文件是以“.log”为文件名后缀的数据文件,用于保存消息实际数据。两个索引文件分别以“.index”和“.timeindex”作为文件名后缀,分别表示消息偏移量索引文件和消息时间戳索引文件。
- 代理(Broker):一个kafka实例称为Broker,在一个Kafka集群中,每增加一个代理就需要为这个代理配置一个与该集群中其他代理不同的id, id值可以选择任意非负整数即可,只要保证它在整个Kafka集群中唯一,这个id就是代理的名字,也就是在启动代理时配置的broker.id对应的值,因此在本书中有时我们也称为brokerId。
- 生产者:将消息发送到Broker。
- 消费者和消费者组:消费者已拉取(pull)的方式拉取数据,每一个消费者属于一个特定的消费者组,我们可以为每个消费者指定一个消费组,以groupId代表消费组名称,通过group.id配置设置,如果不指定消费组,则该消费者属于默认消费组test-consumer-group。每个消费者也有一个全局唯一的id,通过配置项client.id指定,如果客户端没有指定消费者的id, Kafka会自动为该消费者生成一个全局唯一的id,格式为${groupId}-${hostName}-${timestamp}-${UUID前8位字符}。同一主题的一条消息只能被同一消费者组下的某一个消费者消费,但不同消费者组之间可以重复消费。消费者组是kafka实现对一个主题消息进行单播和广播的手段,实现广播只需要指定订阅同意主题的各个消费者属于不同消费者组即可。单播则让各个消费者属于同一消费者组。
- ISR:Kafka在ZooKeeper中动态维护了一个ISR(In-sync Replica),即保存同步的副本列表,该列表中保存的是与Leader副本保持消息同步的所有副本对应的代理节点id,如果一个Follower副本宕机或落后太多,则该Follower副本节点将从ISR列表中移除。
- ZooKeeper:zk在kafka中的角色定义:Kafka利用ZooKeeper保存相应元数据信息,Kafka元数据信息包括如代理节点信息、Kafka集群信息、旧版消费者信息及其消费偏移量信息、主题信息、分区状态信息、分区副本分配方案信息、动态配置信息等。Kafka在启动或运行过程当中会在ZooKeeper上创建相应节点来保存元数据信息,Kafka通过监听机制在这些节点注册相应监听器来监听节点元数据的变化,从而由ZooKeeper负责管理维护Kafka集群,同时通过ZooKeeper我们能够很方便地对Kafka集群进行水平扩展及数据迁移。
应用场景:
- 具有高吞吐量来支持诸如实时的日志采集这个的大规模事件流。
- 能够很好地处理大量积压的数据,以便能够周期性地加载离线数据进行处理。
- 能够低延迟处理传统消息应用场景。
- 能够支持分区、分布式,实时地处理消息,同时具有容错保障机制。
特性:
- 消息持久化:依赖于文件系统来存储消息,文件系统存储速度快慢取决于磁盘(如何配置和使用磁盘)(使用文件系统和依赖于页缓存(page cache)的存储比维护一个内存的存储或是应用其他结构来存储消息更有优势,因此Kafka选择以文件系统来存储数据)。由于消息进行了持久化,在kafka宕机重启时,已存储的消息可以继续恢复使用,能够很好的支持在线或离线处理、与其他存储及流处理框架的继承。
- 高吞吐量:Kafka将数据写到磁盘,充分利用磁盘的顺序读写。同时,Kafka在数据写入及数据同步采用了零拷贝(zero-copy)技术,采用sendFile()函数调用,sendFile()函数是在两个文件描述符之间直接传递数据,完全在内核中操作,从而避免了内核缓冲区与用户缓冲区之间数据的拷贝,操作效率极高。Kafka还支持数据压缩及批量发送,同时Kafka将每个主题划分为多个分区,这一系列的优化及实现方法使得Kafka具有很高的吞吐量。
- 扩展性:kafka是依赖于zk来对集群进行协调管理,使得kafka更加容易进行水平扩展,集群能够自动感知,重新进行负责均衡及数据复制。
- 数据备份:为每个主题指定副本数,对数据进行持久化备份。
- 轻量级:broker是无状态的,不会记录消息是否已消费,消费的偏移量的管理交由消费者自己或组协调器来维护。同时集群本身几乎不需要生产者和消费者的状态信息,这就使得Kafka非常轻量级,同时生产者和消费者客户端实现也非常轻量级。
- 消息压缩:Kafka支持Gzip、Snappy、LZ4这3种压缩方式,通常把多条消息放在一起组成MessageSet,然后再把MessageSet放到一条消息里面去,从而提高压缩比率进而提高吞吐量。
kafka组件
- 延迟操作组件:该组件可以辅助Kafka其他组件完成相应的功能,如协助客户端处理创建主题操作、协助组协调器(GroupCoordinator)处理JoinGroupRequest和HeartbeatRequest请求、协助副本管理器(ReplicaManager)处理ProduceRequest和FetchRequest请求。
- 控制器:在启动Kafka集群时,每一个代理都会实例化并启动一个KafkaController,并将该代理的brokerId注册到ZooKeeper的相应节点当中。Kafka集群中各代理会根据选举机制选出其中一个代理作为Leader,即Leader控制器。控制器负责主题的创建与删除、分区和副本的管理以及代理故障转移处理等。当控制器所在代理发生故障或ZooKeeper通过心跳机制感知控制器与自己的连接Session已过期时,也会再次从所有代理中选出一个节点作为集群的控制器。选举核心:Kafka控制器选举的核心思想就是各代理通过争抢向/controller节点请求写入自身的信息,先成功写入的代理即为Leader。故障转移:触发控制器进行选举有3种情况:一是在控制器启动的时候,二是当控制器发生故障转移的时候,三是当心跳检测超时的时候。因此,我们说控制器故障转移的本质是控制权的转移,而控制权的转移也就是重新选出新的控制器。
kafka stream
流(stream)是Kafka Streams提供的最重要的抽象,它代表的是一个无限的、不断更新的数据集。一个流就是由一个有序的、可重放的、支持故障转移的不可变的数据记录(data record)序列,其中每个数据记录被定义为一个键值对。
KStream是一个由键值对构成的抽象记录流,每个键值对是一个独立单元,即使相同的Key也不会被覆盖,类似数据库的插入操作;KTable可以理解成一个基于表主键的日志更新流,相同Key的每条记录只保存最新的一条记录,类似数据库基于主键更新