一个生产者和多个消费者从证券交易所获取市场数据的架构

The architecture of one producer and several consumers in getting market data from Stock Exchange

我有一个场景,我需要使用一个提供市场数据的生产商(证券交易所)。每个市场数据消息包含 ("symbol"、"price" 和 "timestamp")。

同时,我有3个消费者(服务器),他们每个人都会消费一定"symbol"的市场数据。例如,消费者A只会消费符号为"AAPL"、"AMZN"的行情数据,消费者B会消费符号为"GOOS"的市场数据,以此类推。

一个要求是消费者必须接收他们想要的符号的按时间戳排序的消息。

还有一个要求就是消费者可以不时地改变他们的偏好。比如消费者A可能开始消费符号为"GOOS"的消息。

这个架构应该怎么设计?我知道我可能需要利用 Kafka MQ,但我不是这方面的专家。有人可以详细说明设计如何吗?

您的设计可以包含以下组件

数据采集层:一个将从交换获取数据并嵌入 Kafka 生产者以便能够将数据发送到 Kafka 的组件。

消息层:这将是您的 Kafka 集群(多个代理,假设 3 个以启用复制)。在这个 Kafka 集群上,您需要创建一个具有多个分区的主题(假设 raw-market-data)。例如,如果您总共有 300 个符号,那么您可以选择创建 100 个分区(编号从 0 到 299),每个分区以 3 个符号结尾。

消费层:这是您的消费者运行。您已经提到您将拥有该消费者的 3 个实例。

其他设计注意事项:

分区策略:

  • 数据采集层的Kafka生产者运行ning可以将消息结构化为{7, { "stockSymbol": "AAPL", "marketPrice": 57.10, "timestamp": "May 13th, 10:03:18 AM "} }。消息开头的数字7,即消息的键,指示该消息应该去往哪个分区。您需要在生产者中编写逻辑,将特定股票代码映射到专用分区。

  • 另一种选择是将消息结构化为 {"AAPL", { "stockSymbol": "AAPL", "marketPrice": 57.10, "timestamp": "May 13th, 10:03:18 AM "} }。您明确地将股票代码压入消息的键中,然后 Kafka 的默认分区程序将跳入并计算字符串 AAPL 的哈希值,并对分区数进行模运算。然后,此计算的结果将确定此消息最终所在的分区。此选项有一个警告,即跨分区的符号分布可能并不总是均匀的。想自己研究的可以参考the actual source code of the default partitioner

  • 第三个选项是编写您自己的自定义分区程序。这是一个 reference article with an example.

  • 分区的实际数量将取决于各种其他因素,例如总吞吐量、代理数量、消费者实例数量,即并行单元等。

消费策略:

  • 通常,消费者实例将由 Kafka 自动分配分区 - 默认分配是使用 RangeAssignor 完成的。例如,如果你有 8 个分区(编号从 0 到 7)和 3 个消费者(c1、c2 和 c3),那么 Kafka 将分配分区 {0, 1, 2}c1{3, 4, 5}c2{6, 7}c3。您可以通过直接调用 assign() 方法将特定的分区分配给特定的消费者,或者通过实现 this interface.

  • 来编写您的自定义分配器
  • 关于您要求根据时间戳对消息进行排序。现在,这是 Kafka 无法保证的事情。消息将按照它们到达的顺序被推送到主题,所以如果有 2 条消息的时间戳为 t1t2 带有 t1 < t2 并且由于某种原因消息带有 t2 时间戳先到达然后这将在具有 t1 时间戳的消息之前被消耗。因此,您需要在您的消费者应用程序实例中处理这个问题 - 我过去使用 TreeMap 数据结构,timestamp 作为实现此目的的关键。

  • 关于更改消费偏好的要求 - 最好实现自定义分区分配器(在消费策略的第 1 点中提到),这将使您能够按原样处理此问题非常具体的要求。

我已经提到了与您的问题中所述要求相关的设计注意事项。随着我们的深入,会有更多,但这可能会给你一个起点。

希望对您有所帮助!