繁体   English   中英

使用 Kafka 进行数据建模? 主题和分区

[英]Data Modeling with Kafka? Topics and Partitions

在使用新服务(例如非 RDBMS 数据存储或消息队列)时,我首先考虑的事情之一是:“我应该如何构建我的数据?”。

我阅读并观看了一些介绍性材料。 特别地,以Kafka: a Distributed Messaging System for Log Processing为例,它写道:

  • “主题是与消息关联的容器”
  • “并行的最小单位是主题的分区。这意味着......属于主题特定分区的所有消息将被消费者组中的消费者消费。”

知道了这一点,什么是说明如何使用主题和分区的好例子? 什么时候应该成为话题? 什么时候应该是分区?

例如,假设我的 (Clojure) 数据如下所示:

{:user-id 101 :viewed "/page1.html" :at #inst "2013-04-12T23:20:50.22Z"}
{:user-id 102 :viewed "/page2.html" :at #inst "2013-04-12T23:20:55.50Z"}

主题应该基于user-id吗? viewed吗? at 分区呢?

我如何决定?

在为 Kafka 构建数据时,它实际上取决于它的使用方式。

在我看来,主题是一组相似类型的消息,将由相同类型的消费者使用,因此在上面的示例中,我只有一个主题,如果您决定推送其他类型的消息通过 Kafka 获取数据,您可以稍后为其添加新主题。

主题在 ZooKeeper 中注册,这意味着如果尝试添加太多主题,您可能会遇到问题,例如,您拥有一百万用户并决定为每个用户创建一个主题。

另一方面,分区是一种并行化消息消费的方法。 代理集群中的分区总数至少需要与消费者组中的消费者数量相同才能理解分区功能。 消费者组中的消费者将根据分区在他们之间分担处理主题的负担,这样一个消费者将只关心分区本身被“分配给”的消息。

可以使用生产者端的分区键显式设置分区,或者如果未提供,将为每条消息选择一个随机分区。

一旦您知道如何对事件流进行分区,主题名称就会很简单,所以让我们先回答这个问题。

@Ludd 是正确的 - 您选择的分区结构在很大程度上取决于您希望如何处理事件流。 理想情况下,您需要一个分区键,这意味着您的事件处理是partition-local

例如:

  1. 如果您关心用户的平均现场时间,那么您应该按:user-id分区。 这样,与单个用户的站点活动相关的所有事件都将在同一分区中可用。 这意味着像Apache Samza这样的流处理引擎可以通过查看单个分区中的事件来计算给定用户的平均现场时间。 这避免了必须执行任何类型的昂贵的分区全局处理
  2. 如果您关心网站上最受欢迎的页面,则应按:viewed页面进行分区。 同样,Samza 将能够仅通过查看单个分区中的事件来记录给定页面的查看次数

通常,我们试图避免依赖全局状态(例如在 DynamoDB 或 Cassandra 等远程数据库中保持计数),而是能够使用分区本地状态工作。 这是因为本地状态是流处理中的基本原语

如果您需要上述两个用例,那么 Kafka 的一个常见模式是首先通过:user-id进行分区,然后通过:viewed重新分区,为下一阶段的处理做好准备。

关于主题名称 - 这里很明显的一个是eventsuser-events 更具体地说,您可以使用events-by-user-id和/或events-by-viewed

这与问题并不完全相关,但如果您已经决定基于主题对记录进行逻辑隔离,并且想要优化 Kafka 中的主题/分区计数,那么这篇博文可能会派上用场。

简而言之,关键要点:

  • 一般来说,Kafka 集群中的分区越多,可以实现的吞吐量就越高。 让生产的单个分区上可实现的最大吞吐量为p ,消费为c 假设您的目标吞吐量是t 那么你至少需要有 max( t / p , t / c ) 个分区。

  • 目前,在 Kafka 中,每个 broker 都会打开每个日志段的索引和数据文件的文件句柄。 因此,分区越多,需要在底层操作系统中配置打开文件句柄限制就越高。 例如,在我们的生产系统中,我们曾经看到过一个错误,说too many files are open ,而我们有大约 3600 个主题分区。

  • 当一个代理被不干净地关闭(例如,kill -9)时,观察到的不可用性可能与分区数成正比。

  • Kafka 中的端到端延迟定义为从生产者发布消息到消费者读取消息的时间。 根据经验,如果您关心延迟,将每个代理的分区数量限制为 100 x b x r可能是个好主意,其中b是 Kafka 集群中的代理数量, r是复制因子。

我认为主题名称是一种消息的结论,生产者向主题发布消息,消费者通过订阅主题订阅消息。

一个主题可以有多个分区。 分区有利于并行。 partition也是复制的单位,所以在Kafka中,leader和follower也是在partition这个层面上说的。 实际上,分区是一个有序队列,其顺序是消息到达顺序。 主题由一个或多个队列组成一个简单的词。 这对我们为我们的结构建模很有用。

Kafka 由 LinkedIn 开发,用于日志聚合和交付。 这个场景非常好作为例子。

用户在您的 Web 或应用程序上的事件可以由您的 Web 服务器记录,然后通过生产者发送到 Kafka 代理。 在生产者中,您可以指定分区方法,例如:事件类型(不同的事件保存在不同的分区中)或事件时间(根据您的应用程序逻辑将一天分成不同的时间段)或用户类型或没有逻辑并平衡所有日志分成许多分区。

关于你的案例,你可以创建一个名为“page-view-event”的topic,通过hash键创建N个分区,将日志平均分配到所有分区。 或者你可以选择一个分区逻辑,让日志按照你的精神进行分发。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM