某次公募基金交易系统架构设计
Posted 蛇精病用友高级开发组
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了某次公募基金交易系统架构设计相关的知识,希望对你有一定的参考价值。
年份:2020年
记录下针对那个年代的技术栈进行选型架构设计,开发周期6个月,开发过程中的一些场景和探索。
经过真实场景的交易测试后,因为公司砍掉该业务方向的探索而终止废弃。
大体架构图如下:
附上业务大体流转图:
因为是一个新项目,从0开始,所以整体上微服务架构解耦没太多的纠结,而且从一开始可以保证服务之间的rpc调用统一,以及技术栈上的统一。
团队人员:4个Java,2个vue,1个安卓,2个ios,1个ui设计师,3个产品,5个测试。
前端:采用vue,接口定义靠后端的swaggerui,减少不必要的沟通和编写接口文档成本(虽然现在都已经很流行了,但是依然会有很多公司存在令人无力吐槽的接口文档编写任务)
后端:
大体如下:
springboot2.0.6+springcloud Finchley.SR2+spring jpa
mysql7,redis4, es6,jenkins (公司之前的环境)
系统在最初解藕时考虑 将后端服务根据各自的用途 归类为两类:
系统性质的web服务 和 服务性的后端服务。前者可以理解成前台,后者是中台,比如交易服务就是中台服务,而针对个人(c端)与机构(b端)分别开发的系统被定位为前台服务,他们都需要依赖交易服务的接口,此时只有交易服务需要对外提供feign接口,而c端,b端则只需要对外提供restful api即可。
关于基金信息是公司从聚源公司采购的,每天同步一次基金数据到基金信息mysql数据库,以及es。app,h5上所看到的k线图历史行情都是直接从es拿到的,当然为了页面内容丰富点,也会向东方财富这些公开的url里获取一些排行榜。
由于基金交易规则并不像股票交易那样实时撮合交易,所以系统在开发时可以减少一些实时性挑战,重点集中在交易不能丢失和回传交易结果上。
当有一笔交易进来,直接落库到交易表,并且推送出交易事件到rocketmq to pic,如果落库这个环节出错,后续所有操作都是没意义的,(这里假设my sql能承受我们的业务量)。 交易事件会被订阅处理后发送到专门为恒生系统封装的第三方服务,恒生会与基金公司的ta系统进行撮合。在调用恒生接口时,每一次均会返回一个流水号,后续就要根据这个流水号从恒生同步交易结果,之所以不在调用接口时根据回参判断交易结果,是因为这个交易撮合存在很长的时间间隔,一方面要从银行签约扣款并实时反馈给app,另一方面需要割上1天或者更多时间才能获取基金公司对这笔交易的确认,所以系统在开发的时候需要考虑开发补偿订单的业务,这里采用roketmq的延时消息队列来驱动,并提供相关定时任务进行兜底。
关于定时任务,采用了xxl-job分布式调度,为了保证HA,上面的系统都做了无状态多活部署,所以不能简单的通过cron来定时执行任务,这个框架有点坑的是早期版本有时候会不明原因没有触发任务。
关于对elasticsearch的利用除了存储基金行情信息外,有时候也会存储一些费用计算时产生的记录,这里需要注意的是es的写是有一定的延时,当写入新数据后,最快1s后才能没检索到,这个1s是默认设置,可以人工调节,但是不建议更改,所以es并不能拿来当mysql进行增删改查,不然会出现幻读问题。
在分布式事务上,这次系统主要关注最终结果一致性,并且由于跨了不同公司,所以没有办法采用saga这些框架,纯靠延时消息和兜底服务来保证。
在分布式锁上,采用redlock来实现。
涉及到性能和效率问题主要是日终持仓更新和佣金,保有量计算时因为要频繁调用恒生接口需要做异步多线程处理,以及大数据量的情况下通过消息topic订阅驱动并行计算。
关于鉴权,这次项目直接用jwt,token放redis的方式。
因为系统性质需要对用户身份证进行图片识别,采用百度的API。
在系统开发之初,作为主程还要干几件事:
封装一pom parent来统一各个模块的maven文件版本,避免出现版本混乱问题。
编写一个spring boot starter,定义全局异常 ,错误代码枚举,自定义注解,拦截器等,编写统一报文基类。
编写鉴权网关web服务,这里是对springCloud gateway进行了扩展配置,用于token校验,url拦截等处理
提供spring jpa的generator工具包
规划并配置好spring cloud config各个环境的yml
约定建表规范,包名规范以及其他规范
配置cicd ,部署机器
可做可不做的系统架构图分享,数据流转分享,凭个人素养。
以上是关于某次公募基金交易系统架构设计的主要内容,如果未能解决你的问题,请参考以下文章