【2】Kafka概念及原理

1、Kafka背景

1.1、Kafka概要

 Apache Kafka是一个开源的、轻量级的、分布式的、可分区的、可复制备份的、基于zookeeper协调管理的分布式流式消息系统。由Scala写成,支持多语言客户端,是由Apache软件基金会开发的一个开源消息系统。
 Kafka最初是由LinkedIn公司开发,并于2011年初开源。2012年10月从Apache Incubator毕业。该项目的目标是为处理实时数据提供一个统一、高通量、低等待的分布式流式平台。
 简单说, Kafka是一个高吞吐量、分布式的发布/订阅消息系统,用于在流式计算中用来缓存数据。

1.2、Kafka基本结构


 生产者负责生产消息,将消息写入Kafka集群,消费者从Kafka集群中拉取消息。

1.3、Kafka基本概念

主题(Topic):Kafka将一组消息抽象归纳为一个主题。主题就是对消息的分类,生产者将消息发送到特定的主题,消费者订阅主题或是主题的某些分区进行消费。

消息(Message):消息是Kafka通信的基本单位,由固定长度的消息头和可变长度的消息体构成。在java重新实现的客户端中,Message被称之为Record。

分区(Partition):Kafka将一组消息归纳为一个主题,再将每个主题换分为一个或多个分区,每个分区是一个有序队列,由一系列有序的、不可变的消息组成。
  每个分区在物理上对应为一个文件夹,分区的命名规则为“”主题-分区编号”,分区编号从 0 开始,编号最大值为分区的总数减 l 。
  分区使得 Kafka 在井发处理上变得更加容易,理论上来说,分区数越多吞吐量越高,但这要根据集群实际环境及业务场景而定。
  分区也是 Kafka 保证消息被顺序消费以及对消息进行负载均衡的基础。
  Kafka 只能保证一个分区之内消息的有序性,并不能保证跨分区消息的有序性 。 每条消息被追加到相应的分区中,是顺序写磁盘,因此效率非常高,这是 Kafka 高吞吐率的一个重要保证。
  与传统消息系统不同的是, Kafka 并不会立即删除已被消费的消息,由于磁盘的限制消息也不会一直被存储(事实上这也是没有必要的),因此 Kafka 提供两种删除老数据的策略,一是基于消息己存储的时间长度, 二是基于分区的大小。这两种策略都能通过配置文件进行配置。

副本(Replica):每个分区又有一至多个副本,副本分布在集群的不同代理上,以提高可用性 。 从存储角度上分析,分区的每个副本在逻辑上抽象为一个日志( Log )对象,即分区的副本与日志对象是一一对应的 。 每个主题对应的分区数可在 Kafka 启动时所加载的配置文件中配置,也可在创建主题时指定 ,客户端还可以在主题创建后修改主题的分区数。

Leader副本和Follower副本:存在副本,就要副本之间数据的一致性, Kafka 会选择各自分区中的一个副本作为 Leader 副本,该分区中的其他副本为 Follower 副本,Leader 副本负责处理客户端读/写请求, Follower 副本从 Leader 副本同步数据 。副本 Follower 与 Leader 的角色并不是固定不变的,如果 Leader 失效,通过相应的选举算法将从其他 Follower 副本中选出新的 Leader 副本。

偏移量:任何发布到分区的消息会被直接追加到日志文件的尾部,每条消息在日志文件中的位置都会对应一个按序递增的偏移量(偏移量是一个分区下严格有序的逻辑值)。
  消费者通过控制消息偏移量来对消息进行消费,消费者对消息偏移量的操作并不会影响消息本身的偏移量。为了保证消息被顺序消费 ,需要保存消费者己消费消息对应的偏移量。
  旧版消费者将消费偏移量保存到 ZooKeeper 当中,而新版消费者是将消费偏移量保存到 Kafka 内部一个主题当中。当然,消费者也可以自己在外部系统保存消费偏移量。

日志段( LogSegment):一个日志被划分为多个日志段,日志段是 Kafka 日志对象分片的最小单位。与 日志对象一样,日志段也是一个逻辑概念, 一个日志段对应磁盘上一个具体日志文件和两个索引文件。
  日志文件是以 “ .log”为文件名后缀的数据文件,用于保存消息实际数据 。
  两个索引文件分别以“ .index ”和“ .timeindex ”作为文件名后缀,分别表示消息偏移量索引文件和消息时间戳索引文件。

代理(Broker):Kafka 基本体系结构中的集群就是由一个或多个 Kafka 实例构成,Kafka 实例就是Kafka代理,通常也称代理为 Kafka 服务器( KafkaServer )。
  生产环境中 Kafka 集群一般包括一台或多台服务器,我们可以在一台服务器上配置一个或多个代理。每一个代理都有一个所在集群中唯一的、非负整数的标识 id。
  在一个 Kafka集群中,每增加一个代理就需要为其指定一个标识id。标识 id 就是代理的名字,也是在启动代理时配置的 broker.id 对应的值。

生产者(Producer):生产者负责将消息发送给代理,就是向 Kafka 代理发送消息的客户端 。

消费者(Comsumer)和消费组(ConsumerGroup ):消费者以拉取(pull) 方式拉取数据。
  在 Kafka 中可以为每个消费者指定一个消费者组,通过 group.id 配置。未指定时的默认消费组为test-consumer-group。
  每个消费者有一个全局唯一的 id,通过 client.id 配置,未指定时 Kafka 会自动为该消费者生成一个全局唯一的 id,格式为$ {groupld}-${hostName}-${timestamp}-$ {UUID 前 8 位字符}。
  同一个主题的一条消息只能被同一个消费组下的某一个消费者消费,但不同消费组的消费者可同时消费该消息。
  消费组是 Kafka用来实现对一个主题消息进行广播和单播的手段,实现消息广播只需指定各消费者均属于不同的消费组,消息单播则只需让各消费者属于同一个消费组。

ISR (In-sync Replica ):Kafka 在 ZooKeeper 中动态维护了 一个 ISR,即保存同步的副本列表,用于保存 Leader 副本保持消息同步的所有副本对应的代理节点 id 。 如果一个 Follower副本宕机或是落后太多,则该 Follower副本节点将从 ISR 列表中移除 。

ZooKeeper: Kafka 利用 ZooKeeper 保存相应元数据信息, Kafka 元数据信息包括如代理节点信息、 Kafka集群信息、旧版消费者信息及其消费偏移量信息、主题信息、分区状态信息、分区副本分配方案信息、动态配置信息等。 Kafka 在启动或运行过程当中会在 ZooKeeper 上创建相应节点来保存元数据信息, Kafka 通过监昕机制在这些节点注册相应监听器来监昕节点元数据的变化,从而由 ZooKeeper 负责管理维护 Kafka 集群,同时通过 ZooKeeper 我们能够很方便地对 Kafka 集群进行水平扩展及数据迁移 。

Kafka 集群结构图

1.4、Kafka特性

 Kafka作为一个分布式流处理平台,具备如下三个关键特性:

  • 消息持久化
     Kafka的消息持久化 高度依赖于文件系统来存储和缓存消息 。 原因是使用文件系统和依赖于页缓存( page cache )的存储比维护一个内存的存储或是应用其他结构来存储消息更有优势,因此 Kafka 选择以文件系统
    +高吞吐量
     高吞吐量是 Kafka 设计的主要目标, Kafka 将数据写到磁盘,充分利用磁盘的顺序读写 。
    同时, Kafka 在数据写入及数据同步采用了零拷贝( zero-copy )技术,采用 senc!File()函数调用,
    senc!File()函数是在两个文件描述符之间直接传递数据,完全在内核中操作,从而避免了内核缓
    冲区与用户缓冲区之间数据的拷贝,操作效率极高 。 Kafka 还支持数据压缩及批量发送,同时
    Kafka 将每个主题划分为多个分区,这一系列的优化及实现方法使得 Kafka 具有很高的吞吐量。
    经大多数公司对 Kafka 应用的验证, Kafka 支持每秒数百万级别的消息 。

允许发布和订阅流数据

  • 存储流数据时提供相应的容错机制
  • 当流数据到达时能够被及时处理

Producer写入消息至Kafka集群

Kafka的信息存储

Kafka集群的调度管理

Kafka集群的消息负载均衡

Kafka组件的通讯

Consumer消费Kafka集群消息

2.1、Kafka架构图


1)Producer :消息生产者,向kafka broker发消息的客户端;
2)Consumer :消息消费者,向kafka broker取消息的客户端;
3)Topic :可以理解为一个队列;
4) Consumer Group (CG):kafka用来实现一个topic消息的广播(发给所有的consumer)和单播(发给任意一个consumer)的手段。一个topic可以有多个CG。topic的消息会复制(不是真的复制,是概念上的)到所有的CG,但每个partion只会把消息发给该CG中的一个consumer。如果需要实现广播,只要每个consumer有一个独立的CG就可以了。要实现单播只要所有的consumer在同一个CG。用CG还可以将consumer进行自由的分组而不需要多次发送消息到不同的topic;
5)Broker :一台kafka服务器就是一个broker。一个集群由多个broker组成。一个broker可以容纳多个topic;
6)Partition:为了实现扩展性,一个非常大的topic可以分布到多个broker(即服务器)上,一个topic可以分为多个partition,每个partition是一个有序的队列。partition中的每条消息都会被分配一个有序的id(offset)。kafka只保证按一个partition中的顺序将消息发给consumer,不保证一个topic的整体(多个partition间)的顺序;
7)Offset:kafka的存储文件都是按照offset.kafka来命名,用offset做名字的好处是方便查找。例如你想找位于2049的位置,只要找到2048.kafka的文件即可。当然the first offset就是00000000000.kafka。

参考资料

参考书籍:Kafka入门与实践

  • 作者: DeepInThought
    出处: https://www.cnblogs.com/DeepInThought
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 原文地址:https://www.cnblogs.com/DeepInThought/p/10989961.html