网易宝支撑了整个集团业务绝大部分的支付场景,平均天天的支付订单有100万单,接近1亿的交易额。对系统的可用性要求极高。下面就从个人理解上说说网易宝的系统是如何实现高可用的。linux
先看看网易宝的系统总体架构(16年初的架构)nginx
网易宝目前系统总体架构图web
中间大的浅蓝色的部分为网易宝系统的整个体系。按照从下到上的层次关系分为存储层、技术组件、服务层、接入层。每一个层都有系统监控来监控系统的状态。服务层和接入层有风控系统来监控风险行为,保障用户资金的安全。算法
存储层:数据库主要使用Oracle。网易宝的核心支付服务是基于本地事务去保证数据强一致性的。用户支付完成,订单状态修改成成功,扣除余额,产生资金流水,须要强一致性的保证。订单和流水的数据占了网易宝数据库业务数据的绝大部分。Oracle在单机大表的性能上是很是高的。因此数据库采用的Oracle。文件存储主要使用的FTP。用于存放银行清算文件、对帐文件、结算文件。sql
技术组件层:包括dubbo分布式远程调用中间件、消息队列中间件kafka、 分布式应用程序协调服务Zookeeper、分布式缓存存储memcached、杭研调度系统、linux-crontab(逐步迁移到杭研调度系统上,后续废弃)数据库
服务层:为网易宝的核心层,提供高内聚的服务。网易宝支持多样化的支付需求是经过组装服务层的服务来完成业务流程的。包括用户帐户服务,订单查询服务,支付核心服务(实现了实名,绑卡,充值,支付,提现,退款的核心流程);网关服务payments-trans接入了几十家银行和其余支付通道;积分服务提供积分成包的充值、提现、发放和消费服务;网关路由服务gate-service提供支付时路由到具体的支付通道的服务;sign-service提供签名服务,保证内部系统之间和外部系统的调用请求的安全性;pay-gate提供第三方支付通道的对接服务;platform-module提供商户数据的查询服务。接入服务层的服务的方式包括dubbo,http,依赖jar组件。对帐中心和结算中心不参与用户支付的流程,对帐中心支持全部银行通道的对帐,核对咱们的备付金和用户商户的帐户资金彻底无误, 对网易宝的资金流水按会计分录作到日切,符合人行的监管要求。结算中心给商户提供人民币结算服务和外币结算服务。后端
接入层: 分为前台系统(界面交互, 后台API接口)和管理后台系统。 前台系统包括用户前台epay-web、收银台cashier(从epay-web拆分出来,正在开发中)、网易宝用户端APP、可嵌入第三方APP的支付SDK组件、活动系统promotion、商户前台系统platform-web。 管理后台系统包括后台管理epay-admin、网关管理payments-admin、商户后台管理platform-boss(正在开发中)。缓存
风控: 对用户在网易宝的整个行为作风险控制,保障用户帐号和资金的安全。风控经过kafka异步方式同步网易宝的业务数据,运用大数据处理技术作分析。安全
与网易宝接入层人机交互的有用户、商户、后台管理人员(技术支持&客服&财务),商户的应用(游戏、 考拉、一元夺宝、邮箱、理财等)。性能优化
网关系统和对帐中心后台依赖几十家银行的网关。
以上对网易宝的整个体系架构按照层次作了个简单的介绍,下面进入主题,网易宝系统是怎么实现总体系统的高可用性的。
网易宝的全部核心应用和中间件都是集群部署的,经过负载均衡,平均分配流量。
对于业务系统, 在nginx服务器(nginx集群部署,负载均衡使用LVS)上配置了负载均衡策略,路由请求到后端的应用服务器resin。若是web应用集群某台机器挂了,nginx经过心跳健康检查,3秒内能检测到,把这台机器从可用列表中剔除出去。
中间件dubbo的consumer基于负载均衡算法, 获取zookeeper上统计的provider的负载状况,决定请求哪台provider。Kafka也是相似的原理。若是dubbo服务的某台provider挂了,与provider维持长链接的zookeeper心跳线程会检测到,把provider从服务的可用provider列表中剔除,并快速通知到全部依赖该服务的consumer(也是维持的TCP长链接),consumer更新本地缓存的provider列表。
对于有状态的服务器,都有数据备份机制。
数据库主库会异步同步数据到备库。数据库主库挂了,若是切到备库,可能会丢失部分业务数据(异步复制,网络稳定状况下10ms之内的延迟,不是同步写多份的)。Kafka每条消息都会复制到不一样的机器(broker)上。Zookeeper上的数据也是多写的。Kafka的主broker挂了或者zookeeper的主服务器挂了,经过选举算法选举出新的leader。Leader用于读写,slavers用于备份。Leader挂了,从slavers中选举出新的leader快速恢复服务。Kafka和zookeeper是作了数据高可靠性保证的,极小几率会出现丢失数据的状况。
多机房部署上,网易宝有杭州、北京两地机房。杭州是主机房,北京是备,不是多活的。 北京的机房服务器数量较少,数据库服务器性能较差,数据复制也有秒级的延迟。因此不到万不得已,是不会切到备用机房的。目前网易支付已经在搭建义桥的机房,2017年实现滨江机房和义桥机房的双活,解决机房的单点问题。
综上所述,在同一个机房,网易宝不管是无状态的服务器,仍是有状态的服务器,从存储层,到中间件层,到应用层,都不存在单点问题。机房的单点问题也会在不久后解决。
更新不频繁的基础热点数据,如配置项、全部商户信息、网关数据,在应用启动时,加载到本地缓存。减小对数据库的频繁调用。
网易宝的session管理使用中心化的memcached集群,业务流程中的一些状态数据,也是存放到memcached。系统之间使用文件数据交互的,文件保存到FTP。须要持久化的业务数据保存到中心化的数据库。 不论是业务数据,仍是非业务数据,都不会保存到本地应用服务器,保证应用无状态化,使得应用集群能够快速的横向扩展。
为了保证核心支付服务的稳定性,数据库上作了读写分离。核心业务的读写走主库。对于读实时性要求不高的查询场景,查询备库。如商户系统订单的查询请求。对于耗时长的sql的查询场景,查询异构库,如商户的对帐单下载。
热点帐户处理异步化
为了不热点帐户上的行锁的激烈竞争影响系统吞吐,网易宝对热点帐户的余额更新和资金流水生成,作了异步处理。业务完成后若是须要变更热点帐户的金额,先生成缓冲流水,而后由调度任务异步去消费缓冲流水去更新余额、生成资金流水。使热点帐户的并发锁竞争变成了串行处理,大大下降了行锁竞争致使的线程阻塞,提升了系统的吞吐。
提现、退款处理对实时性的要求不高,经过异步化,对于处理失败的订单能够用重试机制补偿。避免了同步调用失败给用户很差的体验。
早期的网易宝只包括epay、epay-admin、payments、sign几个系统。 大部分的业务功能都集中在epay一个应用里。epay应用很是的庞大,包含了用户前台、收银台、积分成包、活动、商户前台功能、API、风控、资金对帐监控。存在如下几个问题:
a.核心业务功能和非核心业务功能在一个系统里,代码紧耦合,而且公用服务器资源,非核心业务功能出现问题容易影响到核心业务功能。
b.在一个应用上大量的分支并行开发feature,合并代码容易冲突。应用的一次发布包含几十个feature。一个feafure发布出问题,发布回滚,致使其余feature也一块儿回滚了。形成开发效率和发布效率低。
c.epay系统通过几年的业务和技术选型升级,遗留下代码多套并存的问题。一个需求的变动,可能须要从上层到下层,改动多套代码。核心代码的多套并存、低内聚,代码难以维护,使开发的工做量变大,而且容易出bug。使后续的系统拆分,服务化改造困难重重。
为了提升系统的总体可用性,提升你们的工做效率,针对以上几个问题,网易宝在过去的一两年里作了不少的重构改造工做。包括如下几个方面:
2.6.1 系统拆分
积分成包底层service从epay中拆分出来,独立jifen系统,提供服务化的接口。
活动功能从epay中拆分出来,独立promotion系统,提供活动业务功能。
风控模块从epay中拆分出来,独立risk系统,提供限额服务、黑白名单服务、反洗钱监控、用户风险评级。
网关路由模块从epay中拆分出来,独立gate-service系统,提供网关查询和路由支付、提现通道的高可用服务。
Epay与网关路由服务的调用关系
商户前台系统从epay中拆分出来,独立platform-web系统,提供商户的业务功能。
商户系统模块依赖关系图
2.6.2 代码重构
在此我向你们推荐一个架构学习交流群。交流学习群号:821169538 里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多。
底层核心代码消除多个版本,统一为一个版本实现,内聚化。
epay核心代码内聚归一
epay按层次拆分为多个子工程,底层子工程能够打包为公共jar组件,也能够包装为服务化接口。
Epay子工程拆分依赖关系图
提升系统的可用性非一蹴而就,只有深刻的理解业务,梳理清楚业务流程和依赖关系,工做中不断的发现系统的痛点,逐个解决,步步为营,系统的总体可用性才能上一个台阶。
出处:https://www.tuicool.com