我有一个场景,我需要使用一个生产者(证券交易所)提供市场数据。每个市场数据消息都包含(“符号”、“价格”和“时间戳”)。
同时,我有3个消费者(服务器),每个消费者(服务器)将使用带有特定“符号”的市场数据。例如,消费者a将只消费具有符号“aapl”、“amzn”的市场数据,消费者b将消费具有符号“goos”等的消费者。
一个要求是消费者必须接收他们想要的符号的按时间戳排序的消息。
还有一个要求是,消费者可能会不时改变他们的偏好。与消费者一样,消费者可能会开始消费带有“goos”符号的消息。
我应该如何设计这个架构?我知道我可能需要利用Kafkamq,但我不是这方面的Maven。有人能详细说明一下设计方案吗?
1条答案
按热度按时间tv6aics11#
您的设计可以包含以下组件:
数据采集层:一个将从交换中获取数据的组件,它将嵌入一个Kafka生产者,以便能够向Kafka发送数据。
消息层:这将是您的kafka集群(多个代理,比方说3个代理以启用复制)。在这个kafka集群上,您需要创建一个主题(比如
raw-market-data
)有多个分区。例如,如果您总共有300个符号,那么您可以选择创建100个分区(编号从0到299),每个分区以3个符号结束。消费层:这是你的消费者将运行的地方。您已经提到,您将有3个此消费者的示例。
其他设计考虑:
分区策略:
运行在数据采集层的kafka生产者可以将消息构造为
{7, { "stockSymbol": "AAPL", "marketPrice": 57.10, "timestamp": "May 13th, 10:03:18 AM "} }
. 数字7
在消息的开头,即消息的键,指示该消息应转到哪个分区。您需要在producer中编写逻辑,将特定的股票符号Map到专用分区。另一种选择是将消息构造为
{"AAPL", { "stockSymbol": "AAPL", "marketPrice": 57.10, "timestamp": "May 13th, 10:03:18 AM "} }
. 显式地将stock符号压入消息的键中,然后kafka的默认分区器将跳入并计算字符串的哈希值AAPL
对分区数进行模运算。然后,此计算的结果将确定此消息将在其中结束的分区。此选项有一个警告,即跨分区的符号分布可能并不总是一致的。如果您想自己研究的话,这里有一个对默认分区器的实际源代码的参考。第三种选择是编写自己的自定义分区器。下面是一篇带有示例的参考文章。
分区的实际数量将取决于各种其他因素,如总吞吐量、代理数、使用者示例数(即并行单元)等。
消费策略:
通常,使用者示例将由kafka自动分配分区-默认分配是使用
RangeAssignor
. 例如,如果您有8个分区(编号从0到7)和3个使用者(c1、c2和c3),那么kafka将分配分区{0, 1, 2}
至c1
,{3, 4, 5}
至c2
以及{6, 7}
至c3
. 您可以通过直接调用assign()
方法或通过实现此接口编写自定义赋值器。根据时间戳对消息进行排序的要求。现在,这是Kafka无法保证的。消息将按到达的顺序推送到主题,因此如果有2条带有时间戳的消息
t1
以及t2
与t1 < t2
因为某种原因t2
时间戳首先到达,然后在消息t1
时间戳。因此,您需要在您的消费者应用程序示例中处理这个问题—我已经使用了TreeMap
过去的数据结构timestamp
作为实现这一目标的关键。关于更改消费首选项的要求-最好实现自定义分区赋值器(在消费策略的第1点中提到),这将使您能够处理这个问题,因为这是一个非常具体的要求。
我提到了与您问题中所述要求相关的设计考虑。随着我们的深入,会有更多的信息,但这可能会给你一个起点。
我希望这有帮助!