美文网首页kafka
Kafka原理详细介绍

Kafka原理详细介绍

作者: 上善若泪 | 来源:发表于2022-03-30 09:52 被阅读0次

    1 Kafka

    1.1 定义

    Kafka 是一个分布式流媒体平台,kafka官网:http://kafka.apache.org/

    Kafka 是一种高吞吐量、分布式、基于发布/订阅的消息系统,最初由 LinkedIn 公司开发,使用Scala 语言编写,目前是Apache 的开源项目。

    流媒体平台有三个关键功能:

    • 发布和订阅记录流,类似于消息队列或企业消息传递系统。
    • 以容错的持久方式存储记录流。
    • 记录发生时处理流。

    Kafka通常用于两大类应用:

    • 构建可在系统或应用程序之间可靠获取数据的实时流数据管道
    • 构建转换或响应数据流的实时流应用程序

    1.1.1 Kafka名词

    下面是Kafka中涉及到的相关概念:

    1. brokerKafka 服务器,负责消息存储和转发
    2. topic:消息类别,Kafka 按照topic 来分类消息(即使如此,kafka仍然有点对点和广播发布类型)
    3. partitiontopic 的分区,一个 topic 可以包含多个 partitiontopic 消息保存在各个partition
    4. offset:消息在日志中的位置,可以理解是消息在 partition 上的偏移量,也是代表该消息的唯一序号
    5. Producer:消息生产者
    6. Consumer:消息消费者
    7. Consumer Group:消费者分组,每个Consumer 必须属于一个 group
    8. Zookeeper:保存着集群 broker、topic、partitionmeta 数据;另外,还负责 broker 故障发现,partition leader 选举,负载均衡等功能

    1.1.2 Kafka核心API

    Kafka有四个核心API:

    • Producer API(生产者API)允许应用程序发布记录流至一个或多个kafkatopics(主题)

    • Consumer API(消费者API)允许应用程序订阅一个或多个topics(主题),并处理所产生的对他们记录的数据流。

    • Streams API(流API)允许应用程序充当流处理器,从一个或多个topics(主题)消耗的输入流,并产生一个输出流至一个或多个输出的topics(主题),有效地变换所述输入流,以输出流。

    • Connector API(连接器API)允许构建和运行kafka topics(主题)连接到现有的应用程序或数据系统中重用生产者或消费者。例如,关系数据库的连接器可能捕获对表的每个更改。

    Kafka中,客户端和服务器之间的通信是通过简单,高性能,语言无关的TCP协议完成的。此协议已版本化并保持与旧版本的向后兼容性。Kafka提供Java客户端,但客户端有多种语言版本。

    1.2 相关组件介绍

    1.2.1 Topic

    Topic 是生产者发送消息的目标地址,是消费者的监听目标

    image.png

    一个服务可以监听、发送多个 Topics


    image.png

    Kafka 中有一个consumer-group(消费者组)的概念。
    这是一组服务,扮演一个消费者

    image.png

    如果是消费者组接收消息,Kafka 会把一条消息路由到组中的某一个服务

    image.png

    这样有助于消息的负载均衡,也方便扩展消费者。
    Topic 扮演一个消息的队列。
    首先,一条消息发送了

    image.png

    然后,这条消息被记录和存储在这个队列中,不允许被修改


    image.png

    接下来,消息会被发送给此 Topic 的消费者。
    但是,这条消息并不会被删除,会继续保留在队列中

    image.png

    像之前一样,这条消息会发送给消费者、不允许被改动、一直呆在队列中。
    (消息在队列中能呆多久,可以修改 Kafka 的配置)


    image.png image.png

    1.2.2 Partitions分区

    上面 Topic 的描述中,把 Topic 看做了一个队列,实际上,一个 Topic 是由多个队列组成的,被称为Partition(分区)
    这样可以便于 Topic 的扩展

    image.png

    生产者发送消息的时候,这条消息会被路由到此Topic 中的某一个 Partition

    image.png

    消费者监听的是所有分区


    image.png

    生产者发送消息时,默认是面向 Topic 的,由 Topic 决定放在哪个 Partition,默认使用轮询策略

    image.png

    也可以配置 Topic,让同类型的消息都在同一个 Partition
    例如,处理用户消息,可以让某一个用户所有消息都在一个 Partition
    例如,用户1发送了3条消息:A、B、C,默认情况下,这3条消息是在不同的 Partition 中(如 P1、P2、P3)。
    在配置之后,可以确保用户1的所有消息都发到同一个分区中(如 P1)

    image.png

    这个功能有什么用呢?
    这是为了提供消息的【有序性】。
    消息在不同的 Partition 是不能保证有序的,只有一个 Partition 内的消息是有序的


    image.png image.png

    1.2.3 Topics主题 和 partitions分区

    一个Topic可以认为是一类消息,每个topic将被分成多个partition(区),每个partition在存储层面是append log文件
    主题是发布记录的类别或订阅源名称。Kafka的主题总是多用户; 也就是说,一个主题可以有零个,一个或多个消费者订阅写入它的数据。
    对于每个主题,Kafka集群都维护一个如下所示的分区日志:

    image.png

    每个分区都是一个有序的,不可变的记录序列,不断附加到结构化的提交日志中。分区中的记录每个都分配了一个称为偏移的顺序ID号,它唯一地标识分区中的每个记录。

    Kafka集群持久保存所有已发布的记录 - 无论是否已使用 - 使用可配置的保留期。例如,如果保留策略设置为两天,则在发布记录后的两天内,它可供使用,之后将被丢弃以释放空间。Kafka的性能在数据大小方面实际上是恒定的,因此长时间存储数据不是问题。

    image.png

    实际上,基于每个消费者保留的唯一元数据是该消费者在日志中的偏移或位置。这种偏移由消费者控制:通常消费者在读取记录时会线性地提高其偏移量,但事实上,由于该位置由消费者控制,因此它可以按照自己喜欢的任何顺序消费记录。例如,消费者可以重置为较旧的偏移量来重新处理过去的数据,或者跳到最近的记录并从“现在”开始消费。

    这些功能组合意味着Kafka 消费者consumers 非常cheap - 他们可以来来往往对集群或其他消费者没有太大影响。例如,可以使用我们的命令行工具“tail”任何主题的内容,而无需更改任何现有使用者所消耗的内容。

    日志中的分区有多种用途。首先,它们允许日志扩展到超出适合单个服务器的大小。每个单独的分区必须适合托管它的服务器,但主题可能有许多分区,因此它可以处理任意数量的数据。其次,它们充当了并行性的单位 - 更多的是它

    1.2.4 Distribution分配

    一个Topic的多个partitions,被分布在kafka集群中的多个server上;每个server(kafka实例)负责partitions中消息的读写操作;此外kafka还可以配置partitions需要备份的个数(replicas),每个partition将会被备份到多台机器上,以提高可用性.

    基于replicated方案,那么就意味着需要对多个备份进行调度;每个partition都有一个serverleader;leader负责所有的读写操作,如果leader失效,那么将会有其他follower来接管(成为新的leader);follower只是单调的和leader跟进,同步消息即可..由此可见作为leaderserver承载了全部的请求压力,因此从集群的整体考虑,有多少个partitions就意味着有多少个"leader",kafka会将"leader"均衡的分散在每个实例上,来确保整体的性能稳定

    1.2.5 Producers生产者 和 Consumers消费者

    1.2.5.1 Producers生产者

    Producers将数据发布到指定的topics 主题。同时Producer 也能决定将此消息归属于哪个partition;比如基于round-robin方式或者通过其他的一些算法等。

    1.2.5.2 Consumers

    本质上kafka只支持Topic.每个consumer属于一个consumer group;反过来说,每个group中可以有多个consumer.发送到Topic的消息,只会被订阅此Topic的每个group中的一个consumer消费。

    如果所有使用者实例具有相同的使用者组,则记录将有效地在使用者实例上进行负载平衡。

    如果所有消费者实例具有不同的消费者组,则每个记录将广播到所有消费者进程。

    image.png

    分析:两个服务器Kafka群集,托管四个分区(P0-P3),包含两个使用者组。消费者组A有两个消费者实例,B组有四个消费者实例。

    Kafka中实现消费consumption 的方式是通过在消费者实例上划分日志中的分区,以便每个实例在任何时间点都是分配的“公平份额”的独占消费者。维护组中成员资格的过程由Kafka协议动态处理。如果新实例加入该组,他们将从该组的其他成员接管一些分区; 如果实例死亡,其分区将分发给其余实例。

    Kafka仅提供分区内记录的总订单,而不是主题中不同分区之间的记录。对于大多数应用程序而言,按分区排序与按键分区数据的能力相结合就足够了。但是,如果您需要对记录进行总订单,则可以使用仅包含一个分区的主题来实现,但这将意味着每个使用者组只有一个使用者进程。

    1.2.5.3 Consumers kafka确保

    发送到partitions中的消息将会按照它接收的顺序追加到日志中。也就是说,如果记录M1由与记录M2相同的生成者发送,并且首先发送M1,则M1将具有比M2更低的偏移并且在日志中更早出现。

    消费者实例按照它们存储在日志中的顺序查看记录。对于消费者而言,它们消费消息的顺序和日志中消息顺序一致。

    如果Topicreplicationfactor为N,那么允许N-1个kafka实例失效,我们将容忍最多N-1个服务器故障,而不会丢失任何提交到日志的记录。

    1.2.6 架构和zookeeper关系

    Kafka 是集群架构的,ZooKeeper是重要组件。

    image.png

    ZooKeeper 管理者所有的 TopicPartition
    TopicPartition 存储在 Node 物理节点中,ZooKeeper负责维护这些 Node

    image.png

    有2个 Topic,各自有2个 Partition


    image.png

    这是逻辑上的形式,但在 Kafka 集群中的实际存储可能是这样的


    image.png

    Topic APartition #1 有3份,分布在各个Node 上。
    这样可以增加 Kafka 的可靠性和系统弹性。
    3个 Partition #1 中,ZooKeeper 会指定一个 Leader,负责接收生产者发来的消息

    image.png

    其他2个 Partition #1 会作为 Follower,Leader 接收到的消息会复制给 Follower


    image.png

    这样,每个 Partition 都含有了全量消息数据。


    image.png

    即使某个 Node 节点出现了故障,也不用担心消息的损坏。
    Topic A 和 Topic B 的所有 Partition 分布可能就是这样的


    image.png

    转载于:https://mp.weixin.qq.com/s/k7DJJGmImcpnaSy9AhAmmQ

    1.3 kafka是如何保证消息的有序性

    kafka这样保证消息有序性的:
    一个topic,一个 partition,一个 consumer,内部单线程消费,单线程吞吐量太低,一般不会用这个。(全局有序性)
    N 个内存 queue,具有相同 key的数据都到同一个内存 queue;然后对于 N 个线程,每个线程分别消费一个内存 queue即可,这样就能保证顺序性。
    大家可以看下消息队列的有序性是怎么推导的:

    消息的有序性,就是指可以按照消息的发送顺序来消费。有些业务对消息的顺序是有要求的,比如先下单再付款,最后再完成订单,这样等。假设生产者先后产生了两条消息,分别是下单消息(M1),付款消息(M2),M1比M2先产生,如何保证M1比M2先被消费呢。


    image.png

    为了保证消息的顺序性,可以将将M1、M2发送到同一个Server上,当M1发送完收到ack后,M2再发送。如图:


    image.png

    这样还是可能会有问题,因为从MQ服务器到服务端,可能存在网络延迟,虽然M1先发送,但是它比M2晚到。


    image.png

    那还能怎么办才能保证消息的顺序性呢?将M1和M2发往同一个消费者,且发送M1后,等到消费端ACK成功后,才发送M2就得了。


    image.png

    消息队列保证顺序性整体思路就是这样啦。比如Kafka的全局有序消息,就是这种思想的体现: 就是生产者发消息时,1个Topic只能对应1个Partition,一个 Consumer,内部单线程消费。
    但是这样吞吐量太低,一般保证消息局部有序即可。在发消息的时候指定Partition KeyKafka对其进行Hash计算,根据计算结果决定放入哪个Partition。这样Partition Key相同的消息会放在同一个Partition。然后多消费者单线程消费指定的Partition
    转载于:https://mp.weixin.qq.com/s/gHjuYH6R6Fgfn3WZ8W79Zg

    1.4 kafka使用场景

    1.4.1 消息Messaging

    Kafka可以替代更传统的消息代理。消息代理的使用有多种原因(将处理与数据生成器分离,缓冲未处理的消息等)。与大多数消息传递系统相比,Kafka具有更好的吞吐量,内置分区,复制和容错功能,这使其成为大规模消息处理应用程序的理想解决方案。

    根据经验,消息传递的使用通常相对较低,但可能需要较低的端到端延迟,并且通常取决于Kafka提供的强大的耐用性保证。
    在这个领域,Kafka可与传统的消息传递系统(如ActiveMQ或 RabbitMQ)相媲美。

    1.4.2 网站活动跟踪

    Kafka的原始用例是能够将用户活动跟踪管道重建为一组实时发布 - 订阅源。这意味着站点活动(页面查看,搜索或用户可能采取的其他操作)将发布到中心主题,每个活动类型包含一个主题。这些源可用于订购一系列用例,包括实时处理,实时监控以及加载到Hadoop或离线数据仓库系统以进行脱机处理和报告。

    活动跟踪通常非常高,因为为每个用户页面视图生成了许多活动消息。

    1.4.3 度量Metrics

    Kafka通常用于运营监控数据。这涉及从分布式应用程序聚合统计信息以生成操作数据的集中式提要。

    1.4.4 日志聚合

    许多人使用Kafka作为日志聚合解决方案的替代品。日志聚合通常从服务器收集物理日志文件,并将它们放在中央位置(可能是文件服务器或HDFS)进行处理。Kafka抽象出文件的细节,并将日志或事件数据作为消息流更清晰地抽象出来。这允许更低延迟的处理并更容易支持多个数据源和分布式数据消耗。与Scribe或Flume等以日志为中心的系统相比,Kafka提供了同样出色的性能,由于复制而具有更强的耐用性保证,以及更低的端到端延迟。

    1.4.5 流处理

    许多Kafka用户在处理由多个阶段组成的管道时处理数据,其中原始输入数据从Kafka主题中消费,然后聚合,丰富或以其他方式转换为新主题以供进一步消费或后续处理。

    例如,用于推荐新闻文章的处理管道可以从RSS订阅源抓取文章内容并将其发布到“文章”主题; 进一步处理可能会对此内容进行规范化或重复数据删除,并将已清理的文章内容发布到新主题; 最终处理阶段可能会尝试向用户推荐此内容。此类处理管道基于各个主题创建实时数据流的图形。从0.10.0.0开始,这是一个轻量级但功能强大的流处理库,名为Kafka Streams 在Apache Kafka中可用于执行如上所述的此类数据处理。除了Kafka Streams之外,其他开源流处理工具包括Apache Storm和 Apache Samza。

    1.4.6 Event Sourcing

    Event Sourcing是一种应用程序设计风格,其中状态更改记录为按时间排序的记录序列。Kafka对非常大的存储日志数据的支持使其成为以这种风格构建的应用程序的出色后端。

    1.4.7 提交日志

    Kafka可以作为分布式系统的一种外部提交日志。该日志有助于在节点之间复制数据,并充当故障节点恢复其数据的重新同步机制。Kafka中的日志压缩功能有助于支持此用法。在这种用法中,Kafka类似于Apache BookKeeper项目

    相关文章

      网友评论

        本文标题:Kafka原理详细介绍

        本文链接:https://www.haomeiwen.com/subject/dhuijrtx.html