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

Dav*_* J. 160 apache-kafka

在使用新服务(例如非RDBMS数据存储或消息队列)时,我想到的第一件事是:"我应该如何构建数据?".

我已经阅读并观看了一些介绍性材料.特别是,例如,采用Kafka:一种用于日志处理的分布式消息系统,它写道:

  • "主题是与消息相关联的容器"
  • "最小的并行单元是主题的分区.这意味着......属于某个主题的特定分区的所有消息都将被消费者组中的消费者使用."

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

举个例子,假设我的(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"}
Run Code Online (Sandbox Code Playgroud)

主题应该基于user-idviewedat?分区怎么样?

我该如何决定?

Lun*_*ahl 131

在为Kafka构建数据时,它实际上取决于它的消费意义.

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

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

另一方面,分区是一种并行化消息消耗的方法,并且代理群集中的分区总数需要至少与消费者组中的消费者数量相同,以便了解分区功能.消费者群体中的消费者将根据分区将处理主题的负担分开,以便一个消费者仅关注分区本身中的消息被"分配给".

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

  • 因此,不是使用主题作为获取每个用户ID的数据的方式,从而压倒Zookeeper,最好按用户ID进行分区,并且如果基于用户ID的消费者订阅每个分区? (5认同)
  • @RavindranathAkila`Kafka的设计数量级为数千个,大约不到10,000个.而主要的瓶颈是zookeeper.设计这样一个系统的一个更好的方法是使用更少的分区并使用键控消息在一组固定的分区上分发数据.让我觉得它不是你所描述的正确的工具 - 但更多,主题是"页面查看事件"?并且所有页面视图都将在该"主题"中.分区似乎更多关于并行性和复制品和东西? (4认同)
  • http://mail-archives.apache.org/mod_mbox/kafka-users/201310.mbox/%3CCA+Vbu7zMRWuLiVLzC+iAdX+XJUb3xdZHaunxGJzNsC9QwrtYSg@mail.gmail.com%3E (2认同)

Ale*_*ean 57

一旦您知道如何对事件流进行分区,主题名称就很容易了,所以让我们首先回答这个问题.

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

例如:

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

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

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

关于主题名称 - 这里显而易见的是eventsuser-events.更具体地说,你可以选择events-by-user-id和/或events-by-viewed.

  • 我已经看到了将事件发布到两个主题的引用:每个工作者/预期用法一个.在这种情况下,可能有两个主题,具有两种不同的分区方案. (7认同)

Gua*_*Zuo 5

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

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

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

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

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


Bit*_*sky 5

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

关键要点:

  • 通常,Kafka群集中的分区越多,可以实现的吞吐量就越高。设单个生产分区上可达到的最大值为p,消耗为c。假设您的目标吞吐量为t。然后,您至少需要有max(t / pt / c)个分区。

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

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

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