简介
Apache Kafka是一个分布式流媒体平台。这到底是什么意思呢?
流媒体平台有三个关键功能:
- 系统具备发布和订阅流数据的能力, 在这方面, 它类似于消息队列或企业消息总线。
- 系统在存储数据时具备容错能力。
- 系统在数据流触发时具备进行实时处理的能力。
Kafka通常用于两大类应用:
- 在系统或应用程序之间用于处理数据流交互的实时系统。
- 需要对数据流中的数据进行转换或及时处理的实时系统。
要了解Kafka如何做这些事情,让我们深入探讨Kafka的能力。
首先是几个概念:
- Kafka作为一个集群运行在一台或多台服务器上(可跨多个数据中心)。
- Kafka集群以主题为类别划分数据流。
- 数据流中的每条记录由一个键,一个值和一个时间戳组成。
Kafka有四个核心API:
- Producer API :Producer API 用于将流数据发送至一个或多个Kafka主题中。
- Consumer API :Consumer API 用于应用程序在订阅一个或多个主题后,对他们所产生的数据流进行处理。
- Streams API :Streams API 使用来自一个或多个主题的输入流,并生成到一个或多个输出主题的输出流,提供一种有效的数据流处理方式。
- Connector API :Connector API允许构建和运行可重用的生产者或消费者,将Kafka主题连接到现有的应用程序或数据系统。例如, 创建一个到关系型数据库连接器, 用于捕获对某张表的所有数据变更。
在Kafka中,客户端和服务器之间的通信使用简单、高性能、语言无关的TCP协议完成。该协议经过版本控制,并与旧版本保持向后兼容性。我们为Kafka提供了一个Java客户端,除了Java客户端还可以使用多种语言。
主题和日志
主题:为记录流提供的核心抽象。
主题是发布记录的类别或提要名称。Kafka中的主题始终支持多个订阅者,即一个主题可以有零个、一个或多个订阅其所写数据的消费者。
针对每个主题队列, kafka集群构建一组这样的分区日志:
每个分区都是一个有序的、不可变的记录序列,这些记录连续地附加到一个结构化的提交日志中。分区中的每条记录都被分配了一个名为偏移量的连续id号,该偏移量是分区中每条记录的惟一地标识。
无论发布到Kafka的数据是否有被消费, 都会保留所有已经发布的记录, Kafka使用可配置的数据保存周期策略。例如,如果保留策略被设置为两天,那么在记录发布后的两天内,它是可用的,在此之后,它将被丢弃以释放空间。Kafka的性能在数据大小方面是稳定的,所以长时间存储数据不是存在问题。
实际上, 每个消费者唯一保存的元数据信息就是消费者当前消费日志的偏移位置.,偏移位置被消费者控制, 正常情况下, 如果消费者读取记录后, 偏移位置往前移动. 但是事实上, 由于偏移位置是消费者控制的, 所以消费者可以按照任何他喜欢的次序进行消费, 例如, 消费者可以重置偏移到之前的位置以便重新处理数据, 或者跳过头部从当前最新的位置进行消费。
这些特性表明Kafka消费者消费的代价是十分小的, 消费者可以随时消费或停止, 而对集群或其他消费者没有太多的影响, 例如你可以使用命令行工具, 像”tail”工具那样读取topic的内容, 而对其它消费者没有影响。
分区日志有几个这样目的, 首先, 它能扩大日志在单个服务器里面的大小, 每个分区大小必须适应它所属服务器规定的大小, 但是一个topic可以有任意很多个分区, 这样topic就能存储任意大小的数据量, 另一方面, 分区还和并发有关系。
分布式
日志的分区分布在Kafka集群中的服务器上,每个服务器处理数据并请求分区的共享。每个分区都在可配置数量的服务器上进行复制,以实现容错。
每个分区都有一台服务器是主节点, 另外零台或多台是从节点, 主节点责所有分区的读写请求, 从节点被动从主节点的分区同步数据. 如果主节点的分区失败了, 那么从节点的分区就会自动变成主的. 每台服务器的所有分区中, 只有部分会作为主分区, 另外部分作为从分区, 这样可以在集群中对个个服务器做负载均摊。
地狱复制
Kafka MirrorMaker为您的群集提供地理复制支持。使用MirrorMaker,可以跨多个数据中心或云区域复制邮件。您可以在主动/被动方案中使用它进行备份和恢复; 或者在主动/主动方案中,使数据更接近用户,或支持数据位置要求。
生产者
生产者将数据发布到他们选择的主题中。生产者负责选择分配给主题中哪个分区的记录。这可以通过循环方式完成,只是为了平衡负载,或者可以根据一些语义分区功能(例如基于记录中的某些键)来完成。
消费者
消费者使用消费组进行标记,发布到主题里面的每条记录, 至少会被消费组里面一个消费者实例进行消费. 。消费者实例可以在单独的进程中,也可以在不同的机器上。
如果所有的消费者属于同一消费组, 记录将有效地在使用者实例上进行负载均衡(每个消费者只会处理部分记录)。
如果所有的消费者都属于不同的消费组, 则记录会被广播到所有的消费者上(每个消费者会处理所有记录)。
Kafka群集包含两个服务器,拥有四个分区(P0-P3),包含两个使用者组。消费者A组有两个消费者实例,B组有四个消费者实例。
在大多数情况下, 一般一个主题只少量的消费者组, 一个消费组对应于一个逻辑上的消费者. 每个消费组一般包含多个实例用于容错和水平扩展. 这是发布订阅语义,其中订阅者是消费者群集,而不是单个消费者实例。
在kafka中实现日志消费的方式, 是把日志分区后分配到不同的消费者实例上, 所以每个实例在某个时间点都是”公平共享”式独占每个分区. 在这个处理过程中, 维持组内的成员是由kafka协议动态决定的, 如果有新的实例加入组中, 则会从组中的其他成员分配一些分区给新成员, 如果某个实例销毁了, 则它负责的分区也会分配给组内的其它成员。
kafka提供在一个日志分区里面顺序消费的能力, 在同一主题的不同分区里面是没有保证的. 由于记录可以结合键值做分区, 这样的分区顺序一般可以满足各个应用的需求了, 但是如果你要求主题下的所有记录都要按照次序进行消费, 则可以考虑为主题创建一个值分区, 这样意味着你这个主题只能让一个消费者消费。
多租户
您可以将Kafka部署为多租户解决方案。通过配置哪些主题可以生成或使用数据来启用多租户。配额也有运营支持。管理员可以定义和强制执行配额,以控制客户端使用的代理资源。
保障
一个高可用能的kafka集群有如下的保障:
- 同一个发布者发送到特定的日志分区后, 会按照他们发送的顺序进行添加, 例如 记录M1 和记录M2 都被同一个提供者发送, M1比较早发送, 则M1的位移值比M2小, 并记录在比较早的日志位置。
- 消费者实例按照日志记录的顺序进行读取。
- 如果topic有N个副本, 则可以容忍N-1台服务器宕机时, 提交的记录不会丢失。
作为消息系统
kafka的流概念和传统的企业消息系统有什么不一样呢?
传统的消息系统有两种模型, 队列模型和发布订阅模型, 在队列模型中, 一群消费者从服务器读取记录, 每条记录会分发到其中一个消费者中, 在发布和订阅模型中, 记录分发给所有的消费者. 这两种模型都有各自的优缺点, 队列的优点是它允许你把数据处理提交到多个消费者实例中, 适用于数据处理的水平扩展, 但是队列不是多订阅的, 一旦其中的一个消费者读取了记录, 则记录就算处理过了. 在发布订阅模型中允许你广播到记录到不同的订阅者上, 但是这种方式无法进行扩展处理。
卡夫卡的消费者群体概念概括了这两个概念。与队列一样,使用者组允许您将处理划分为一组进程(使用者组的成员)。与发布 订阅一样,Kafka允许向多个消费者组广播消息。
kafka这个模型的好处是, 这样每个topic都能同时拥有这样的属性, 既能消费者有水平扩展的处理能力, 又能允许有多个不同的订阅者–不需要让用户选择到底是要使用队列模型还是发布订阅模型。
与传统的消息系统相比,Kafka具有更强的消息顺序保证。
传统队列在服务器上按顺序保留记录,如果多个消费者从队列中消耗,则服务器按照存储顺序分发记录。但是,虽然服务器按顺序分发记录,但是记录是异步传递给消费者的,因此它们可能会在不同的消费者上无序传送。这实际上意味着在存在并行消耗的情况下丢失记录的顺序。消息传递系统通常通过具有“独占消费者”的概念来解决这个问题,该概念只允许一个进程从队列中消耗,但这意味着处理中没有并行性。
卡夫卡做得更好。在主题中具有并行性概念 - 分区,Kafka能够在消费者流程池中提供订购保证和负载平衡。这是通过将主题中的分区分配给使用者组中的使用者来实现的,以便每个分区仅由该组中的一个使用者使用。通过这样做,我们确保使用者是该分区的唯一读者并按顺序使用数据。由于有许多分区,这仍然可以平衡许多消费者实例的负载。但请注意,消费者组中的消费者实例不能超过分区。
作为存储系统
作为存储系统, 任意消息队列都允许发布到消息队列中, 并能高效消费这些消息记录, kafka不同的地方是它是一个很好的存储系统。
写入Kafka的数据将写入磁盘并进行复制以实现容错。Kafka允许生产者等待确认,以便在完全复制之前写入不被认为是完整的,并且即使写入的服务器失败也保证写入仍然存在。
Kafka使用的物理存储结构伸缩性很好,无论服务器上有50 KB还是50 TB的持久数据, kafka都具有同样的性能。
对于那些需要认真考虑存储性能, 并允许客户端自主控制读取位置的, 你可以把kafka当作是一种特殊的分布式文件系统, 并致力于高性能, 低延迟提交日志存储, 复制和传播。
用于流处理
仅仅读取、写入和存储数据流是不够的,最终的目的是使流实时处理。
kafka的流数据处理器是持续从输入的topic读取连续的数据流, 进行数据处理, 转换, 后产生连续的数据流输出到topic中。
聚合使用
这种消息传递、存储和流处理的组合可能看起来不寻常,但对于Kafka作为流平台的角色来说,这是必不可少的。
像hdfs分布式文件处理系统, 允许存储静态数据用于批处理, 能使得系统在处理和分析过往的历史数据时更为有效。
像传统的消息系统, 允许处理在你订阅之前的信息, 像这样的应用可以处理之前到达的数据。
kafka整合这些功能, 这些组合包括把kafka平台当作一个流处理应用, 或者是作为流处理的管道。
通过组合数据存储和低订阅开销, 流处理应用可以平等对待之前到达记录或即将到达的记录, 这就是一个应用可以处理历史存储的数据, 也可以在读到最后记录后, 保持等待未来的数据进行处理. 这是流处理,包括批处理以及消息驱动的应用的一个广义的概念。
同样的像流处理管道, 使用kafka在实时事件系统能实现比较低的延迟管道; 在kafka的存储能力, 使得一些离线系统, 如定时加载数据, 或者维护宕机时数据分发能力更有保障性. 流处理功能在数据到达时进行数据转换处理。
用例
消息中间件
Kafka 可以很好替代传统的消息中间件系统, 消息中间件系统的使用有多方面的原因(比如, 可以从生产者上解耦出数据处理, 缓冲未处理的数据),,相比其他消息中间件系统,Kafka具有更好的吞吐量,内置分区,复制和容错功能,这使其成为大规模消息处理应用程序的理想解决方案。
根据我们的经验,一般吞吐量都比较小, 更多的是要求更低的端到端的延迟, 这些功能都可以依赖于kafka的高可用保障。
在这个领域,Kafka可与传统的消息中间件(如ActiveMQ或 RabbitMQ)相媲美。
网页活动追踪
kafka最通常一种使用方式是通过构建用户活动跟踪管道作为实时发布和订阅反馈队列. 页面操作(查看, 检索或任何用户操作)都可以按活动类型发送的不同的topic上, 这些反馈信息, 有助于构建一个实时处理, 实时监控, 或加载到hadoop集群, 构建数据仓库用于离线处理和分析。
由于每个用户页面访问都要记录, 活动日志跟踪一般会有大量的访问消息被记录。
监控
Kafak还经常用于运行监控数据的存储, 这涉及到对分布式应用的运行数的及时汇总统计。
分布式日志系统
很多人使用kafka作为分布式日志系统的替代品. 日志聚合通常从服务器收集物理日志文件,并将它们放在中央位置(可能是文件服务器或HDFS)进行处理,Kafka抽象出文件的细节,并将日志或事件数据更清晰地抽象为消息流。这允许更低延迟的处理并更容易支持多个数据源和分布式数据消耗。与Scribe或Flume等以日志为中心的系统相比,Kafka提供了同样出色的性能,由于复制而具有更强的耐用性保证,以及更低的端到端延迟。
流处理
许多Kafka用户在处理由多个阶段组成的管道实时处理数据,其中原始输入数据从Kafka主题中消费,然后聚合,丰富或以其他方式转换为新主题以供进一步消费或后续处理。例如,用于推荐新闻文章的处理管道可以从RSS订阅源抓取文章内容并将其发布到“文章”主题; 进一步处理可能会对此内容进行规范化或重复数据删除,并将已清理的文章内容发布到新主题; 最终处理阶段可能会尝试向用户推荐此内容。此类处理管道基于各个主题创建实时数据流的图形。从0.10.0.0开始,这是一个轻量级但功能强大的流处理库,名为Kafka Streams 在Apache Kafka中可用于执行如上所述的此类数据处理。除了Kafka Streams之外,其他开源流处理工具包括Apache Storm和 Apache Samza。
事件源
事件源是一种应用程序设计风格,其中状态更改被记录为按时间排序的记录序列。Kafka对非常大的存储日志数据的支持使其成为以这种风格构建的应用程序的出色后端。
提交日志
Kafka可以作为分布式系统的一种外部提交日志。该日志有助于在节点之间复制数据,并充当故障节点恢复其数据的重新同步机制。Kafka中的日志压缩功能有助于支持此用法。在这种用法中,Kafka类似于Apache BookKeeper项目。