从联交所获取市场数据的一个生产者和几个消费者的体系结构

时间:2019-05-12 21:10:09

标签: architecture apache-kafka message-queue

我有一种情况,我需要使用一个提供市场数据的生产者(证券交易所)。每个市场数据消息都包含(“符号”,“价格”和“时间戳”)。

与此同时,我有3个使用者(服务器),每个使用者(服务器)都会使用某些“符号”来消费市场数据。例如,消费者a将只使用符号为“ AAPL”,“ AMZN”的市场数据,消费者B将使用符号为“ GOOS”的消费者,等等。

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

还有另一个要求,即消费者可能会不时更改其偏好。就像消费者A可能开始消费带有符号“ GOOS”的消息。

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

1 个答案:

答案 0 :(得分:2)

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

数据获取层:将从交易所获取数据并嵌入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,即消息的关键字,指示此消息应转到的分区。您需要在生产者中编写将特定股票代码映射到专用分区的逻辑。

  • 另一种选择是将消息构造为{"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来编写自定义分配器。

  • 根据您的要求根据时间戳顺序订购消息。现在,这是卡夫卡无法保证的。消息将按照到达的顺序推送到主题,因此如果有两个时间戳为t1t2且消息为t1 < t2的消息,并且由于某种原因,消息有{{1} }时间戳首先到达,然后在具有t2时间戳的消息之前被消耗。因此,您需要在用户应用程序实例中处理此问题-过去,我使用t1的{​​{1}}数据结构作为实现此目的的关键。

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

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

我希望这会有所帮助!