您当前的位置:首页 > 电脑百科 > 程序开发 > 架构

高频交易支付架构并不复杂

时间:2019-11-29 12:03:54  来源:  作者:

写在前面

支付系统是整个交易系统中相当核心的一部分功能,以我们的交易中台为例,通过领域方式的拆分,支付架构隶属于订单团队,在整个用户下单之后进行支付,支付之后成单进入交易履约流程。

支付系统由于本身和金融相关,不像其他高频系统面对海量请求可以大量使用缓存,异步mq等方式解决三高问题。支付系统对数据一致性要求更高,所以对于其架构设计原则还是有自己特点的。

分库分表

构建一个支撑每秒十万只读系统并不复杂,无非是通过一致性哈希扩展缓存节点,水平扩展web服务器等。每秒钟数十万数据更新操作,在任何数据库上都是不可能的任务,首先需要对订单表进行分库分表。

在进行数据库操作时,一般会用ID(UID)字段,所以选择以UID进行分库分表。

分库策略我们选择了“二叉树分库”,所谓“二叉树分库”指:在进行数据库扩容时,以2倍数进行扩容。比如:1台扩容2台,2台扩容4台,以此类推。最后把Order库分了8个库中,每个库10个表。

根据uid计算数据库编号:

分库信息 = (uid / 10) % 8 + 1

根据uid计算表编号:

表编号 = uid %10

订单ID

订单系统的ID必须具有全局唯一的特征,简单的方式是利用数据库的序列,每操作一次就能获得一个全局唯一的自增ID,如果支持每秒10w订单,那每秒至少需要生成10w订单ID,通过数据库自增ID显然无法完成上述请求。所以通过内存计算获取全局唯一的订单ID。

JAVA领域著名的唯一ID应该是UUID了,不过UUID太长且包含字母,不适合做订单ID。

通过反复比较筛选,借鉴Twitter的算法实现全局唯一ID。

三部分组成:

  • 时间戳
  • 时间戳的粒度是毫秒级,生成订单ID时,使用System.currentTimerMillis()作为时间戳。
  • 机器号
  • 每个订单服务器都被分配一个唯一的编号,生成订单ID时,直接使用该唯一编号作为机器即可。
  • 自增序号
  • 当同一服务器的同一号码中有多个生成订单ID的请求时,会在当前毫秒下自增此序号,下一个毫秒此序号继续同0开始。如同一服务器同一毫秒生成3个订单ID请求,这3个订单ID的自增序号分别是0,1,2。

最终订单结构:

分库分表信息 + 时间戳 + 机器号 + 自增序号

还是按照第一部分根据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级:

  • 第1级:订单数据和支付流水数据;这两块数据对实时性和精确性要求很高,所以不添加任何缓存,读写操作将直接操作数据库。
  • 第2级:用户相关数据;这些数据和用户相关,具有读多写少的特征,所以我们使用redis进行缓存。
  • 第3级:支付配置信息;这些数据和用户无关,具有数据量小,频繁读,几乎不修改的特征,所以我们使用本地内存进行缓存。

使用本地内存缓存有一个数据同步问题,因为配置信息缓存在内存中,而本地内存无法感知到配置信息在数据库的修改,这样会造成数据库中数据和本地内存中数据不一致的问题。

为了解决此问题,我们开发了一个高可用的消息推送平台,当配置信息被修改时,我们可以使用推送平台,给支付系统所有的服务器推送配置文件更新消息,服务器收到消息会自动更新配置信息,并给出成功反馈。

粗细管道

举个简单的例子,我们目前订单的处理能力是平均10万下单每秒,峰值14万下单每秒,如果同一秒钟有100万个下单请求进入支付系统,毫无疑问我们的整个支付系统就会崩溃,后续源源不断的请求会让我们的服务集群根本启动不起来,唯一的办法只能是切断所有流量,重启整个集群,再慢慢导入流量。

我们在对外的web服务器上加一层“粗细管道”,就能很好的解决上面的问题。

高频交易支付架构并不复杂

 

请看上面的结构图,http请求在进入web集群前,会先经过一层粗细管道。入口端是粗口,我们设置最大能支持100万请求每秒,多余的请求会被直接抛弃掉。出口端是细口,我们设置给web集群10万请求每秒。

剩余的90万请求会在粗细管道中排队,等待web集群处理完老的请求后,才会有新的请求从管道中出来,给web集群处理。

这样web集群处理的请求数每秒永远不会超过10万,在这个负载下,集群中的各个服务都会高校运转,整个集群也不会因为暴增的请求而停止服务。

如何实现粗细管道?Nginx商业版中已经有了支持,相关资料请搜索

nginx max_conns,需要注意的是max_conns是活跃连接数,具体设置除了需要确定最大TPS外,还需确定平均响应时间。

end:如果你觉得本文对你有帮助的话,记得关注点赞转发,你的支持就是我更新动力。

如果您有不同的看法,欢迎在评论区留言与我们一起讨论



Tags:支付架构   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
写在前面支付系统是整个交易系统中相当核心的一部分功能,以我们的交易中台为例,通过领域方式的拆分,支付架构隶属于订单团队,在整个用户下单之后进行支付,支付之后成单进入交易履...【详细内容】
2019-11-29  Tags: 支付架构  点击:(86)  评论:(0)  加入收藏
电商支付架构设计...【详细内容】
2019-08-20  Tags: 支付架构  点击:(193)  评论:(0)  加入收藏
▌简易百科推荐
为了构建高并发、高可用的系统架构,压测、容量预估必不可少,在发现系统瓶颈后,需要有针对性地扩容、优化。结合楼主的经验和知识,本文做一个简单的总结,欢迎探讨。1、QPS保障目标...【详细内容】
2021-12-27  大数据架构师    Tags:架构   点击:(5)  评论:(0)  加入收藏
前言 单片机开发中,我们往往首先接触裸机系统,然后到RTOS,那么它们的软件架构是什么?这是我们开发人员必须认真考虑的问题。在实际项目中,首先选择软件架构是非常重要的,接下来我...【详细内容】
2021-12-23  正点原子原子哥    Tags:架构   点击:(7)  评论:(0)  加入收藏
现有数据架构难以支撑现代化应用的实现。 随着云计算产业的快速崛起,带动着各行各业开始自己的基于云的业务创新和信息架构现代化,云计算的可靠性、灵活性、按需计费的高性价...【详细内容】
2021-12-22    CSDN  Tags:数据架构   点击:(10)  评论:(0)  加入收藏
▶ 企业级项目结构封装释义 如果你刚毕业,作为Java新手程序员进入一家企业,拿到代码之后,你有什么感觉呢?如果你没有听过多模块、分布式这类的概念,那么多半会傻眼。为什么一个项...【详细内容】
2021-12-20  蜗牛学苑    Tags:微服务   点击:(9)  评论:(0)  加入收藏
我是一名程序员关注我们吧,我们会多多分享技术和资源。进来的朋友,可以多了解下青锋的产品,已开源多个产品的架构版本。Thymeleaf版(开源)1、采用技术: springboot、layui、Thymel...【详细内容】
2021-12-14  青锋爱编程    Tags:后台架构   点击:(21)  评论:(0)  加入收藏
在了解连接池之前,我们需要对长、短链接建立初步认识。我们都知道,网络通信大部分都是基于TCP/IP协议,数据传输之前,双方通过“三次握手”建立连接,当数据传输完成之后,又通过“四次挥手”释放连接,以下是“三次握手”与“四...【详细内容】
2021-12-14  架构即人生    Tags:连接池   点击:(17)  评论:(0)  加入收藏
随着移动互联网技术的快速发展,在新业务、新领域、新场景的驱动下,基于传统大型机的服务部署方式,不仅难以适应快速增长的业务需求,而且持续耗费高昂的成本,从而使得各大生产厂商...【详细内容】
2021-12-08  架构驿站    Tags:分布式系统   点击:(23)  评论:(0)  加入收藏
本系列为 Netty 学习笔记,本篇介绍总结Java NIO 网络编程。Netty 作为一个异步的、事件驱动的网络应用程序框架,也是基于NIO的客户、服务器端的编程框架。其对 Java NIO 底层...【详细内容】
2021-12-07  大数据架构师    Tags:Netty   点击:(17)  评论:(0)  加入收藏
前面谈过很多关于数字化转型,云原生,微服务方面的文章。虽然自己一直做大集团的SOA集成平台咨询规划和建设项目,但是当前传统企业数字化转型,国产化和自主可控,云原生,微服务是不...【详细内容】
2021-12-06  人月聊IT    Tags:架构   点击:(23)  评论:(0)  加入收藏
微服务看似是完美的解决方案。从理论上来说,微服务提高了开发速度,而且还可以单独扩展应用的某个部分。但实际上,微服务带有一定的隐形成本。我认为,没有亲自动手构建微服务的经历,就无法真正了解其复杂性。...【详细内容】
2021-11-26  GreekDataGuy  CSDN  Tags:单体应用   点击:(35)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条