导语:腾讯计费是孵化于支撑腾讯内部业务千亿级营收的互联网计费平台,在如此庞大的业务体量下,腾讯计费要支撑业务的快速增长,同时还要保证每笔交易不错账。采用最终一致性或离线补偿的方案往往会带来较多的处理风险或投诉。因此,我们提出了一种通用的基于应用层的长事务解决方案,将复杂的分布式一致性问题化繁为简。
1 引言
英国计算机专家Hoare所言,软件设计构建有两种方法,一是使其尽可能简单,从而一目了然确定其中不存在缺陷;另一种方法则是使其极为复杂,以至于看不出什么明显的缺陷。然而,实现第一种方法要困难的多。
腾讯计费是孵化于支撑腾讯内部业务千亿级营收的互联网计费平台,目前汇集国内外主流支付渠道,提供账户管理、精准营销、安全风控、稽核分账、计费分析等多维度服务。平台承载了公司每天数亿收入大盘,为上百个国家(地区)、万级业务代码、 百万级结算商户提供服务,托管账户总量 300 多亿,是一个全方位的一站式计费平台。
在如此庞大的业务体量下,腾讯计费要支撑业务的快速增长,同时还要保证每笔交易不错账。然而在分布式场景下要满足ACID,保证所有操作均执行成功才提交结果,随着分布式规模的扩大要达成一致性的时间周期越长。例如,Bitcoin的Scalability问题,为了满足一致性一笔交易的平均确认时间需要10分钟。因此,为了适应复杂的业务场景出现了Base理论,使用最终一致性来代替强一致性。在计费场景下,通常的一些最佳实践是:
先长款后短款原则。由平台方掌握主动权,即使出现异常情况下也可以通过补偿的方式保证一致性。例如,先支付后发货,若发货失败通过重试机制达到最终一致。
临界资源访问尽量使用乐观锁。例如,在读多写少场景使用乐观锁实现互斥,在保证一致性的前提下提高并发处理能力。
远程服务调用保证可重入。例如,已经支付成功的订单,如果再次提交也不允许重复支付。
非关键服务异步化。例如,对于支付旁路的操作,通常借助消息中间件进行解耦处理,并保证最终执行完成。
服务全链路实时监控。关键操作实时上报,监控每一步的成功率和转化率,做到异常的实时发现。
通过上述等机制,在异常情况下可做到读修复,写修复,异步修复等,以保证事前和事中的交易高一致。但考虑到问题的闭环,我们也建立了一套完善的针对实时订单,异步订单,离线订单的三级对账机制,以做到事后的保证。
然而,对于日均过亿的交易量,采用最终一致性或补偿性的方案往往会带来较多的处理风险及投诉,需要我们做到实时的一致性。同时,计费系统的逻辑多且复杂,目前涵盖了近百个特点迥异的支付渠道,异常处理强依赖开发者的经验,需要由平台统一处理异常问题来提高服务的容错性。随着业务系统的发展,系统会有不断的新功能迭代,加强逻辑的可管理性从而降低开发门槛,也是我们需要考虑的。
化繁为简是我们的目标,为了应对上述挑战,结合我们在计费领域的多年工程实践经验,决定着力打造一套通用的基于应用层的分布式高一致解决方案TDXA (Titan Distribute eXtended Architecture),将复杂的分布式一致性问题交给引擎平台处理使业务开发更加聚焦,主要实现以下目标。
分布式事务的原子性,保证交易实时高一致。
自动的异常处理,提高容错性。
基于状态机的流程管理,加强流程的可管理性。
TDXA通过在内部业务的试点,基于TDXA实现的计费服务,上线后通过对账统计发现异常的交易订单数量明显减少,整体服务质量提高。同时,由于TDXA屏蔽了复杂的异常处理,业务开发效率也随之提高,相同需求的开发工作周期较之前减少了近50%。
2 设计思路
2.1 分布式事务
在工程上,作为完整的计费服务,一致性不仅需要考虑数据层的数据一致性,同时也要考虑应用层的逻辑一致性。比如,转账这个行为,数据层可以保证每次数据的更新一致性,而应用层如果只减不加,用户看到的账户数据也是不一致的。交易的一致性,简单讲就是收对钱,发对货。看似简单的描述,但在实现中却面临了很多约束,导致容易出现一致性问题。比如:
计费功能模块多,业务逻辑复杂
支付交易链路长,一笔流程多达几十次rpc
业务请求峰值高,分布式服务节点多
请求响应时间低,需要保证用户体验
系统部署环境差,网络超时错误多
在OLTP场景下,用户的一次购买请求通常会涉及多个后端服务的操作,如果其中某一个服务调用出现了二义性错误(网络超时),此时应该返回失败还是成功,之前调用过的服务是否需要回滚?倘若请求量小的情况下,可以借助人工来处理部分调用异常,但是当请求量大了以后,人工介入的成本就非常高。