梁鑫:美股交易架构实践
图片来源:pexels.com
作者:梁鑫(资深架构师,多年云原生,微服务架构经验,开源 SIA 系列产品 owner)
1
引子
上次文章《重构 - 在美股行情系统的实践》分享自己今年在重构美股行情系统的一些心得。接下来要面临的就是处理股票交易,股票交易一般都是通过证券交易所来完成,业务系统只需要将客户的买卖动作在正确的触发机制下,以最快的速度传递给证券交易所。
股票交易就是股票的买卖。股票交易主要有两种形式:
一种是通过证券交易所买卖股票,称为场内交易;
另一种是不通过证券交易所买卖股票,称为场外交易。
我们处理的都是场内交易。
2
交易系统需要解决的问题
2.1
如何接收不断变化的行情数据
在我们重构美股行情系统之后,股票行情系统已经能够满足客户的需求,跟竞品相比,从时效性上已经几乎没有任何的差距。等接下来采用 MQTT 服务往 APP 端推消息以后,将彻底弥补这个差距。
读过我上篇文章的朋友知道,我们应对海量实时交易的行情信息,使用的 kafka 消息服务器。如何让交易信息获取行情信息呢?最好的办法是交易系统也从 kafka 订阅,才能拿到最及时的信息,但这样直接吧行情系统使用的 kafka 暴露给交易系统。这样会导致不同的功能模组之间的耦合过度紧密,我们更希望系统之间能层次分明,分类清晰。最好不要给将来的运维工作造成太多的难度和工作量。
因此,最合适的方式肯定是封装一个 client 包把具体实现影藏起来,这个 client 由行情系统提供,以后凡是交易模式之间需要最实时的行情信息,都可以通过引入这个 client 来实现。而获取方只需要实现接口的方式即可。
2.2
交易订单流程设计
股票交易订单有很多种类。有限价单,市价单,止损限价单,止损市价单,触及限价单,触及市价单等等。又分着买入和卖出两种交易类型。我们的交易订单处理的简单流程图如下:
当提交股票订单在股票交易时间内,首先进行成交处理(调用证券交易公司的成交接口),如果成功,流程结束。如果不成功,则进入待成交订单数据中。待成交订单的数据会根据不断变化的行情信息进行判断,如果满足成交条件,立即调用成交处理。
2.3
待成交订单池
大量的待成交订单信息保存到哪里? 最好的方式肯定是 redis。redis 性能极高,并且支持丰富的数据类型,并且 redis 所有的操作都原子的。直接规避了我们大量的事务问题。我们把待成交订单的数据结构分成几部分。
首先,每只股票都有一个买入订单的 set 和卖出订单的 set。这两个 set 存储的都是排序好的交易订单的价格。买入订单从高到底排列,卖出订单订单从低到高排列。
其次,我们用两个 map 来保存买入卖出的订单信息,map 的 key 是价格,value 是一个 List,用来保存该价格的所有订单信息。
2.4
待成交订单的触发机制
针对大量的待成交订单处理,需要特别考虑几个问题。
根据海量的行情吞吐信息进行是否可以进行成交处理判断,考虑系统可以承受的性能压力和水平扩展模式。
集群模式下待成交订单的多进程处理。
采用 Redis 保存待成交订单后的,条件判断性能问题。
其实这三个问题很好解决,特别是当你的用户数据还不算多的时候。
系统一定要支持集群,可以水平扩展。当系统压力较大时就可以通过增加节点来解决。
利用 redis 的原子操作和数据库,基本可以解决多进程问题。
最后使用 redis 数据中 range 操作。并把每只股票卖出的最低价格和买入的最高价格单独保存和更新,大量的行情信息其实根本不会触发待成交订单的成交操作。
自然大大提高了系统的性能。
2.5
美股交易系统架构图
3
总结
接连完成了美股行情系统的重构交易系统建设,下一步需要着手处理 MQTT 的工作了。(未完待续)
往期推荐