下面给出 Kafka 一些重要概念,让大家对 Kafka 有个整体的认识和感知,后面还会详细的解析每一个概念的作用以及更深入的原理
• Producer:消息生产者,向 Kafka Broker 发消息的客户端。
• Consumer:消息消费者,从 Kafka Broker 取消息的客户端。
• Consumer Group:消费者组(CG),消费者组内每个消费者负责消费不同分区的数据,提高消费能力。一个分区只能由组内一个消费者消费,消费者组之间互不影响。所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者。
• Broker:一台 Kafka 机器就是一个 Broker。一个集群由多个 Broker 组成。一个 Broker 可以容纳多个 Topic。
• Topic:可以理解为一个队列,Topic 将消息分类,生产者和消费者面向的是同一个 Topic。
• Partition:为了实现扩展性,提高并发能力,一个非常大的 Topic 可以分布到多个 Broker (即服务器)上,一个 Topic 可以分为多个 Partition,每个 Partition 是一个 有序的队列。
• Replica:副本,为实现备份的功能,保证集群中的某个节点发生故障时,该节点上的 Partition 数据不丢失,且 Kafka 仍然能够继续工作,Kafka 提供了副本机制,一个 Topic 的每个分区都有若干个副本,一个 Leader 和若干个 Follower。
• Leader:每个分区多个副本的“主”副本,生产者发送数据的对象,以及消费者消费数据的对象,都是 Leader。
• Follower:每个分区多个副本的“从”副本,实时从 Leader 中同步数据,保持和 Leader 数据的同步。Leader 发生故障时,某个 Follower 还会成为新的 Leader。
• Offset:消费者消费的位置信息,监控数据消费到什么位置,当消费者挂掉再重新恢复的时候,可以从消费位置继续消费。
• ZooKeeper:Kafka 集群能够正常工作,需要依赖于 ZooKeeper,ZooKeeper 帮助 Kafka 存储和管理集群信息。
1. 消息和批次
Kafka中的数据单元称为消息(message)。如果你对数据库非常了解,那么您可以将其视为与数据库中行或记录类似。就Kafka而言,消息只是一个字节数组,因此其中包含的数据对Kafka没有特定的格式或含义。消息可以具有可选的元数据位,其被称为key。key也是一个字节数组,与消息一样,对Kafka没有特定含义。当消息以更受控制的方式写入分区时,使用key。最简单的方案是生成key的一致哈希,然后通过获取哈希模的结果(主题中的分区总数)来选择该消息的分区号。这可确保具有相同key的消息始终写入同一分区。
为了提高效率,将消息分批写入Kafka。批处理只是一组消息,所有消息都生成到同一主题和分区。每条消息通过网络进行单独的往返会导致过度的开销,而将消息一起收集到一个批处理中则会减少这种情况。当然,这是延迟和吞吐量之间的权衡:批次越大,每单位时间可以处理的消息越多,但单个消息传播所需的时间就越长。批次通常也是压缩的,以一些处理能力为代价提供更有效的数据传输和存储。
1.1 消息
是Kafka中的最小数据单元,类比“数据库”中的一条记录;消息由字节数组组成,Kafka没有具体的格式和定义,但是客户端提供的消息定义中有一组可选的数据单元:
public final class ProducerRecord<K, V> {
private final String topic; //消息主题
private final Integer partition; //消息分区
private final K key; //消息的键
private final V value; // 消息值
}
在以上的字段中,只有消息主题是必须的,标识这个消息的分类。
2.2 批次
同我们常说的分批处理思想中的批次概念是一致的;从根本上来讲都是为了减少消耗,提升效率。
如果每一个生产者产生一条消息,我们就写到网络中,会带来大量的开销,所以将消息分批次来传递;当然分批会带来延迟,这样就需要在延迟和吞吐量之间做一个权衡,Kafka提供参数来给开发者优化这种平衡。
单个批次消息越多,延迟越大,同时消息会被压缩,来提升数据的传输和存储能力,当然压缩更消耗CPU。
批次里面的消息都是属于同一个主题中的同一个分区,这样可以保证一次发送一批消息时的网络开销最小。
2. 模式(Schemas)
虽然消息是Kafka本身的不透明字节数组,但建议在消息内容上加上额外的结构或模式,以便易于理解。消息架构有许多选项,具体取决于您的应用程序的个性化需求。简单系统,例如Javascript Object Notation(JSON)和可扩展标记语言(XML),易于使用且易于阅读。但是,它们缺乏强大的类型处理和模式版本之间的兼容性等功能。许多Kafka开发人员都赞成使用Apache Avro,这是一个最初为Hadoop开发的序列化框架。 Avro提供紧凑的序列化格式;与消息有效负载分离的模式,不需要在更改时生成代码;强大的数据类型和模式演变,兼具向后和向前兼容性。
一致的数据格式在Kafka中很重要,因为它允许写入和读取消息分离。当这些任务紧密耦合时,必须更新订阅消息的应用程序以处理新数据格式,与旧格式并行。只有这样才能更新发布消息的应用程序以使用新格式。通过使用定义良好的模式并将它们存储在一个通用的存储库中,可以无需协调地理解Kafka中的消息。
3. 主题和分区
Kafka 里的消息用主题进行分类(主题好比数据库中的表) , 主题下有可以被分为若干个分区(分表技术) 。 分区本质上是个提交日志文件, 有新消息, 这个消息就会以追加的方式写入分区(写文件的形式) , 然后用先入先出的顺序读取。
3.1 主题
是消息的分类标识,类似于文件系统中的文件夹
3.2 分区
是一个主题的队列,同一个主题会包含若干分区,每一个分区都是一个提交记录,消息会被追加到分区中,在一个分区中保证顺序,以先入先出的顺序被消费。
Kafka为每个分区中维护着一个偏移量,偏移量记录着当前分区的消费记录,偏移量保存在分布式协同服务器ZooKeeper上。
分区在Kafka中有着重要的意义,Kafka通过分区来实现数据冗余和主题的横向扩展;多个分区可以分布在不同的kafka服务端机器上,这使主题也可以横跨多个服务器存在,保证了分布式的能力;
在消息中讲到了消息的键,在消息没有配置键的时候,生产者会把消息均衡的写入到各个分区。当我们需要把特定的消息写入到固定的分区时,可以通过消息的键和分区器来实现,分区器会将键生成成散列值,并映射到各个分区上。
为了大量的消息能负载分散,要求主题的分区数要大于当前Kafka的broker服务器数量,这样才能保证所有每个broker能分担到消息的压力。在实际生产中,我们可以增加分区来给主题扩容,但是不能减少分区。
选定分区数量是一个需要经验的事情,需要考虑多个因素:
-
主题需要多大的吞吐
-
单个分区的最大吞吐量多少
-
每个broker上拥有的分区数量,这需要考量磁盘和网络带宽
-
单个分区上拥有的分区也不能太多,毕竟分区越多内存也越大,重新选举的时间也越长
需要注意的是,如果使用了消息的键来控制消息写入分区,那么增加主题时就需要慎重了,因为这会带来rehash的问题。
4. 生产者和消费者
Kafka客户端是系统用户,有两种基本类型:生产者和消费者。还有高级客户端API - 用于数据集成的Kafka Connect API和用于流处理的Kafka Streams。高级客户端使用生产者和消费者作为构建块,并在顶部提供更高级别的功能。
4.1 生产者
生产者创造新的信息。在其他发布/订阅系统中,这些可以称为发布者或编写者。通常,将为特定主题生成消息。默认情况下,生产者不关心特定消息写入的分区,并将均衡地平衡主题的所有分区上的消息。在某些情况下,生产者会将消息定向到特定分区。这通常使用消息key和分区程序来完成,该分区程序将生成key的散列并将其映射到特定分区。这确保了使用给定key生成的所有消息都将写入同一分区。生产者还可以使用遵循其他业务规则的自定义分区程序将消息映射到分区。
4.2 消费者
消费者阅读消息。 在其他发布/订阅系统中,这些客户端可以被称为订阅者或读者。 消费者订阅一个或多个主题,并按消息的生成顺序读取消息。 消费者通过跟踪消息的偏移来跟踪它已经消耗了哪些消息。 偏移量(Offset)是元数据 - 一个不断增加的整数值 - Kafka在生成时添加到每个消息中。 给定分区中的每条消息都有唯一的偏移量。 通过在Zookeeper或Kafka本身中存储每个分区的最后消耗消息的偏移量,消费者可以停止并重新启动而不会丢失其位置。
消费者负责消费者群组的一部分工作,消费者群组是一起工作以消费主题的一个或多个分区。 该小组确保每个分区仅由一名成员消费。 在单个组中有三个消费者使用主题。 其中两个消费者分别在一个分区工作,而第三个消费者在两个分区工作。 消费者对分区的映射通常称为消费者对分区的所有权。
不同的消费者群组可以读取同一个主题,但对于同一个群组中不同消费者不能读取相同分区
通过这种方式,消费者可以横向扩展以消费具有大量消息的主题。 此外,如果单个使用者失败,则该组的其余成员将重新平衡正在使用的分区以接管缺少的成员。
5. 保留消息
保留消息是Kafka的一个重要特性。Kafka broker默认的消息保留策略有两种。
-
保留一段固定的时间。比如7天
-
保留到消息达到一定大小的字节数,如1GB 当达到上限后,旧的消息会过期从而被删除。所以在任何时刻,可用消息的总量不会超过配置参数所指定的大小。
6. 多集群
随着Kafka部署的增长,拥有多个集群通常是有利的。 有几个原因可以解决这个问题:
• 分离数据类型
• 为安全要求隔离
• 多个数据中心(灾难恢复)
特别是在处理多个数据中心时,通常需要在它们之间复制消息。 通过这种方式,在线应用程序可以访问两个站点的用户活动。 例如,如果用户更改其配置文件中的公共信息,则无论显示搜索结果的数据中心如何,都需要显示该更改。 或者,可以将监控数据从许多站点收集到分析和警报系统所在的单个中心位置。 Kafka集群中的复制机制仅设计用于单个集群,而不是多个集群之间。
Kafka项目包括一个名为MirrorMaker的工具,用于此目的。 MirrorMaker的核心是Kafka消费者和生产者,与队列链接在一起。 消息从一个Kafka集群中消耗并为另一个集群生成。使用MirrorMaker架构,将来自两个本地群集的消息聚合到聚合群集中,然后将该群集复制到其他数据中心。 应用程序的简单特性掩盖了它在创建复杂数据管道方面的能力。
本文由
传智教育博学谷
教研团队发布。如果本文对您有帮助,欢迎
关注
和点赞
;如果您有任何建议也可留言评论
或私信
,您的支持是我坚持创作的动力。转载请注明出处!