5.2 双11交易核心链路的故事
1. 多元化的玩法,海量的成交背后的核心链路
第八年的双11全球狂欢节已经落下帷幕,让人印象深刻的1207亿再次创造了历史,双11也从此进入了千亿时代。今年双11宗旨“全球化、娱乐互动化、无线化、全渠道”在活动中体现的淋漓尽致,从狂欢城、线下VR游戏捉猫猫、到双11万星璀璨的晚会,让无数人惊叹双11成为全民娱乐盛宴。在娱乐狂欢的同时,双11回报消费者最直接的就是买买买,“买出新生活、买出新高度”代表了无数剁手党的声音,为了让消费者买的爽、买的值,天猫也是用尽了洪荒之力,从全球精品的低价预售,到狂欢城数十亿的红包、购物券,双11当天更是火山红包、密令红包雨下个不停,再到品质商品半价、下午场满n免一,让消费者经历一波又一波高潮,停都停不下来。
图1 双11多样的玩法
每笔剁手之旅的背后都经过了哪些产品系统的处理,瞬间的剁手快感下面又发生了什么样的信息速递,我们通过一张图来感受。
图2 交易核心链路示意图
令人眼花缭乱的活动,背后是怎样的体系来支撑起这样多元化的玩法,接下来我们一层层的来解构。在每秒17.5w笔的高峰下,每笔订单所经的链路众多,如何海量的订单有序、准确的运行,如丝般润滑,需要完整的业务、技术架构和对高峰时刻技术的攻坚。
2. 核心链路-红包系统面临的业务技术挑战及解决之道
2.1 红包发放
红包发放需要保证精确的预算控制,即一个预算发出去的红包的总金额不能超过其预算金额。一个预算维护在一条DB记录中,对于红包火山等大访问量的活动,这将成为单点热点瓶颈,同时还会导致单表记录多过多,数据严重倾斜。
预算控制因与买家无关不需要实现单元化,而用户的红包信息需要实现单元化,发放不单需要考虑预算的扣减,还需要考虑预算扣减后用户侧需要尽快透出红包。因非单元化与单元化数据分布在不同的数据库以及机房中,这会导致跨机房调用,引入了更多不确定性因素。
1、挑战
如何应对单预算超过几十万的发放QPS,以及在2秒内透出用户获得的红包。为保证精确的预算控制,决定采用数据库的方式来管理预算,而按照之前的常规优化方式,单记录的发放QPS上限不超过4百。跨机房的网络通信也不能保证100%畅通,万一预算扣减成功后用户红包数据写入失败了如何感知并处理。
2、分桶方案
通过分析过往活动数据,我们将预算拆分为多个子预算,然后平均分布到多个数据库中,并根据红包发放请求中的用户Id路由到不同的子预算中。在子预算余额不足时,则路由请求至主预算中。多个子预算的扣减并不会完全相等,那么必然有一部分先发生余额不足,所以主预算需要比子预算多分配一些金额。当多个预算的余额都非常少的时候,可以进行子预算的回收动作,避免预算划分的碎片化。
图3 分桶方案
3、SQL优化
为了提升单记录的写入性能,我们对写入的SQL做了优化。红包发放的场景主要有三条SQL,两条插入语句和一条更新语句,更新语句是导致热点问题的根源,为了减少更新导致的独占锁,我们使用将三条SQL语句放在一起,仅通过一次网络传输就可以到达数据库服务器中。同时为更新语句设置条件以保证更新后的余额大于等于零,这样的写法可以做到扣减之前不用查询预算的余额,仅通过判断SQL返回的错误码就能识别是不是余额不足,减少数据库服务器的压力。为更新SQL添加COMMIT_ON_SUCCESS标签,保证事务成功后立即提交当前事务,不用等待客户端获得更新结果后再次发起COMMIT请求,减少了1次来回的网络交互,同时记录的独占锁可以立即得到释放。为更新SQL添加TARGET_AFFECT_ROW 1 标签保证如果满足条件的记录不存在,事务应该失败因不是成功并且影响的行数为零。
通过和DBA的沟通,我们还采用了集团DBA团队开发的数据库热点补丁,并且修改了数据库的磁盘写入参数,以10个事务为一个写入单位。
4、效果
采用前述的SQL优化方案后,单记录的发放可以稳定在8千左右的 QPS,摸高到大约1万 QPS。在32个库联合压测的过程中,我们发现了因sequence分配原因导致无法超过5万QPS,对sequence的分配SQL采用前述的优化思想优化后,顺利达到接近30万的QPS的性能。此时数据库与应用的性能都表现都比较平稳。
2.2 红包展现
当用户获得红包后,我们需要在多个透出界面中展现用户的红包。这些信息将包括用户一共有多少个红包可用、总计金额多少,以及详细的红包信息。统计这些信息是一件比较消耗数据库性能的事情,而拥有红包的用户是很可能在短时间内多次查询这些信息的。
1、缓存方案
为了减少数据库的减力,很自然的方案是使用缓存,记住用户前一次查询的结果。而问题的焦点就转变为了如果确定缓存应该失效,我们要在红包的多个生命周期节点里做关联逻辑才能确认缓存的失效,而这样的改动工作量会比较大,同时多次这样的工作很可能是没有意义的,因为用户很可能一次也没有看过他的红包。因为我们每次在进行红包状态的更新时,都会更新gmt_modifed字段的值为当前时间,这是一个通用准则,于是我们有了如下的缓存方案:
构造缓存时,采用事务内的一致性读取数据库当前时间做到缓存生成时间,如果该用户没有红包数据,那么缓存生成时间取2000年1月1日。当用户查询红包数据时,我们先执行一次SQL查询返回用户对应红包数据的最后更新时间,“然后比较这里返回的时间与缓存生成时间的关系,当用户红包数据的最后更新时间大于或等于缓存生成时间时,判定缓存失效。这样的判断方式非常准确,同时因为可以利用数据库索引且仅返回很少的信息,数据库性能消耗的并不多。
图4 红包查询方案
2.3 红包使用
红包使用的场景需要支撑超过8万QPS的峰值。业务上的规则是一次下单最多可以10个红包,那么对于我们来说,将需要更新10个红包的状态,产生10条红包的使用流水记录,并且还需要产生至多10条红包相关的业务单据。而通常的情况是用户的一次下单行为所涉及的红包会被全额使用。
1、SQL优化
通过SQL分析我们发现在红包使用场景中数据库花费了大量的CPU资源进行SQL解析,同时一次下单涉及的SQL语句也很多,有非常多的网络消耗。而mysql并不像sqlserver等数据库那样支持预编译,但好消息是mysql支持batch insert语法。于是我们可以使用batch insert的语法来优化插入性能,使用一条UPDATE SQL更新多条红包的方式来优化更新性能,然后再将些SQL使用前面提到过的合并优化方案合并为一条大的SQL语句发送给数据库服务器,减少网络交互。假定本次用户下单时全额使用了3个红包,那么可以通过一个SQL将三个红包的余额更新为零,同时还使用了金额锁保证红包并没有其它的事务并发更新。同时为更新语句添加TARGET_AFFECT_ROW 3的标签,如果红包已经被其它订单在并发场景下使用,那么它会使当前事务失败,并且我们可以通过数据库返回的错误码识别这一情况。
2、效果
通过前述的优化措施,在典型的场景下,数据库服务器的负载下降了至少50%,而且下单的整体响应时间也减少了至少50%。
2.4 红包系统可靠性保障--一致性消息通知(hjbus)
前面有提到红包的发放只是扣减了非单元化场景的预算,然而我们还需要在预算扣减完成后写入单元化场景的用户红包数据。它们处于不同的数据库,我们需要有机制来保证它们的一致性。除了一致性,还有时效性的需求,因为我们需要在发放成功后2秒内就能展现用户的红包数据。普遍的方案使用跨库事务框架来解决问题,但是轻量的跨库事务方案不能做到严格的事务一致性,而严格的跨库事务一致性方案显然是相当重的,它会极大的降低性能。加上我们还有内部业务流程串连的需求,所以便产生了一致性消息通知-hjbus。
hjbus的思想在是业务的事务中插入一条消息记录,建立一套消息的订阅与分发系统来支撑消息的处理。因消息记录与业务记录存在于同一个数据库中,可以做到事务一致性。消息记录并不大,并且多个订阅者共享同一条消息记录,因此并不会增加过多的数据库性能消耗。目前我们已经可以做到生成的消息在1秒内就可以消耗,因此可以保证用户的红包数据透出时效。
图5 一致性消息通知-hjbus原理示意
同时通过消息积压的监控,我们可以及时的发现哪些消息的消费出现了问题,出现了什么问题,保障业务各流程的完整性。在一系列的优化工作完成后,我们的红包系统在双11前后都表现的相当稳定。
3. 核心链路-交易系统面临的业务技术挑战以及解决之道
双11当天交易下单峰值达到了创纪录的17.5万笔每秒,而每次下单都需要完成优惠的计算、红包的使用等一系列的操作,对整个系统的调用量实际远远高于17.5万每秒。如此高的并发,加上交易系统在数据上不能出任何差错的特点,对系统的性能和稳定性方面的要求都非常之高。
3.1 前置处理,提升性能和稳定性
我们的下单系统需要访问物流系统获取运费模板,并计算运费的价格,在以前的架构中,这需要调用远程的一个系统,由那个系统准备好相应的数据,计算结果后返回。这种方式会把下单的峰值带到下游所有的依赖系统中,也就会要求下游依赖系统具备峰值同等级的能力,这不仅使得整体成本很高,而且下游系统的稳定性也会影响整体下单的稳定性,在依赖关系非常复杂的交易系统中对整体稳定性带来了很大的挑战。
把功能前置后,需要计算运费时,下单系统无需请求一个下游系统,而是直接访问存储着运费模板数据的缓存服务器,并通过前置在下单系统中的运费计算模块,直接在本地计算出运费。这种方式不仅减少了远程服务调用的网络开销,带来了性能的提升,同时也减少了下单系统依赖的下游系统个数,增强了系统的稳定性。
我们对很多下游调用采用了功能前置的架构优化,通过双11当天的验证,这种方式在高峰情况下表现突出。
3.2 架构升级,提升开发效率和可靠性
双11的挑战不仅仅是性能和稳定性,由于参与双11的业务团队数量越来越多,业务玩法也越来越丰富,所以直接参与到双11业务开发的团队个数和开发人数也越来越多。众多的团队和开发人员,同时在一个平台上开发,怎么提升开发效率也是很关键的一个点,这关系到是否能按时完成需求的开发。
针对多团队协同开发的场景,交易平台去年完成了架构的升级,在新TMF2框架(见图 6)下,业务级的代码和平台级的代码进行分离,平台级代码对于交易的能力进行分类、抽象并对外透出,业务方的开发团队能力自助地利用平台提供的能力完成各自业务的定制逻辑的开发,无须依赖平台团队介入,从而大幅度提升整体业务开发效率。
图6 TMF2整体架构
TMF2 作为业务与平台分离的业务框架,主要通过两大类模型(能力模型、配置模型),并基于这两大类模型生成的配置数据来贯穿两个业务活动主线(业务配置主线、业务运行主线),详见图7。
图7 TMF2框架模型图
通过对交易建模、抽象和收敛,形成了交易域基础能力层,提供了各交易需要使用的核心能力,采用功能域-》能力-》扩展点方式进行表达。
例如,在合同订立(下单)环节归纳有十几个功能域,比如优惠、支付、交付、价格、订单、结算、税费等。这些域里的能力又通过扩展点的形式开放给业务方开发做定制,以适应其不同业务场景的需求。
在此基础上还引入了产品的概念,它是包装了多个域的能力,对业务方提供了能满足某种业务功能的能力包,从而使得业务能直接使用,加快业务开发效率。比如预售产品。业务能力和产品,通过业务场景串联,从而形成一个完成的业务解决方案。
在这个架构中,业务能力、产品和场景属于平台能力,业务方的定制功能都存放于业务包中,这样的架构可以做到业务于平台分离、业务之间隔离的效果。从而使得平台的开发人员和业务的开发人员之间互相不干扰,而不同业务的开发人员之间也互不影响,这极大的提升了多团队同时协作的效率,从而提升了整体的效率。
4. 核心链路-营销系统面临的业务技术挑战以及解决之道
2016年双11,营销平台是天猫与淘系优惠系统合并后的第一个双11,在系统性能、稳定性、数据一致性上遇到了诸多挑战。下文主要是阐述营销平台系统在高性能、数据一致性上遇到的挑战与解决方案的实践,最后再介绍主要的玩法“双11购物券”从招商到交易过程中,我们的解决方案。
4.1 营销平台双11整体架构
营销平台包括2个交易核心系统,分别是UMP(图中红色部分)与PromotionCenter(图中黄色部分)。
UMP负责所有优惠计算、优惠在导购与交易链路中的透出,包含三部分:
- UMP的核心是优惠计算。例如,折扣价是多少,这笔订单能用多少的双11购物券,抵扣多少金额;
2、优惠规则引擎负责处理优惠与优惠之间的关系。例如,店铺优惠券能和店铺满减活动叠加使用;
3、狼烟多级缓存框架负责将优惠数据根据功能、热度等因素分配到多级的缓存中,同时屏蔽了不同缓存的实现。
在2016年,UMP整合了天猫优惠系统,将原天猫优惠的所有功能与数据都完整的迁移到了UMP中,今年双11和去年相比,调用链路、数据流都发生了巨大的变化。PromotionCenter是权益平台,负责权益的传播、权益的管理。目前主要的权益包括:卡券(店铺优惠券、店铺红包、商品优惠券、天猫购物券、双11购物券等)、优酷会员等。
4.2 数据一致性实践--通用数据对账平台
双11对于营销平台的挑战,先从数据说起。由于营销都是在和钱打交道,钱算的不对,带来的就是资损,所以数据的一致性对于业务正确性来说,尤其重要。
4.2.1 数据一致性的挑战和目标
1、优惠数据产生与使用过程会经历多种数据源(DB、TAIR、Vsearch等)
2、单元化部署结构导致数据会在多个机房中存储
3、优惠与外部如资金,搜索等都有关联,数据链路异常复杂
4、缺少主动发现和补偿机制来保障数据的最终正确,可能引发投诉与资损
4.2.2 我们建立的通用数据对账平台的目标
1、抽取底层模型,形成统一的结构
2、支持多种数据源,如db与tair等,自定义对比方式
3、支持增量与全量对账
4、业务可配置化,能快速上线,发现线上不一致问题,以及相应处理与报警
通用数据对账平台(DataCheck,简称DC)整体架构
底层基于JStorm 实时流式计算框架作为运行的基础,上层增加了任务调度管理,数据源、对账脚本管理、监控报警管理等模块。用户可以通过实现简单的对账脚本,就可以完成数据的对账工作。
离线对账,通过chronus定时调度程序,扫描DB或者定时拉取云梯表的数据,将需要对账的内容组装成metaq消息,DataCheck根据消息内容执行对应的数据对账脚本(数据对账需要预先在百宝箱中配置好),最终的执行结果
实时对账,与离线对账的差异在于触发的机制不同,实时对账通过DB的DRC消息触发,精卫通过消息触发DataCheck进行对账。
4.2.3 与功能相类似的BCP的对比
| DataCheck | BCP |
多数据源支持 | 支持 | 支持 |
动态脚本支持 | 支持 | 支持 |
云梯离线 | 支持 | 不支持 |
DB扫表 | 支持 | 不支持 |
可视化后台管理 | 完善(基于JStorm) | 不完善 |
动态扩容 | 完善(基于JStorm) | 不完善 |
异地多活 | 完善(基于JStorm) | 不完善 |
资源隔离 | 支持 | 不支持 |
4.3 多级缓存框架实践 —— 狼烟多级缓存框架
在UMP整合了天猫优惠系统后,由于天猫卖家中,会有大卖家,如:猫超、当当网、优衣库。每到大促,热点数据成为了我们关注的问题。UMP由于实时性的要求,是一个重度依赖缓存的系统。如何防止热点数据击穿,提升热点数据的访问效率,我们建立了一个多级缓存框架来解决这个问题 —— 狼烟。
4.3.1 狼烟三级缓存结构
1、预热缓存,在双11大促里我们是可以预测出一些热点数据和必定极热的卖家维度数据。这种促销级的活动在一定的周期内是禁止编辑的,在开始的周期内将预测的热点数据提前写到本地缓存。在16年双11,狼烟做到了在3分钟内完成7千多台机器、几个G数据的预热。具体实现有堆内、local tair(堆外)
2、热点缓存,存储在应用中的活跃数据,一些无法预测买家购买行为的数据可以按照周期内QPS排序,保证Top热点常驻在零点里。我们和sentinel团队的子矜合作,提供了初步想法,最后由子矜完成hotsensor,采用hotsensor来防止黑马热点的问题。
3、全量数据缓存,一般采用tair实现,支持ldb与mdb
4.3.2 狼烟特性
1、统一接口
由于不同缓存有不同的实现,接口差异性较大,在狼烟里封装了统一的API,业务代码在应用时,无须关注底层实现
2、流程控制
狼烟支持在多级缓存获取的流程上,做到细致的控制,如各级缓存的写操作、tair&db一体化、db限流等等
3、缓存控制
在狼烟里可以做到任意一级缓存的可拆分,可以细粒度到只访问某一级缓存(包括db,在狼烟里db也是统一的一套接口,由应用提供回调)
4、预热缓存
狼烟采用蜻蜓进行分发需要预热的数据,采用统一的数据结构包装预热的数据,在单机生成数据(文件)后,提供数据获取接口给到蜻蜓进行分发,分发的流程如下图
图8 狼烟分发原理
5、热点缓存
高峰期驱逐策略:两小时内数据有效,在周期内针对数据访问的qps和最近访问一次时间点进行排序,排在最后面的驱逐。热点缓存依赖了hotsensor进行热点的计算,hotsensor针对周期内的单位时间做了一个滑动窗口。采样窗口长度设为1.5s或2h,这个采样窗口又被分割为20个格子。通过用一定的算法来统计这20个格子的平均滑动窗口累积平均值来进行统计.
计算公式:
6、数据处理
在涉及到多级缓存时,未命中的key到下一级进行查询,多key的情况(譬如常见的:mget、mprefixGet、mprefixGets)需要组装每次的查询结果,去识别到每一个key。代码量比较多且重复,在ump里面充斥着大量的组装返回结果的代码,在应用狼烟后,清理了一大批这样的代码,用两三行去替换之前几十上百行代码,大大增加了代码可读性
4.3.4 狼烟在2016双11表现
1、预热缓存
- 优惠活动数据,命中率为百分之十几,减少到Tair百分之十几的调用量。
- 卡券规则数据,命中率近乎100%,应用基本不需要访问Tair获取这部分数据
2、热点缓存,0点峰值整体命中率为20%左右,支持单key最高40多万的 QPS访问,没有出现击穿缓存到DB的情况。、
5. 业务中台,电商链路的基石
交易,营销,资金只是业务平台事业部的一部分功能,除此之外部门还有商品,会员,店铺,商户,电子凭证,LBS,数据,评价,规则和内容功能单元。单元之间无缝的衔接构建了阿里集团电商板块业务的全链路业务支撑技术体系,除了耳熟能详的三淘之外,还有很多新兴的业务。利用了平台提供的模块化、可视化配置的技术组件,开放服务和元数据来快速定制独特的商业形态,多个渠道的商业数据又通过Imap技术动态归一沉淀,为平台治理和商家多渠道铺货提供便利。
业务平台事业部承接集团“大中台,小前台”战略业务层部分,以支撑业务方快速,低成本创新的能力为目标。然而,业务中台并非部门一己之力来建设,集团的技术团队都是业务中台能力的提供者,没有团队界限,只有”高效实现业务”的共同目标。按照一致的标准和协议注册到中台,确保模块之间的连通性,避免重复低效建设。随着业务的频繁上线,不断沉淀、打磨、升级能力,技术同学发现自己精心打造的能力被多个业务使用,真是莫大的鼓舞!步入良性循环的运营机制,业务实现的效率越来越高。
双11是业务平台事业部难得一次的全员大练兵,我们用实力和勇气证明了自己,然而我们却愿意退居幕后锻铸平台,支撑前端丰富多彩的繁荣生态。今天最好的成绩是明天最低的要求,我们仍然保持追求极致用户体验,性能,稳定的目标,用技术拓展业务边界,为业务方提供简单,可信赖的电商技术基础产品,高效高质量地支持前端业务快速发展和创新,这是我们的愿望,也是我们的使命!