支付系统由于本身和金融相关,不像其他高频系统面对海量请求可以大量使用缓存,异步mq等方式解决三高问题。支付系统对数据一致性要求更高,所以对于其架构设计原则还是有自己特点的。
构建一个支撑每秒十万只读系统并不复杂,无非是通过一致性哈希扩展缓存节点,水平扩展web服务器等。每秒钟数十万数据更新操作,在任何数据库上都是不可能的任务,首先需要对订单表进行分库分表。
在进行数据库操作时,一般会用ID(UID)字段,所以选择以UID进行分库分表。
分库策略我们选择了“二叉树分库”,所谓“二叉树分库”指:在进行数据库扩容时,以2倍数进行扩容。比如:1台扩容2台,2台扩容4台,以此类推。最后把Order库分了8个库中,每个库10个表。
根据uid计算数据库编号:
分库信息 = (uid / 10) % 8 + 1
根据uid计算表编号:
表编号 = uid %10
订单系统的ID必须具有全局唯一的特征,简单的方式是利用数据库的序列,每操作一次就能获得一个全局唯一的自增ID,如果支持每秒10w订单,那每秒至少需要生成10w订单ID,通过数据库自增ID显然无法完成上述请求。所以通过内存计算获取全局唯一的订单ID。
JAVA领域著名的唯一ID应该是UUID了,不过UUID太长且包含字母,不适合做订单ID。
通过反复比较筛选,借鉴Twitter的算法实现全局唯一ID。
三部分组成:
最终订单结构:
分库分表信息 + 时间戳 + 机器号 + 自增序号
还是按照第一部分根据uid计算数据库编号和表编号的算法,当uid=9527时,分库信息=1,分表信息=7,将他们进行组合,两位的分库分表信息即为”17”。
我们通过对order表uid维度的分库分表,实现了order表的超高并发写入与更新,通过uid和订单ID查询订单信息。
上面方案虽然简单,但是保持两个order表机器的数据一致是很麻烦的事情。
两个表集群显然是在不同的数据库集群中,如果写入与更新中引入强一致性的分布式事务,这无疑会大大降低系统效率,增长服务响应时间,这是我们所不能接受的,所以引入了消息队列进行异步数据同步,为了实现数据的最终一致性。
当然消息队列的各种异常会造成数据不一致,所以我们又引入了实时服务监控,实时计算两个集群的数据差异,并进行一致性同步。
所谓数据库高可用指的是:
当数据库由于各种原因出现问题时,能实时或快速的恢复数据库并修补数据。
从整体集群角度看,就像没有出任何问题一样,需要注意的是,这里的恢复数据库服务并不一定是指修复原有数据库,也包括将服务切换到另外备用的数据库。
数据库高可用的主要工作是数据恢复月数据修补,一般我们完成这两项工作的时间长短,作为衡量高可用好坏的标准。
我们认为,数据库运维应该和项目组分开,当数据库出现问题时,应由DBA实现统一恢复,不需要项目组操作服务,这样便于做到自动化,缩短服务恢复时间。
如上图所示,web服务器将不再直接连接从库DB2和DB3,而是连接LVS负载均衡,由LVS连接从库。
这样做的好处是LVS能自动感知从库是否可用,从库DB2宕机后,LVS将不会把读数据请求再发向DB2。
同时DBA需要增减从库节点时,只需独立操作LVS即可,不再需要项目组更新配置文件,重启服务器来配合。
再来看主库高可用结构图:
如上图所示,web服务器将不再直接连接主库DB1,而是连接KeepAlive虚拟出的一个虚拟ip,再将此虚拟ip映射到主库DB1上,同时添加DB_bak从库,实时同步DB1中的数据。
正常情况下web还是在DB1中读写数据,当DB1宕机后,脚本会自动将DB_bak设置成主库,并将虚拟ip映射到DB_bak上,web服务将使用 健康 的DB_bak作为主库进行读写访问。
这样只需几秒的时间,就能完成主数据库服务恢复。
组合上面的结构,得到主从高可用结构图:
数据库高可用还包含数据修补,由于我们在操作核心数据时,都是先记录日志再执行更新,加上实现了近乎实时的快速恢复数据库服务,所以修补的数据量都不大,一个简单的恢复脚本就能快速完成数据修复。
支付系统除了最核心的支付订单表与支付流水表外,还有一些配置信息表和一些用户相关信息表。如果所有的读操作都在数据库上完成,系统性能将大打折扣,所以我们引入了数据分级机制。
我们简单的将支付系统的数据划分成了3级:
使用本地内存缓存有一个数据同步问题,因为配置信息缓存在内存中,而本地内存无法感知到配置信息在数据库的修改,这样会造成数据库中数据和本地内存中数据不一致的问题。
为了解决此问题,我们开发了一个高可用的消息推送平台,当配置信息被修改时,我们可以使用推送平台,给支付系统所有的服务器推送配置文件更新消息,服务器收到消息会自动更新配置信息,并给出成功反馈。
举个简单的例子,我们目前订单的处理能力是平均10万下单每秒,峰值14万下单每秒,如果同一秒钟有100万个下单请求进入支付系统,毫无疑问我们的整个支付系统就会崩溃,后续源源不断的请求会让我们的服务集群根本启动不起来,唯一的办法只能是切断所有流量,重启整个集群,再慢慢导入流量。
我们在对外的web服务器上加一层“粗细管道”,就能很好的解决上面的问题。
请看上面的结构图,http请求在进入web集群前,会先经过一层粗细管道。入口端是粗口,我们设置最大能支持100万请求每秒,多余的请求会被直接抛弃掉。出口端是细口,我们设置给web集群10万请求每秒。
剩余的90万请求会在粗细管道中排队,等待web集群处理完老的请求后,才会有新的请求从管道中出来,给web集群处理。
这样web集群处理的请求数每秒永远不会超过10万,在这个负载下,集群中的各个服务都会高校运转,整个集群也不会因为暴增的请求而停止服务。
如何实现粗细管道?nginx商业版中已经有了支持,相关资料请搜索
nginx max_conns,需要注意的是max_conns是活跃连接数,具体设置除了需要确定最大TPS外,还需确定平均响应时间。
1、高频交易系统概述
高频交易是指从那些人们无法利用的极为短暂的市场变化中寻求获利的计算机化交易。
比如,某种证券买入价和卖出价差价的微小变化,或者某只股票在不同交易所之间的微小价差。
这种交易的速度如此之快,以至于有些交易机构将自己的“服务器群组”(server farms) 安置到了离交易所的计算机很近的地方,以缩短交易指令到达交易所的距离。
2、高频交易系统特点
(1)交易指令完全由电脑发送,对市场数据的响应延时在微秒级,有的甚至是纳秒级;
(2)系统由专用的软、硬件组成;
(3)系统的硬件需要放在离交易所主机很近的位置上,所谓 co-location。
3、高频交易的两大核心要素
(1)一是产生高频交易信号的交易策略
(2)二是优化交易执行过程的算法。
扩展资料
1、高频交易系统的特点
高频系统是一种非常有特点的计算机应用。在输入和输出层面,数据比较简单。
输入用的都是市场行情数据,用的是Tick级别,甚至是更细颗粒度,比如用order book上数据。
输出就是报单到交易所,执行层面上频率会比较高,有可能会大量、频繁地向交易所报单。系统运行时处理的信号源是交易所播报的实时行情,要求用最快的速度对信号进行拆解、计算和输出,对于系统的实时计算能力的要求也比较高。
同时,一般高频交易系统从逻辑的层面上来说是比较简单的。
2、编程语言的选择
目前,高频交易系统最主流的是C/C++语言。
这是一种优点及其很显著的语言。相比依赖虚拟机的JAVA和Python而言,C/C++是一种非常接近底层硬件的开发语言,对硬件操控的控制度、灵活度都超过其他语言,在性能上的把控力会更强。
但是,其语法相当复杂,比较难学,没有受过系统编程训练的开发者,掌握起来比较困难。
同时,使用C/C++编程也可以获得及其优越的性能,这对于高频交易系统来说,就非常重要了!并且,国内大多数的交易所提供的都是C++级别的类库,只有用C++进行开发,才能方便进行系统对接。
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)