欢迎访问信息侠官方网站!

行业新闻

解析CIFS|华泰证券毕成功:低延时交易系统的平台架构设计
2024-04-24
在座的嘉宾大家好,很高兴受到组委会的邀请,让我来参加这次分享,我分享的主题是“低延时交易系统的平台架构设计”。

背景简介

首先说一下这个内容的背景,我们做的系统叫大象系统,我们主要做的是FICC多资产实时定价,还有做市、风险对冲的平台,是一个比较综合类的交易平台,我们服务的对口部门是华泰的固收部门,这两年华泰的固收发展非常猛,基本每年翻很多倍的增长,尤其是量化做市这块,背后增长支撑的系统是我们大象交易系统。我们最近这段时间也拿了不少的奖,最近拿的最有重量级的奖应该是金发奖的一等奖,应该是金融类最高的奖项之一了。我负责大象平台的平台架构团队,我今天分享一方面希望大家理解一下我们在做交易系统背后的而且思考,另外一方面了解一下作为一种交易系统设计的方式。

低延时的价值

正式内容之前我解释一个问题,为什么要低延时?我讲一个比较简单的例子,当资产价格标的产生波动的时候,要赶快的做撤单,重新报单,如果不能及时做到,就会被别人吃单,很容易做套利交易。这个很像一种军备竞赛,低延时要多低,只是说相对比别人更快就行了。从早期大概的竞争,差不多是毫秒级的,我们现在竞争已经到了微秒级,大家稍微注意一下量级微秒,我们后面很多设计的东西就是在抠到微秒级的性能。

设计概述

从宏观的视角上先看我们怎么做的,拿一个对照来看,这是一次单次的请求,可以看到我们中间系统都喜欢做成无状态服务,实际上严格意义上不是无状态,进程是无状态的,把状态放到了外层,就造成了依赖于外层,或者DB。我们做这个专业系统有点反其道而行之,我们做的是有状态服务,有状态的交易速度和性能是非常好的。另外一个比较大的特点,我们这个地方用到了一个总线,我今天的内容把这两个基础特征展开说说。

为什么还用总线架构?

微服务 VS 总线

第一,为什么还在用总线?很多人觉得总线是被微服务淘汰的架构,我刚从互联网到券商看到这套架构的时候也有类似的疑问,我们先理性分析一下为什么这么做。先看看微服务有什么特色,微服务是点对点的IBD通讯,横向扩展非常容易,它是同步的请求,它的设计模式很符合它的业务场景。但总线是天然ESB的通讯模式,上游只管发,异步也支持同步。

交易系统属于通道服务,整个过程是异步的。我们交易过程涉及到交易、风控、对冲等等很多环节,其实它并不是一个简单的请求,是一个复杂事务。我们做FICC,很多是场外衍生品,场内就是标准化合约,场外这个东西玩的非常花,各种玩法都有,但它也不是说完全没有可复用的东西,很多时候在某些地方上是有差异性的。就很容易出现我们的场景当中上下游很多环节的排列组合,所以我们需要很高的流动性。

最后一点,微服务我们经常在说的,像电商类的系统,这些东西对吞吐量要求很高,我们在秒杀或者双十一的场景中,只要让交易系统不超时问题就不大。但在我们的券商类系统来说就是要快,实际上它对吞吐量的要求并没有那么高,一方面市场的资金总量是有限的,第二标的总量也是有限的,所以场景没有那么复杂,不是吞吐量的要求。

综合以上来看,并不是微服务架构一定比总线架构更优,只是说总线架构更适合我们。但我们也不得不面临一个现实的问题,很多微服务的框架生态非常成熟,总线一下子想不到有什么东西,所以我们选择总线框架有一个挑战,总线相关的服务和治理得自己做出来。而且这个地方还有个很客观的问题,在微服务上上下游算是强依赖的,本身又有框架支持,所以管理不会很混乱。内部系统一般比较乱的是总线,总线跟这个情况是一模一样的。我们又把这个东西自己核心交易主要的分发模式,它的管理就被提高到非常高的边际,所以我们需要把总线的管理做的更好。特别是总线,因为是异步框架,上游不管下游,上游发生了更新,下游不知道,怎么办?在交易的整个架构生产线,需要我们把管理收得更紧来做这个补足。

总线的使用与管理

所以遇到几个很具体要做的事情,1,总线的格式要有管控。2,总线上的Topic,权限、路由都要做同步管控。还有一个比较现实的问题,就是总线能不能解决所有同性问题?这是终极的问题,我们本来希望内部不要异构了,就只有总线。阿里这么大的数据量都从总线上过,总线的压力也很大,我们认为在适合的场景下不一定都用总线,应该是混合的模式。我们又希望在开发过程中不要产生太复杂的,就是异构造成的复杂性,所以我们在框架上又把这个给屏蔽了。

总线的扩展性

总线有点像中央节点,这也是当时为什么总线被互联网淘汰的重要原因,我们依然也有同样的问题,比较容易想到的总线做横向扩展、纵向扩展,但也有上限的,互联网也解决不了这样的问题。我们如何解决这个问题?按业务分割,最好的思路肯定就是说完全分割,两个完全不相干的业务,各有各的集群,我们管它叫域。这是理想的结构,有点像玩游戏的时候每个游戏自己一套分区,实际开发过程中发现很难做到这么干净的分离,我们采用的方式叫多接。但这种连接要做强管控,因为一旦多了,就很难做管控,这个也有点像传统做架构设计中的六边形理论,我们中间其实并没有做其他桥接的东西,直接连上去了,这个为了最高的性能考虑。我们又得在框架上把这个逻辑屏蔽,让他用到总线上的东西自动连上去。还有一种把桥接点拉进来,还有一种场景有点像数据中台,我们一般把它放在旁路上,拿桥接器把一个数据从一个总线放到另外一个总线上,让它自己玩。

总线优化

说到总线还有个不能回避的问题,总线毕竟是个中间链,多一个中间链多一跳,信号更差,这个怎么优化?业内用的是可靠UDP组合,把五层协议直接降成四层协议,四层协议率肯定要高得多,而且这个是底层优化,优化是有全局性的。这个东西大家很多不去用,因为它有它的问题。既然是四层协议,所以路由管控的能力很弱,基本来说把数据发过去,本地不要的数据过滤掉,所以是有一定的运行成本。第二,它依赖组网环境,必须在同一个区域网内做,跨区域不行。最后它有很高的硬件资源占用。

总线优化在功能上没有本质区别,但在结构上变得非常复杂,以上是我们在总线使用上的考虑。

怎么敢搞内存计算?

第二个重点,内存计算?内存计算是我们先把上游的数据订阅到本地,后面所有的数据处理直接查本地内存,这肯定是非常非常快的。但是还有个很重要的特点,很稳定,如果我们传统微服务当中依赖数据库,至少有两个依赖,一个是网络,网络有波动不行,二是依赖数据库的稳定性,这些都是我们不希望看到的,我们希望这些东西在一个进程,只要进程不挂,这个东西就是可运行的。

状态数据的高可用

业内为什么大家不用内存计算呢?肯定还是因为它横向扩展更容易,可以做到动态扩容,这是互联网业务中的特色,其实我们用不到。我们用内存计算面临新的挑战,我们把内存加载到进程里面来,进程挂了以后内存不就没了吗?怎么恢复回来?我们涉及到内存状态的高可用。我们做的思路非常简单,在旁路又加了一层,把服务的内存状态又记了一份,当你挂了以后,再从旁路记的数据恢复回来,恢复到原来的状态,中间也有问题,你的订阅和旁路服务还没有落到数据库里面,没办法给你实时查。

有状态服务的高可用

这是一个进程挂了怎么办,我们还会想到另外一个问题,有状态服务高可用怎么办?能不能多服使用,一个挂了,不受影响。我们和业内的共识多活很难,我们还是做储备,我们是个交易系统,整个市场的容量,高性能的单机是能撑得住的,其实不太需要多服,主备就用了,主备也有挑战点。

第一个思路,主备两台机器一起消费这个数据,让行为绑成一致的,这样一个挂了,另外一个接过去。备机是只借逻辑处理,不往外发消息,当它挂了,它往外发消息。为什么同步很难?就是我们中间会用到多线程,不确定,两边一起做,行为可能不一致。必须用多线程,如何解决不一致的情况,那就只能创新。一方面会造成性能下降,第二方面你的开发也有侵入,而且这个模式也有个其他的问题,主从两个机器并不做协调,性能很好,但你怎么保证他们内存状态真的是一致的,有问题也比较难发现。还有一种业内的思路,叫做状态同步,把主消费完状态的变更同步给备机,这个思路就是主机多干了一件事,我们本来希望最高性能去跑。我们用这种思路,主要的实现方式在于,它实际同步的动作是异步的,并不是在主的业务逻辑线程里面去。用异步做,虽然可以避免这个东西的影响,但又涉及到临界状态的问题。所以通常来说,这个东西宁可多,不可少,又涉及去重等一系列的问题。所以说这个实现的逻辑也比较复杂,而且主备两套逻辑完全是不一样的,所以开发起来更麻烦,框架实现起来更麻烦。

基于业务自动机的弱事务

还有一个不得不说的问题,我们已经把数据库给剔了,数据库有个特别重要的能力,就是事务,我们就没有事务,需要支持事务的事情怎么办呢?交易系统是个横纵的过程,事务性能非常之差,依赖于数据库,数据库又依赖于磁盘,所以基本是接受不了的,在低延时的场景下玩不转。我们的做法就是把它做成一个自动机,自动机过程中涉及到很多出了异常以后怎么去做的细节控制,整个设计思路可以理解为最终一致性,但绝对不能依靠数据库。

其他的优化角度?

还有没有其他需要考虑的东西?我们已经优化到微秒级,微秒级的东西有很多事情又要纳入到考虑的范畴。我们在网络链路上要做相应的优化,最典型的跨机房,我们希望跨机房的链路是最短的,不要出现机房来回跳的情况,所以部署上是非常小心的。比如说做量化交易的东西,我们把策略指令的下发,一旦发过来以后,中间的运行直接在交易所机房做的,避免跨机房的问题,我们就近接入。

我们还有个很重要的思想是就近调用,做微服务开发当中肯定要分模块设计,我们做交易系统也依然希望模块化,开发起来结构更清晰。但要每个模块独立部署,就一定是跨阶层用的,所以是有问题的。模块的设计,实际在部署的时候打包到一个进程内完成,所以我们是能打包在一个里面就打包在一个里面,比如一个订单服务和风控服务就会撮合在一个进程内,但你会想到会不会很重,影响到性能上限,那就回到跟总线扩展是一个思路,按不同的标的、不同的交易品种,拆成多个垂直的线。

我们很难把所有的东西打包到一个进程内,怎么办?退而求其次,同步到一个物理机上调用,我们也是共享内存的模式,也是防止跨界调用性能的问题。

总结

总结一下,我们在做这个系统设计当中,我们最终看到的架构已经和刚开始微服务的架构差别很大,为什么产生这个差别?是因为我们在原则指导上有不同,我们更多为了低延时,还有为了交易系统复杂的场景能做灵活的解耦,有这方面作为我们更优先的指导研究,把可高用等放为第二目标,最后设计出来这样的结构。第二,我们原来在微服务上怎么画模块,怎么部署,一一对等。我们这边为了优化,结构上是分模块,部署上是打包的。最后一点,有状态的服务启动肯定是很慢的,经常到分钟级才能启动起来,为什么做这样的设计?我们希望交易系统的稳定性是高的,对外部依赖是少的,但是它的异常只要在最大的范围内可控的我们就认为是好的,我们希望在正常的交易过程中,刚才说的低延时是一种军备竞赛,我们希望在正常的执行过程中是最优的,军备竞赛中能战胜的。但在异常的时候,它真的出现异常我们得人工排查异常的原因和影响才能拉活,所以异常的恢复只要是可控的,并不需要那么高效,所以整个设计变成这样的结构。

以上是我的分享,希望大家在分享当中获得交易系统开发的启发。谢谢大家!  


扫一扫微信二维码

随时了解信息侠微报资讯


扫一扫手机端二维码

随时了解信息侠微报资讯

Copyright @ 2018-2019 信息侠一站式数字化转型交流分享平台  版权所有 皖ICP备19006839号-1

上海申馥文化传媒有限公司

安徽申馥商务咨询有限公司

安徽申馥企业服务有限公司

地址:安徽合肥望江西路西湖国际广场D座2345室   网址:www.xinxixia.cn

电话:021-34121111     0551-64388008


友情链接: 安徽省经济和信息化厅 |  江苏省经济和信息化厅  |  浙江省经济和信息化厅  |  上海市经济和信息化委员会  |  四川省经济和信息化厅 |  中华人民共和国工业和信息化部 |  小牛网络 |