【问题标题】:Data Modeling with Kafka? Topics and Partitions使用 Kafka 进行数据建模?主题和分区
【发布时间】:2013-06-16 19:59:29
【问题描述】:

在使用新服务(例如非 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?分区呢?

我该如何决定?

【问题讨论】:

  • 奇怪的是这个话题和分区,但不一定是其中数据的演变。如果您想将用户代理或标头附加到那些“用户视图”事件怎么办?您如何发展并以某种方式与下游消费者沟通?
  • @OneCricketeer 对我来说听起来像是一个单独的问题 :) 去做吧......

标签: apache-kafka apache-zookeeper data-modeling


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 因此,与其使用主题作为获取每个用户 ID 数据的方式,从而压倒 Zookeeper,不如按用户 ID 分区,并让基于用户 ID 的消费者订阅每个分区,如果?
  • @RavindranathAkila Kafka is designed to have of the order of few thousands of partitions roughly less than 10,000. And the main bottleneck is zookeeper. A better way to design such a system is to have fewer partitions and use keyed messages to distribute the data over a fixed set of partitions. 让我觉得它不是您所描述的正确工具 - 但更多的是,主题将是“页面查看事件”?并且所有页面浏览量都在该“主题”中。分区似乎更多地是关于并行性和副本之类的?
  • 谢谢 :) 终于有回复了 :P
【解决方案2】:

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

简而言之关键要点:

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

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

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

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

【讨论】:

    【解决方案3】:

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

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

    Kafka 由 LinkedIn 开发,用于日志聚合和交付。这个场景就是很好的例子。

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

    关于您的案例,您可以创建一个名为“page-view-event”的主题,并通过哈希键创建N个分区,将日志平均分配到所有分区。或者你可以选择一个分区逻辑,让你的精神分配日志。

    【讨论】:

      【解决方案4】:

      一旦你知道如何划分你的事件流,主题名称就很容易了,所以让我们先回答这个问题。

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

      例如:

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

      通常,我们试图避免依赖全局状态(例如将计数保存在 DynamoDB 或 Cassandra 等远程数据库中),而是能够使用分区本地状态工作。这是因为local state is a fundamental primitive in stream processing

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

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

      【讨论】:

      • 我看到了您将事件发布到两个主题的参考资料:每个工作人员/预期用途一个。在这种情况下,可能有两个主题,具有两种不同的分区方案。
      猜你喜欢
      • 2019-12-05
      • 1970-01-01
      • 2016-10-01
      • 2016-10-27
      • 2016-11-15
      • 2017-04-03
      • 2015-03-05
      • 1970-01-01
      相关资源
      最近更新 更多