用Kafka进行数据build模? 主题和分区
在使用新服务(如非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"}
该主题是否应该基于user-id
? viewed
? at
? 那分区怎么样?
我如何决定?
在为卡夫卡(Kafka)构build数据时,真正取决于它如何被消费。
在我看来,一个话题是一组类似的消息,将被同一types的消费者消费,所以在上面的例子中,我只是有一个单一的话题,如果你决定推其他types的消息通过卡夫卡的数据,你可以在以后添加一个新的话题。
在ZooKeeper中注册了主题,这意味着如果尝试添加太多的话,可能会遇到问题,例如,如果您有一百万个用户,并决定为每个用户创build一个主题。
另一方面,分区是并行化消息消耗的一种方式,代理群集中的分区总数至less要与消费群中的消费者数量相同,以便理解分区function。 消费者群体中的消费者将根据分区来将处理该话题的负担分解,使得一个消费者只关心分区本身中的消息被“分配给”。
可以使用生产者端的分区键明确设置分区,或者如果不提供分区,将为每个消息select一个随机分区。
一旦你知道如何分割你的事件stream,主题名称将很容易,所以我们先回答这个问题。
@Ludd是正确的 – 你select的分区结构在很大程度上取决于你想如何处理事件stream。 理想情况下,你需要一个分区键,这意味着你的事件处理是分区本地的 。
例如:
- 如果您关心用户的平均在线时间,那么您应该按照
:user-id
分区。 这样,与单个用户的网站活动相关的所有事件都将在同一个分区中提供。 这意味着像Samzaza这样的stream处理引擎可以通过查看单个分区中的事件来计算给定用户的平均时间。 这避免了必须执行任何昂贵的分区全局处理 - 如果您关心您网站上最受欢迎的网页,则应该按照
:viewed
网页进行分区。 再次,Samza将能够通过查看单个分区中的事件来保持给定页面视图的计数
通常,我们试图避免不得不依赖于全局状态(例如在DynamoDB或Cassandra等远程数据库中保留计数),而是可以使用分区本地状态。 这是因为地方政府是stream处理的基本原则 。
如果你需要两个上面的用例,那么Kafka的一个通用模式是首先通过:user-id
进行分区 ,然后通过:viewed
为下一个处理阶段的:viewed
做好准备。
在主题名称 – 这里显而易见的是events
或user-events
。 更具体地说,您可以使用events-by-user-id
和/或events-by-viewed
。
我认为主题名是一种消息的结论,而生产者通过订阅主题向主题和消费者订阅消息发布消息。
一个话题可能有很多分区。 分区对并行性有好处。 分区也是复制的单位,所以在卡夫卡,领导者和追随者也是在分区层面上说的。 实际上一个分区是一个有序队列,其顺序是消息到达顺序。 而话题由一个或多个队列组成。 这对我们模拟我们的结构非常有用。
Kafka由LinkedIn开发,用于日志聚合和交付。 这个场景是非常好的例子。
您的networking或应用程序中的用户事件可以由您的networking服务器logging,然后通过制作人发送到卡夫卡经纪人。 在生产者中,你可以指定分区方法,例如:事件types(不同的事件被保存在不同的分区中)或事件时间(根据你的应用程序逻辑将一天划分到不同的时间段)或用户types或只是没有逻辑和平衡所有日志分成许多分区。
关于您遇到的问题,您可以创build一个名为“page-view-event”的主题,并通过散列键创buildN个分区,以平均分配所有分区中的日志。 或者你可以select一个分区逻辑来让日志分配你的精神。