欢迎大家前往
云加社区,获取更多腾讯海量技术实践干货哦~
译者: 人工智能资讯小编
本译文自 Jean-Paul Azar 在 https://dzone.com 发表的 Kafka Detailed Design and Ecosystem ,文中版权,图像代码的数据均归作者所有。为了本土化,翻译内容略作修改。
Kafka 的核心是经纪人,主题,日志,分区和集群。核心也包括像 MirrorMaker 这样的相关工具。前面提到的是 Kafka,因为它存在于 Apache 中。
Kafka 生态系统由 Kafka Core,Kafka Streams,Kafka Connect,Kafka REST Proxy 和 Schema Registry 组成。大部分 Kafka 生态系统的其他部分来自 Confluent,不属于 Apache。
Kafka Stream 是 Streams API,用于转换、汇总和处理来自流的记录并生成衍生流。Kafka Connect 是 API 连接器,用于创建可重用的生产者和消费者(例如,来自 DynamoDB 的更改流)。Kafka REST 代理通过 REST(HTTP)被用于生产者和消费者。该架构注册管理使用模式的 AvroKafka 的记录。Kafka MirrorMaker 用于将群集数据复制到另一个群集。
Kafka 连接源是记录的来源。Kafka 连接水槽是记录的目的地。
Kafka Stream API 基于核心 Kafka 原语构建,并拥有自己的生命。Kafka 流可以实时处理流。Kafka Streams 支持流处理器。流处理器从输入主题获取连续的记录流,对输入执行一些处理,转换和聚合,并产生一个或多个输出流。例如,视频播放器应用程序可能会接收观看的视频事件的输入流,并暂停视频,并输出用户偏好流,然后基于最近的用户活动或许多用户的聚合活动来获取新的视频推荐,以查看哪些新的视频很热。Kafka Stream API 解决了无序记录的难题,跨多个流聚合,连接来自多个流的数据,允许有状态的计算等等。
Kafka 流可以实时处理流。它可以聚合多个流,连接来自多个流的数据,允许有状态的计算等等。
Kafka Connect 是连接器 API,用于创建可重用的生产者和消费者(例如,来自 DynamoDB 的更改流)。Kafka 连接源是记录的来源。Kafka 连接水槽是记录的目的地。
模式注册管理使用 Avro 作为 Kafka 记录管理模式。
Kafka MirrorMaker 用于将群集数据复制到另一个群集。
Kafka REST 代理通过 REST(HTTP)被用于生产者和消费者。您可以使用它来轻松整合现有的代码库。
如果您不确定 Kafka 是 什么 ,请参阅 什么是 Kafka?
这篇文章从我们关于 Kafka 架构 的系列文章中 有所体现 ,其中包括 Kafka 主题架构 , Kafka 制作者架构 , Kafka 用户架构 和 Kafka 生态系统架构。
本文受到 Kafka 设计部分的 启发。你可以把它想成悬崖笔记。
LinkedIn 工程师构建 Kafka 以支持实时分析。Kafka 被设计为提供实时处理流的分析系统。LinkedIn 将 Kafka 开发为实时处理流式数据馈送的统一平台。Kafka 背后的目标是构建一个高吞吐量的流媒体数据平台,支持日志聚合,用户活动等大容量事件流。
为了满足 Kafka 的需求扩展,分布式支持分片和负载均衡。扩展需求激发了 Kafka 的分区和消费者模型。Kafka 使用分区,分布式,提交日志来扩展写入和读取。Kafka 的分片被称为分区( Kinesis,类似于 Kafka ,称为分区 "碎片")。
根据维基百科的说法,"数据库分片是数据库或搜索引擎中数据的水平分区,每个分区被称为分片或数据库分片,每个分片被保存在一个单独的数据库服务器实例上,以传播负载"。
Kafka 被设计为处理来自离线系统的周期性大数据加载以及传统的消息传递用例,低延迟。
MOM 是面向消息的中间件; 考虑 IBM MQSeries, JMS ,ActiveMQ 和 RabbitMQ。像许多 MOM 一样,Kafka 通过复制和领导选举来节点故障的容错。但是,Kafka 的设计更像是一个分布式的数据库事务日志而不是传统的消息传递系统。与许多 MOM 不同的是,Kafka 的复制是建立在低级设计之上的,并不是事后的想法。
Kafka 依靠文件系统来存储和缓存记录。
顺序写入 硬盘性能的 硬盘性能很快 ( 非常快 )。JBOD 只是一堆磁盘驱动器。带有 6 个 7200rpm SATA RAID-5 阵列的 JBOD 配置约为 600MB / 秒。像 Cassandra 表一样,Kafka 日志是只写结构,意思是数据会被附加到日志的末尾。在使用硬盘驱动器时,顺序读取和写入速度快,可预测,并且可以通过操作系统进行大量优化。使用 HDD 时,顺序磁盘访问可能比随机存储器访问和 SSD 更快。
尽管 JVM GC 的开销可能会很高,但是 Kafka 在操作系统上依赖于缓存,这是一个巨大的,快速且稳定的缓存。而且,现代操作系统使用所有可用的主存储器来进行磁盘缓存。操作系统文件缓存几乎是免费的,没有操作系统的开销。实现高速缓存一致性是正确的挑战,但是 Kafka 依靠坚如磐石的操作系统来实现高速缓存一致性。使用 OS 进行缓存还会减少缓冲区副本的数量。由于 Kafka 磁盘使用趋向于顺序读取,所以 OS 预读缓存令人印象深刻。
Cassandra,Netty 和 Varnish 使用类似的技术。所有这一切都在 Kafka 文件 中得到了很好的解释,在 油漆现场 还有一个更有趣的解释。
Kafka 主张长时间顺序访问磁盘进行读取和写入。像 Cassandra,LevelDB,RocksDB 和其他 Kafka 使用日志结构化存储和压缩的形式,而不是磁盘上可变的 BTree。像 Cassandra 一样,Kafka 使用墓碑而不是立即删除记录。
由于磁盘这些天有一些无限的空间,并且速度非常快,Kafka 可以提供通常在消息系统中不常见的功能,如长时间保持旧消息。这种灵活性允许 Kafka 有趣的应用。
生产者向 Kafka 经纪人询问有关哪个 Kafka 经纪人具有哪个主题分区领导的元数据,因此不需要路由层。这个领导数据允许生产者直接向 Kafka 经纪人分区领导发送记录。
生产者客户端控制它将消息发布到哪个分区,并且可以根据某些应用程序逻辑选择一个分区。生产者可以通过密钥,循环法或使用定制应用程序特定的分区逻辑来分区记录。
Kafka 生产商支持记录配料。批量可以通过批量记录的大小来配置。批次可以根据时间自动刷新。
批量处理对于网络 IO 吞吐量非常有利,并大幅提高吞吐量。
缓冲是可配置的,并允许您在更好的吞吐量之间进行额外延迟之间的权衡。或者在大量使用的系统的情况下,它可能是更好的平均吞吐量,并减少总体延迟。
批量处理允许累积更多的字节发送,相当于 Kafka Brokers 上较少的 I / O 操作,并提高了压缩效率。为了获得更高的吞吐量,Kafka Producer 配置允许基于时间和大小的缓冲。生产者发送多个记录作为一个批次,而不是逐个发送每个记录的网络请求。
在大型流媒体平台中,瓶颈并不总是 CPU 或磁盘,而是通常网络带宽。云中存在更多的网络带宽问题,如集装箱化和虚拟化环境,因为多个服务可能共享一个 NiC 卡。另外,与数据中心或 WAN 通信时,网络带宽问题可能会有问题。
批处理有利于高效压缩和网络 IO 吞吐量。
Kafka 提供了端到端的批量压缩,而不是一次压缩记录,Kafka 有效地压缩了整批记录。相同的消息批处理可以一次压缩并发送到 Kafka 代理 / 服务器,并以压缩形式写入日志分区。您甚至可以配置压缩,以便在 Kafka 经纪商将压缩记录传送给用户之前不进行解压缩。
Kafka 支持 GZIP,Snappy 和 LZ4 压缩协议。
Kafka 消费者从经纪人那里获取数据。其他系统经纪商将数据或流数据推送给消费者。消息通常是一个基于拉的系统(SQS,大多数 MOM 使用拉)。在拉动式的情况下,如果消费者落后,它会在晚些时候赶上。
由于 Kafka 是基于拉式的,所以它实施了大量的数据分批处理。Kafka 像许多基于拉的系统实现了长期民意调查(SQS,Kafka 都这样做)。长时间轮询在请求一段时间后保持连接打开并等待响应。
一个基于拉的系统必须拉取数据然后处理它,拉和获取数据之间总是有一个暂停。
推送数据给消费者(抄写员,水槽,反应流,RxJava,Akka)。基于推送或流式传输系统在处理缓慢或死亡的消费者方面存在问题。当消费率低于生产速度时,推送系统消费者有可能不知所措。一些基于推送的系统使用基于背压的退避协议,其允许消费者指示其被压倒看到 反应性流 。当试图跟踪消息确认时,这种不会淹没消费者和消费者恢复的问题是棘手的。
基于推送或流式传输的系统可以立即发送请求,或者累积请求并批量发送(或基于反压的组合)。基于推送的系统总是在推送数据。消费者可以在处理已经发送的数据的同时累积消息,这有利于减少消息处理的延迟。但是,如果消费者在加工后死亡,那么经纪人如何知道消费者在哪里以及何时将数据再次发送给其他消费者。这个问题不是一个容易解决的问题。Kafka 通过使用拉式系统来解决这些复杂问题。
对于大多数 MOM,经纪人有责任跟踪哪些消息被标记为已消耗。消息跟踪不是一件容易的事情。随着消费者消费信息,经纪人会跟踪状态。
大多数 MOM 系统的目标是让经纪人在消费后快速删除数据。还记得大部分的 MOM 是在磁盘小得多,能力不足,价格昂贵的时候写的。
这个消息跟踪比听起来要复杂(确认功能),因为经纪人必须保持大量状态来跟踪每个消息,发送,确认并知道何时删除或重发消息。
请记住,Kafka 主题分为有序分区。每条消息在此有序分区中都有一个偏移量。每个主题分区一次仅由一个消费者组消费。
这种分区布局的意思是,Broker 跟踪每个消息跟踪的偏移数据,如 MOM,但只需要每个用户组的偏移量,即存储的分区偏移对。这种偏移追踪等同于要追踪的数据少得多。
消费者定期向 Kafka 经纪人发送位置数据(消费者组,分区偏移对),经纪人将该偏移数据存储到偏移主题中。
与 MOM 相比,抵消风格的消息确认要便宜得多。另外,消费者更加灵活,可以倒退到更早的偏移(重放)。如果有错误,那么修复错误,倒回消费者并重播主题。这个倒带功能是 Kafka 的一个杀手功能,因为 Kafka 可以保存很长一段时间的主题日志数据。
有三种消息传递语义:最多一次,至少一次,恰好一次。最多一次的消息可能会丢失,但永远不会重新发送。至少一次消息是永远不会丢失的,但可以重新传递。每个消息恰好一次只传送一次。确切地说,曾经是首选的,但更昂贵的,并要求生产者和消费者更多的簿记。
回想一下,所有副本具有相同的偏移量的完全相同的日志分区,并且用户组在日志每个主题分区中保持其位置。
为了实现 "最多一次" 消费者读取消息,然后将其偏移保存在分区中,并将其发送给代理,最后处理该消息。"最多一次" 的问题是消费者可能会在保存其位置之后,但在处理消息之前死亡。然后,接管或重新启动的消费者将在最后的位置离开,并且不会处理有问题的消息。
为了实现 "至少一次",消费者读取消息,处理消息,并最终将代价保存到代理。"至少一次" 的问题是消费者在处理消息之后但在保存最后偏移位置之前可能崩溃。然后,如果消费者重新启动或其他消费者接管,消费者可能会收到已处理的消息。"至少一次" 是最常见的消息传递设置,您的责任是使消息具有幂等性,这意味着两次获得相同的消息不会导致问题(两个借方)。
为了在消费者方面实现 "恰好一次",消费者需要在消费者位置的存储与消费者的消息处理输出的存储之间的两阶段提交。或者,消费者可以将消息处理输出存储在与最后偏移相同的位置。
Kafka 提供了前两个,从消费者的角度来看,实现第三个。
Kafka 为耐用性提供了可操作的可预测性语义。发布消息时,消息被 "提交" 到日志,这意味着所有 ISR 都接受消息。只要至少有一个副本存在,这个提交策略对于耐久性就能很好地工作。
生产者连接可能在发送过程中下降,生产者可能不确定它发送的消息是否经过,然后生产者重新发送消息。这个重发逻辑是为什么使用消息密钥和使用幂等消息(重复确定)是重要的。Kafka 直到最近(2017 年 6 月)才保证消息不会从生产者重试中复制。
生产者可以重新发送一个消息,直到收到确认,即收到确认。生产者重新发送消息而不知道其发送的其他消息是否与否,从而否定 "恰好一次" 和 "最多一次" 的消息传递语义。
制片人可以指定耐久度级别。制作人可以等待提交的消息。等待提交可确保所有副本都具有该消息的副本。
制片人可以发送没有确认(0)。生产者可以从分区领导(1)得到一个确认。生产者可以发送并等待来自所有副本(-1)的确认,这是默认的。
Kafka 现在支持 从生产者 "精确地一次" 交付 ,性能改进和分区间的原子写入。他们通过生产者发送一个序列 ID 来实现这一点,代理跟踪生产者是否已经发送了这个序列,如果生产者试图再次发送它,它会得到重复消息的确认,但是没有任何东西被保存到日志中。这种改进不需要 API 改变。
Kafka 的另一个改进是 Kafka 生产者在原子笔划上进行分割。原子写入意味着 Kafka 用户只能看到提交日志(可配置)。Kafka 有一个协调员,写一个标记到主题日志,以表示已经成功处理了什么。事务协调器和事务日志维护原子写入的状态。
原子写入确实需要一个新的生产者 API 来处理事务。
这是一个使用新的生产者 API 的例子。
- producer.initTransaction();
- try {
- producer.beginTransaction();
- producer.send(debitAccountMessage);
- producer.send(creditOtherAccountMessage);
- producer.sentOffsetsToTxn(...);
- producer.commitTransaction();
- } catch (ProducerFencedTransactionException pfte) {
- ...
- producer.close();
- } catch (KafkaException ke) {
- ...
- producer.abortTransaction();
- }
Kafka 通过可配置数量的 Kafka 经纪人复制每个主题的分区。Kafka 的复制模式是默认的,而不是像大多数 MOM 那样的插入功能,因为 Kafka 从一开始就打算使用分区和多节点。每个主题分区都有一个领导者和零个或多个关注者。
领导者和追随者被称为复制品。复制因素是领导者节点加上所有的追随者。分区领导在 Kafka 经纪人之间平均分享。消费者只能从领导读取。制片人只写信给领导。
追随者的主题日志分区与领导者的日志同步,ISR 是领导者的精确副本减去正在进行中的待复制记录。追随者像一个普通的 Kafka 消费者一样,从他们的领导人那里批量提取记录。
Kafka 记录哪些 Kafka 经纪人还活着。为了活着,Kafka 经纪人必须使用 ZooKeeper 的心跳机制来维护一个 ZooKeeper 会话,并且必须让所有的追随者与领导者同步,而不会落后太多。
这个 ZooKeeper 会话和同步是被称为同步的代理生存所需要的。同步副本被称为 ISR。每个领导者都跟踪一组 "同步副本"。
如果 ISR / 追随者死亡,则落后,领导者将从 ISR 中移除追随者。落后于复制品在
时段之后不同步的时候 。
- replica.lag.time.max.ms
当所有 ISR 将消息应用到其日志时,消息被认为是 "已提交" 的。消费者只看到提交的消息。Kafka 保证:只要至少有一个 ISR,承诺的信息就不会丢失。
Kafka 分区是一个复制的日志。复制日志是分布式数据系统原语。复制日志对于使用状态机来实现其他分布式系统很有用。一个复制的日志模型对有序的一系列值 "达成一致"。
当一个领导人活着的时候,所有的追随者只需要复制他们领导的价值观和秩序。如果领导者死了,Kafka 从同步的追随者中选择一个新的领导者。如果一个生产者被告知一个消息被提交,然后领导失败,那么新当选的领导者必须有这个提交的消息。
你有更多的 ISR; 在领导失败的时候选举越多。
法定人数是所需的确认数量,以及必须与选举领导人进行比较的日志数量,以确保可用性重叠。大多数系统使用多数票,Kafka 不使用简单的多数投票来提高可用性。
在 Kafka,领导人的选择是基于完整的日志。如果我们有一个复制因子 3,那么至少两个 ISR 必须在领导者声明发送的消息提交之前同步。如果一个新的领导者需要当选,不超过 3 次失败,新的领导者保证有所有承诺的信息。
在追随者中,必须至少有一个包含所有提交的消息的副本。大多数投票的问题法定人数是没有多少失败,有一个无法操作的群集。
Kafka 为每个领导人维护一套情监侦。只有这一套 ISR 的成员才有资格领导选举。在所有 ISR 确认写入之前,生产者写入分区的内容不会被提交。只要 ISR 设置发生变化,ISR 就会持续到 ZooKeeper。只有属于 ISR 成员的副本才有资格当选领导。
ISR 法定人数的这种风格允许生产者在没有大多数所有节点的情况下继续工作,但只有 ISR 多数票。ISR 仲裁的这种风格也允许副本重新加入 ISR 集并且拥有其投票计数,但是在加入之前必须完全重新同步,即使副本在其崩溃期间丢失未刷新的数据也是如此。
Kafka 关于数据丢失的保证只有在至少一个副本同步的情况下才有效。
如果所有正在复制分区领导者的追随者都立即死亡,那么数据丢失 Kafka 保证是无效的。如果分区的所有副本都关闭,则默认情况下,Kafka 选择作为首领活动的第一个副本(不一定在 ISR 集合中)(config unclean.leader.election.enable = true 是缺省值)。这种选择有利于可用性的一致性。
如果一致性比您的用例的可用性更重要,那么您可以设置配置,
那么如果所有副本都停止运行一个分区,Kafka 会等待第一个 ISR 成员(而不是第一个副本)活跃起来以选出新的领导者。
- unclean.leader.election.enable=false
生产者可以通过设置 acks(0),仅前导(1)或所有副本(-1)来选择耐久性。
acks = all 是默认值。总而言之,当所有当前的同步复制品(ISR)都收到该消息时,便会发生这种情况。
您可以在一致性和可用性之间进行权衡。如果耐用性超过可用性,那么禁用不干净的领导者选举并指定最小的 ISR 大小。
最小的 ISR 规模越大,保证一致性就越好。但是,如果 ISR 集的大小小于最小阈值,则 ISR 的最小 ISR 越高,可用性就越低,因为分区不可用。
Kafka 已经为消费者和生产者制定了限制他们被允许消费的带宽的限额。这些配额阻止消费者或生产者占用 Kafka 经纪人资源。配额是由客户端 ID 或用户。配额数据存储在 ZooKeeper 中,所以更改不需要重新启动 Kafka 代理。
使用配额限制消费者的带宽。
所有。这意味着所有 ISR 必须将消息写入其日志分区。
Kafka 选择第一个复制品(不一定在 ISR 集合中),作为领导者活跃起来,
以支持可用性。
- unclean.leader.election.enable=true
通过线路以及磁盘优化 IO 吞吐量。它还通过压缩整个批次来提高压缩效率。
成为高吞吐量,可扩展的流媒体数据平台,用于对日志聚合,用户活动等大容量事件流进行实时分析。
生产者原子写入,性能改进和生产者不发送重复的消息。
有三种消息传递语义:最多一次,至少一次,恰好一次。
来源: https://www.cnblogs.com/qcloud1001/p/8145016.html