8595 字
43 分钟
【译】 Kafka —— 日志处理领域的分布式消息系统

Kafka:用于日志处理的分布式消息系统#

Jay Kreps
LinkedIn
jkreps@linkedin.com

Neha Narkhede
LinkedIn
nnarkhede@linkedin.com

Jun Rao
LinkedIn
jrao@linkedin.com

摘要#

日志处理已成为消费者互联网公司数据管道的重要组成部分。我们介绍了一种名为Kafka的分布式消息系统,用于以低延迟收集和传递大量日志数据。我们的系统融合了现有日志聚合器和消息系统的理念,适用于离线和在线消息消费。Kafka在设计上做出了一些非传统但实用的选择,使系统高效且可扩展。实验结果表明,Kafka在性能上优于两种流行的消息系统。我们已在生产环境中使用Kafka一段时间,每天处理数百GB的新数据。

通用术语#

管理、性能、设计、实验

关键词#

消息传递、分布式、日志处理、吞吐量、在线

1. 引言#

在任何规模较大的互联网公司中,都会生成大量的“日志”数据。这些数据通常包括:(1) 用户活动事件,如登录、页面浏览、点击、“点赞”、分享、评论和搜索查询;(2) 运营指标,如服务调用堆栈、调用延迟、错误以及每台机器的CPU、内存、网络或磁盘利用率等系统指标。日志数据长期以来一直是分析用户参与度、系统利用率等指标的重要组成部分。然而,近期互联网应用的趋势使得活动数据直接成为生产数据管道的一部分,用于网站功能。这些用途包括:(1) 搜索相关性;(2) 基于项目流行度或活动流中共同出现的推荐;(3) 广告定位和报告;(4) 防止垃圾信息或未经授权数据抓取的安全应用;(5) 聚合用户状态更新或操作供“朋友”或“联系人”阅读的新闻流功能。

这些生产环境的实时日志数据使用带来了新的挑战,因为其数据量比“真实”数据大几个数量级。例如,搜索、推荐和广告通常需要计算细粒度的点击率,这不仅为每次用户点击生成日志记录,还为页面上未被点击的数十个项目生成记录。每天,中国移动收集5-8TB的电话通话记录[11],Facebook收集近6TB的各种用户活动事件[12]。

许多早期处理此类数据的系统依赖于从生产服务器上物理抓取日志文件进行分析。近年来,出现了几种专门的分布式日志聚合器,包括Facebook的Scribe[6]、Yahoo的Data Highway[4]和Cloudera的Flume[3]。这些系统主要设计用于收集日志数据并加载到数据仓库或Hadoop[8]进行离线消费。在LinkedIn(一家社交网络网站),我们发现除了传统离线分析外,还需要支持上述大多数实时应用,延迟不超过几秒。

我们开发了一种名为Kafka[18]的新型基于消息的日志处理系统,结合了传统日志聚合器和消息系统的优点。一方面,Kafka是分布式的、可扩展的,并提供高吞吐量;另一方面,Kafka提供类似于消息系统的API,允许应用程序实时消费日志事件。Kafka已开源并在LinkedIn的生产环境中成功使用超过6个月。它极大地简化了我们的基础设施,因为我们可以利用单一软件同时支持所有类型的日志数据的在线和离线消费。本文的结构如下:第2节回顾传统消息系统和日志聚合器;第3节描述Kafka的架构及其关键设计原则;第4节介绍Kafka在LinkedIn的部署;第5节展示Kafka的性能结果;第6节讨论未来工作并总结。

2. 相关工作#

传统企业消息系统[1][7][15][17]存在已久,通常作为处理异步数据流的事件总线发挥关键作用。然而,它们不适合日志处理有以下几个原因。首先,企业系统的功能存在不匹配。这些系统通常专注于提供丰富的传递保证。例如,IBM Websphere MQ[7]支持事务,允许应用程序将消息原子性地插入多个队列。JMS[14]规范允许对每条消息进行确认,且可能无序确认。这些传递保证对于收集日志数据往往过于复杂。例如,偶尔丢失一些页面浏览事件并非灾难。这些不必要的功能往往增加了系统API和底层实现的复杂性。其次,许多系统并未将吞吐量作为主要设计约束。例如,JMS没有API允许生产者显式地将多条消息批量发送为单个请求。这意味着每条消息需要完整的TCP/IP往返,这对于我们领域的吞吐量要求不可行。第三,这些系统在分布式支持方面较弱。没有简单的方法在多台机器上分区和存储消息。最后,许多消息系统假设消息几乎立即被消费,因此未消费消息的队列通常较小。如果消息被允许积累(如离线消费者,如数据仓库应用,定期进行大批量加载而非持续消费),性能会显著下降。

过去几年中,出现了一些专门的日志聚合器。Facebook使用名为Scribe的系统。每台前端机器通过套接字将日志数据发送到一组Scribe机器。每台Scribe机器聚合日志条目,并定期将其转储到HDFS[9]或NFS设备。Yahoo的Data Highway项目具有类似的数据流。一组机器从客户端聚合事件,并生成“分钟”文件,随后添加到HDFS。Flume是Cloudera开发的一种较新的日志聚合器,支持可扩展的“管道”和“接收器”,使日志数据流处理非常灵活。它还具有更集成的分布式支持。然而,这些系统大多是为离线消费日志数据而构建的,并且常常不必要地暴露实现细节(例如“分钟文件”)给消费者。此外,这些系统大多采用“推送”模型,由代理将数据转发给消费者。在LinkedIn,我们发现“拉取”模型更适合我们的应用,因为每个消费者可以以其能承受的最大速率检索消息,避免被推送的消息淹没。拉取模型还便于消费者回溯,我们将在第3.2节末尾讨论这一优势。

最近,Yahoo! Research开发了一种新的分布式发布/订阅系统HedWig[13]。HedWig具有高可扩展性和可用性,并提供强大的持久性保证。然而,它主要用于存储数据存储的提交日志。

3. Kafka架构与设计原则#

由于现有系统的局限性,我们开发了一种新型基于消息的日志聚合器Kafka。我们首先介绍Kafka的基本概念。特定类型的消息流由一个主题(topic)定义。生产者(producer)可以向主题发布消息。发布消息存储在一组称为代理(brokers)的服务器上。消费者(consumer)可以从代理订阅一个或多个主题,并通过从代理拉取数据来消费订阅的消息。

消息传递在概念上很简单,我们努力使Kafka的API同样简单以反映这一点。我们不展示确切的API,而是通过示例代码展示API的使用方式。以下是生产者的示例代码。消息仅包含字节有效负载。用户可以选择喜欢的序列化方法来编码消息。为提高效率,生产者可以在单个发布请求中发送一组消息。

示例生产者代码:#

producer = new Producer(...);
message = new Message("test message str".getBytes());
set = new MessageSet(message);
producer.send("topic1", set);

要订阅一个主题,消费者首先为该主题创建一条或多条消息流。发布到该主题的消息将均匀分布到这些子流中。Kafka如何分配消息的细节将在第3.2节中描述。每条消息流提供了一个迭代器接口,覆盖持续生成的消息流。消费者遍历流中的每条消息并处理消息的有效负载。与传统迭代器不同,消息流迭代器永不终止。如果当前没有更多消息可消费,迭代器将阻塞直到新消息发布到主题。我们支持点对点传递模型(多个消费者共同消费主题中所有消息的单一副本)和发布/订阅模型(多个消费者各自检索主题的副本)。

示例消费者代码:#

streams[] = Consumer.createMessageStreams("topic1", 1)
for (message : streams[0]) {
bytes = message.payload();
// 对字节进行处理
}

Kafka的总体架构如图1所示。由于Kafka是分布式的,Kafka集群通常由多个代理组成。为了平衡负载,一个主题被划分为多个分区,每个代理存储一个或多个分区。多个生产者和消费者可以同时发布和检索消息。在第3.1节中,我们描述单个分区的布局以及我们为提高分区访问效率所做的设计选择。在第3.2节中,我们描述生产者和消费者如何在分布式环境中与多个代理交互。在第3.3节中,我们讨论Kafka的传递保证。

figure1

图1. Kafka架构

3.1 单一分区的效率#

我们在Kafka中做出了一些决策以提高系统效率。

简单存储:Kafka具有非常简单的存储布局。主题的每个分区对应一个逻辑日志。物理上,日志由一组大小大致相同的段文件(例如1GB)实现。每次生产者向分区发布消息时,代理仅将消息追加到最后一个段文件。为提高性能,我们仅在发布了一定数量的消息或经过一定时间后将段文件刷新到磁盘。消息只有在刷新后才对消费者可见。与典型消息系统不同,Kafka中存储的消息没有显式的消息ID。相反,每条消息通过其在日志中的逻辑偏移量寻址。这避免了维护将消息ID映射到实际消息位置的辅助、寻址密集型随机访问索引结构的开销。请注意,我们的消息ID是递增但不连续的。要计算下一条消息的ID,需要将当前消息的长度加到其ID上。以下我们将消息ID和偏移量互换使用。

消费者总是按顺序从特定分区消费消息。如果消费者确认了某个消息偏移量,意味着消费者已接收到该分区中该偏移量之前的所有消息。在底层,消费者向代理发出异步拉取请求,以准备一个数据缓冲区供应用程序消费。每个拉取请求包含开始消费的消息偏移量和可接受的获取字节数。每个代理在内存中维护一个排序的偏移量列表,包括每个段文件的首条消息偏移量。代理通过搜索偏移量列表定位请求消息所在的段文件,并将数据发送回消费者。消费者在接收到消息后,计算下一条要消费的消息偏移量,并将其用于下一个拉取请求。Kafka日志和内存索引的布局如图2所示。每个框显示消息的偏移量。

figure2

图2. Kafka日志

高效传输:我们在Kafka中非常注意数据的输入输出。前面已展示生产者可以在单个发送请求中提交一组消息。尽管最终消费者API一次迭代一条消息,但在底层,每个消费者的拉取请求也会检索多条消息,通常高达数百KB。

我们还做出了一个非传统选择:避免在Kafka层显式缓存消息。相反,我们依赖底层文件系统的页面缓存。这主要避免了双重缓冲——消息仅在页面缓存中缓存。这还带来了即使代理进程重启也能保留热缓存的额外好处。由于Kafka完全不在进程中缓存消息,其内存垃圾回收开销非常小,使得在基于虚拟机的语言中实现高效成为可能。最后,由于生产者和消费者都按顺序访问段文件,且消费者通常仅略微滞后于生产者,常规操作系统缓存启发式(特别是写穿缓存和预读)非常有效。我们发现生产和消费的性能与数据大小成线性关系,最高可达数TB数据。

此外,我们优化了消费者的网络访问。Kafka是多订阅者系统,单条消息可能被不同消费者应用多次消费。从本地文件到远程套接字发送字节的典型方法包括以下步骤:(1) 从存储介质读取数据到操作系统页面缓存;(2) 将页面缓存中的数据复制到应用程序缓冲区;(3) 将应用程序缓冲区复制到另一个内核缓冲区;(4) 将内核缓冲区发送到套接字。这包括4次数据复制和2次系统调用。在Linux和其他Unix操作系统上,存在sendfile API[5],可直接从文件通道传输字节到套接字通道。这通常避免了步骤(2)和(3)中的两次复制和一次系统调用。Kafka利用sendfile API高效地从代理的日志段文件向消费者传递字节。

无状态代理:与大多数其他消息系统不同,Kafka中关于每个消费者消费了多少信息的记录不是由代理维护,而是由消费者自身维护。这种设计大大降低了代理的复杂性和开销。然而,这使得删除消息变得棘手,因为代理不知道是否所有订阅者都消费了该消息。Kafka通过基于时间的简单服务级别协议(SLA)解决此问题。如果消息在代理中保留超过一定时间(通常为7天),则自动删除。这种解决方案在实践中效果良好。大多数消费者,包括离线消费者,通常每天、每小时或实时完成消费。Kafka性能不随数据大小增加而下降,使得长期保留成为可能。

这一设计的另一个重要好处是,消费者可以故意回溯到旧偏移量并重新消费数据。这违反了队列的常见契约,但对许多消费者来说是必不可少的功能。例如,当消费者应用程序逻辑出现错误时,修复错误后可以重新播放某些消息。这对于将数据加载到数据仓库或Hadoop系统的ETL过程尤为重要。另一个例子是,消费的数据可能仅定期刷新到持久存储(例如全文索引器)。如果消费者崩溃,未刷新的数据会丢失。在这种情况下,消费者可以检查点未刷新消息的最小偏移量,并在重启时从该偏移量重新消费。我们注意到,在拉取模型中支持消费者回溯比推送模型更容易。

3.2 分布式协调#

我们现在描述生产者和消费者在分布式环境中的行为。每个生产者可以向随机选择的分区或通过分区键和分区函数语义确定的分区发布消息。我们将重点讨论消费者如何与代理交互。

Kafka具有消费者组的概念。每个消费者组由一个或多个共同消费一组订阅主题的消费者组成,即每条消息仅传递给组内的一个消费者。不同消费者组独立消费完整的订阅消息集,组间无需协调。同一组内的消费者可以在不同进程或不同机器上。我们的目标是将代理中存储的消息在消费者之间均匀分配,同时避免引入过多协调开销。

我们的第一个决定是将主题内的分区作为并行性的最小单位。这意味着在任何给定时间,一个分区的所有消息仅由每个消费者组内的一个消费者消费。如果允许多个消费者同时消费一个分区,他们需要协调谁消费哪些消息,这需要锁定和状态维护开销。相比之下,我们的设计中,消费进程仅在消费者重新平衡负载时需要协调,这是一个不频繁的事件。为了实现真正的负载均衡,我们要求主题中的分区数远多于每个组中的消费者数。通过过度分区主题可以轻松实现这一点。

第二个决定是不设置中心“主”节点,而是让消费者以去中心化方式协调。添加主节点会增加系统复杂性,因为需要进一步考虑主节点故障。为了便于协调,我们使用高可用性共识服务Zookeeper[10]。Zookeeper具有类似文件系统的简单API,可以创建路径、设置路径值、读取路径值、删除路径和列出路径的子节点。它还提供以下功能:(a) 可以在路径上注册观察者,当路径的子节点或值发生变化时收到通知;(b) 路径可以创建为临时路径(相对于持久路径),如果创建客户端断开连接,Zookeeper服务器会自动删除该路径;(c) Zookeeper将其数据复制到多个服务器,使数据高可靠和高可用。

Kafka使用Zookeeper执行以下任务:(1) 检测代理和消费者的添加和移除;(2) 在发生上述事件时触发每个消费者的重新平衡过程;(3) 维护消费关系并跟踪每个分区的已消费偏移量。具体来说,当每个代理或消费者启动时,它在Zookeeper的代理或消费者注册表中存储其信息。代理注册表包含代理的主机名、端口以及存储在其上的主题和分区集。消费者注册表包括消费者所属的消费者组及其订阅的主题集。每个消费者组与Zookeeper中的所有权注册表和偏移量注册表相关联。所有权注册表为每个订阅分区创建一个路径,路径值是当前消费该分区的消费者ID(我们使用术语消费者拥有该分区)。偏移量注册表为每个订阅分区存储最后消费消息的偏移量。

Zookeeper中的代理注册表、消费者注册表和所有权注册表中的路径是临时的,偏移量注册表中的路径是持久的。如果代理失败,其上的所有分区会自动从代理注册表中移除。消费者失败会导致其在消费者注册表中的条目以及其在所有权注册表中拥有的所有分区丢失。每个消费者在代理注册表和消费者注册表上注册Zookeeper观察者,并在代理集或消费者组发生变化时收到通知。

当消费者初始启动或通过观察者收到代理/消费者变化通知时,消费者启动重新平衡过程以确定其应消费的新分区子集。该过程在算法1中描述。通过从Zookeeper读取代理和消费者注册表,消费者首先计算订阅主题T的可用分区集(P_T)和订阅T的消费者集(C_T)。然后将P_T按范围分区为|C_T|个块,并确定性地选择一个块拥有。对于消费者选择的每个分区,它将自己写入所有权注册表作为该分区的新拥有者。最后,消费者启动一个线程从每个拥有的分区拉取数据,从偏移量注册表中存储的偏移量开始。随着从分区拉取消息,消费者定期更新偏移量注册表中的最新消费偏移量。

当组内有多个消费者时,每个消费者都会收到代理或消费者变化的通知。然而,通知可能在消费者之间略有不同时间。因此,一个消费者可能尝试占有仍由另一个消费者拥有的分区。当这种情况发生时,第一个消费者简单地释放其当前拥有的所有分区,稍等片刻后重试重新平衡过程。在实践中,重新平衡过程通常只需几次重试即可稳定。

当创建新的消费者组时,偏移量注册表中没有偏移量。在这种情况下,消费者将从每个订阅分区的最小或最大偏移量(取决于配置)开始消费,使用我们在代理上提供的API。

算法1:消费者C_i在组G中的重新平衡过程

algo1

3.3 传递保证#

一般来说,Kafka仅保证至少一次传递。精确一次传递通常需要两阶段提交,这对我们的应用来说不是必需的。大多数情况下,每条消息对每个消费者组仅传递一次。然而,当消费者进程在未干净关闭的情况下崩溃时,接管失败消费者拥有的分区的消费者进程可能会收到一些重复消息,这些消息位于成功提交到Zookeeper的最后偏移量之后。如果应用程序关心重复消息,必须自行添加去重逻辑,可以使用我们返回给消费者的偏移量或消息内的唯一键。这种方法通常比使用两阶段提交更具成本效益。

Kafka保证来自同一分区的消息按顺序传递给消费者。然而,不保证来自不同分区的消息顺序。

为避免日志损坏,Kafka为每条消息存储一个CRC。如果代理发生I/O错误,Kafka运行恢复过程以移除具有不一致CRC的消息。在消息级别具有CRC还允许在消息生产或消费后检查网络错误。

如果代理宕机,存储在其上尚未消费的消息将不可用。如果代理上的存储系统永久损坏,任何未消费的消息将永久丢失。未来,我们计划在Kafka中添加内置复制,将每条消息冗余存储在多个代理上。

4. Kafka在LinkedIn的使用#

在本节中,我们描述Kafka在LinkedIn的使用情况。图3显示了我们的部署简化版本。我们在每个运行面向用户服务的数据库中部署了一个Kafka集群。前端服务生成各种日志数据,并以批次发布到本地Kafka代理。我们依赖硬件负载均衡器将发布请求均匀分布到一组Kafka代理。在线消费者在同一数据中心的服务的Kafka中运行。

figure3

图3. Kafka部署

我们还在靠近Hadoop集群和其他数据仓库基础设施的单独数据中心部署了一个Kafka集群用于离线分析。此Kafka实例运行一组嵌入式消费者,从实时数据中心的Kafka实例拉取数据。然后我们运行数据加载作业,将数据从此副本Kafka集群拉取到Hadoop和数据仓库,在那里运行各种报告和分析过程。我们还使用此Kafka集群进行原型设计,并能够针对原始事件流运行简单脚本进行临时查询。在不进行过多调优的情况下,完整管道的端到端延迟平均约为10秒,满足我们的需求。

目前,Kafka每天累积数百GB的数据和近10亿条消息,我们预计随着将传统系统转换为利用Kafka,这一数字将显著增长。未来将添加更多类型的消息。重新平衡过程能够自动重定向消费,当操作人员因软件或硬件维护启动或停止代理时。

我们的跟踪还包括一个审计系统,以验证整个管道中没有数据丢失。为此,每条消息携带生成时的.timestamp和服务器名称。我们对每个生产者进行仪器化,使其定期生成监控事件,记录在固定时间窗口内为每个主题发布的消息数量。生产者将监控事件发布到Kafka的单独主题。消费者随后可以统计从给定主题接收的消息数量,并通过监控事件验证这些计数的正确性。

加载到Hadoop集群通过实现特殊的Kafka输入格式完成,允许MapReduce作业直接从Kafka读取数据。MapReduce作业加载原始数据,然后对其分组和压缩以便将来高效处理。无状态代理和客户端存储消息偏移量在此再次发挥作用,允许MapReduce任务管理(允许任务失败和重启)以自然方式处理数据加载,在任务重启时不重复或丢失消息。仅在作业成功完成时,数据和偏移量才存储在HDFS中。

我们选择使用Avro[2]作为序列化协议,因为它高效且支持模式演化。对于每条消息,我们存储其Avro模式ID和序列化字节在有效负载中。此模式允许我们强制执行契约以确保数据生产者和消费者之间的兼容性。我们使用轻量级模式注册服务将模式ID映射到实际模式。当消费者接收到消息时,它在模式注册服务中查找以检索模式,用于将字节解码为对象(每个模式仅需查找一次,因为值是不可变的)。

5. 实验结果#

我们进行了实验研究,比较Kafka与Apache ActiveMQ v5.4[1](JMS的流行开源实现)和RabbitMQ v2.4[16](以性能著称的消息系统)的性能。我们使用了ActiveMQ的默认持久消息存储KahaDB。虽然未在此展示,我们还测试了另一种AMQ消息存储,发现其性能与KahaDB非常相似。尽可能使用所有系统的可比较设置。

我们在两台Linux机器上运行实验,每台机器有8个2GHz核心、16GB内存、6个磁盘配置为RAID 10。两台机器通过1Gb网络链接连接。一台机器用作代理,另一台用作生产者或消费者。

生产者测试:我们配置所有系统的代理异步将消息刷新到其持久存储。对于每个系统,我们运行单一生产者发布总计1000万条消息,每条消息200字节。我们配置Kafka生产者以1和50的批次大小发送消息。ActiveMQ和RabbitMQ似乎没有简单的方法批量发送消息,我们假设其批次大小为1。结果如图4所示。x轴表示随时间发送到代理的数据量(MB),y轴对应生产者吞吐量(每秒消息数)。平均而言,Kafka以每秒50,000和400,000条消息的速率发布消息,分别对应批次大小1和50。这些数字比ActiveMQ高出几个数量级,至少是RabbitMQ的两倍。

figure4

图4. 生产者性能

Kafka性能更好的原因有以下几点。首先,Kafka生产者当前不等待代理的确认,并以代理能处理的最快速度发送消息。这显著提高了发布者的吞吐量。批次大小为50时,单一Kafka生产者几乎饱和了生产者与代理之间的1Gb链接。这是日志聚合情况下的有效优化,因为数据必须异步发送以避免对实时流量服务引入任何延迟。我们注意到,不确认生产者无法保证每条发布消息实际上被代理接收。对于许多类型的日志数据,牺牲持久性换取吞吐量是可取的,只要丢失的消息数量相对较少。然而,我们计划在未来为更关键的数据解决持久性问题。

其次,Kafka具有更高效的存储格式。平均而言,Kafka每条消息的开销为9字节,而ActiveMQ为144字节。这意味着ActiveMQ存储1000万条相同消息比Kafka多使用70%的空间。ActiveMQ的开销之一来自JMS要求的沉重消息头。另一个开销是维护各种索引结构的成本。我们观察到ActiveMQ中最繁忙的线程之一大部分时间用于访问B树以维护消息元数据和状态。最后,批处理通过分摊RPC开销大大提高了吞吐量。在Kafka中,批次大小为50条消息将吞吐量提高了近一个数量级。

消费者测试:在第二个实验中,我们测试了消费者的性能。同样,对于所有系统,我们使用单一消费者检索总计1000万条消息。我们配置所有系统,使每个拉取请求预取大致相同的数据量——最多1000条消息或约200KB。对于ActiveMQ和RabbitMQ,我们将消费者确认模式设置为自动。由于所有消息都在内存中,所有系统都从底层文件系统的页面缓存或某些内存缓冲区提供数据。结果如图5所示。

平均而言,Kafka每秒消费22,000条消息,是ActiveMQ和RabbitMQ的4倍以上。原因有以下几点。首先,由于Kafka具有更高效的存储格式,从代理传输到消费者的字节数更少。其次,ActiveMQ和RabbitMQ的代理必须维护每条消息的传递状态。我们观察到ActiveMQ的一个线程在此测试期间忙于将KahaDB页面写入磁盘。相比之下,Kafka代理没有磁盘写入活动。最后,通过使用sendfile API,Kafka减少了传输开销。

figure5

图5. 消费者性能

我们在此结束本节时指出,实验的目的不是显示其他消息系统不如Kafka。毕竟,ActiveMQ和RabbitMQ具有比Kafka更多的功能。主要目的是说明专门系统可实现的潜在性能增益。

6. 结论与未来工作#

我们提出了一种名为Kafka的新型系统,用于处理大量日志数据流。与消息系统类似,Kafka采用拉取式消费模型,允许应用程序以自己的速率消费数据,并在需要时回溯消费。通过专注于日志处理应用,Kafka实现了比传统消息系统高得多的吞吐量。它还提供集成的分布式支持并可扩展。我们已在LinkedIn成功使用Kafka进行离线和在线应用。

未来我们希望探索以下几个方向。首先,我们计划添加消息跨多个代理的内置复制,以确保即使在不可恢复的机器故障情况下也能保证持久性和数据可用性。我们希望支持异步和同步复制模型,以允许在生产者延迟和保证强度之间进行权衡。应用程序可根据其对持久性、可用性和吞吐量的要求选择适当的冗余级别。其次,我们希望在Kafka中添加一些流处理能力。从Kafka检索消息后,实时应用程序通常执行类似操作,如基于窗口的计数或将每条消息与辅助存储中的记录或其他流中的消息进行连接。在最低级别,这通过在发布时对连接键进行语义分区得到支持,确保具有特定键发送的所有消息进入同一分区,从而到达单一消费者进程。这为在消费者机器集群上处理分布式流提供了基础。在此基础上,我们认为一个包含有用的流实用工具的库,如不同的窗口函数或连接技术,将对这类应用有益。

7. 参考文献#

[1] http://activemq.apache.org/

[2] http://avro.apache.org/

[3] Cloudera的Flume, https://github.com/cloudera/flume

[4] http://developer.yahoo.com/blogs/hadoop/posts/2010/06/enabling_hadoop_batch_processing_1/

[5] 通过零拷贝实现高效数据传输: https://www.ibm.com/developerworks/linux/library/j-zero-copy/

[6] Facebook的Scribe, http://www.facebook.com/note.php?note_id=32008268919

[7] IBM Websphere MQ: http://www-01.ibm.com/software/integration/wmq/

[8] http://hadoop.apache.org/

[9] http://hadoop.apache.org/hdfs/

[10] http://hadoop.apache.org/zookeeper/

[11] http://www.slideshare.net/cloudera/hw09-hadoop-based-data-mining-platform-for-the-telecom-industry

[12] http://www.slideshare.net/prasadc/hive-percona-2009

[13] https://issues.apache.org/jira/browse/ZOOKEEPER-775

[14] Java消息服务: http://download.oracle.com/javaee/1.3/jms/tutorial/1_3_1-fcs/doc/jms_tutorialTOC.html

[15] Oracle企业消息服务: http://www.oracle.com/technetwork/middleware/ias/index-093455.html

[16] http://www.rabbitmq.com/

[17] TIBCO企业消息服务: http://www.tibco.com/products/soa/messaging/

[18] Kafka, http://sna-projects.com/kafka/

原论文

版权声明
允许为个人或课堂使用制作本文全部或部分的数字或硬拷贝,条件是不得为盈利或商业优势制作或分发副本,且副本需保留此声明和首页的完整引用。其他复制、发布、发布到服务器或重新分发到列表的行为需获得事先特定许可和/或费用。
NetDB’11, 2011年6月12日, 希腊雅典.
版权 2011 ACM 978-1-4503-0652-2/11/06

【译】 Kafka —— 日志处理领域的分布式消息系统
https://fuwari.vercel.app/posts/kafka_papper/
作者
Simon
发布于
2025-03-20
许可协议
CC BY-NC-SA 4.0