电商行业近年来发展势头迅猛,诸多巨头成功上市,业务模式不断升级,促销手段花样百出。双十一成为各路电商运营能力的年度大考,同时也是对电商技术平台能力的极限测试,每一年进行了重大改版升级的系统只有通过双十一的枪林弹雨才能浴火重生。前端
在当当,2015年的双11,面临考验的是促销系统和交易系统,二者都是电商体系的核心组成部分。这次双11专题,InfoQ特别邀请EGO会员、当当架构部总监史海峰先生,为你们讲述当当双11背后的技术故事。数据库
另,ArchSummit全球架构师峰会北京站将于2015年12月18日~19日在北京国际会议中心召开,大会设置了《揭秘双十一背后的技术较量》专题来深刻解读双十一背后的技术故事,欢迎关注。后端
相关厂商内容缓存
相关赞助商安全
ArchSummit深圳2017,7月7-8日,深圳·华侨城洲际酒店,精彩内容抢先看服务器
现在大规模促销已经成为大大小小的电商平台及入驻商家运营的常态。随着业务的复杂化、运营的精细化,以及品类、平台、渠道的不断丰富,各类新的促销形式也层出不穷,贯穿从商品展现、搜索、购买、支付等整个流程,电商对于精细化、精准化促销运营的需求也愈来愈强烈。微信
一次促销活动几十万商品,一天以内几十个、上百个促销活动已经是屡见不鲜,至于入驻商家的常态促销更是不胜枚举。双十一期间,电商平台和商家更是会使出浑身解数,火力全开,无品不促销。架构
促销规则支持分时段设置,多个活动可以叠加,促销系统中的数据量甚至会超过商品信息系统,并且促销内容会根据执行效果快速调整,这些都对促销系统提出了更高的要求,促销系统越强大,促销活动才能玩得越疯狂。框架
咱们在重构前面临的情况,是促销模型比较陈旧、扩展性差,促销系统成熟度低、与其余系统耦合严重,新增一个促销类型可能牵动从单品展现、搜索、推荐、购物车、交易、订单、退换货、库存、价格、促销自身等一系列产品线的变动。所以,促销系统的重构势在必行,数据模型与运营的贴合度决定的扩展性、灵活性,系统解耦和更强大的数据处理能力,是核心改进点。less
最基本的促销模型很简单,以下图:
在当当,有一些“类促销”业务,从广义上能够纳入促销范畴,但业务与数据均不属于促销系统,在设计中,咱们考虑将这类业务逐渐回收;另外,促销系统能不能承担一些营销的功能?带着这两点考虑,在促销基础上进一步抽象出活动模型。
什么是活动?咱们认为任何一个有时间范围的事件/动做都可称为活动,活动则抽象为三要素组成:基础信息、维度(条件)、工具(动做)
例如,在11月1日10:00-12:00在第一会议室开双十一准备会,讨论双十一各系统须要准备的事项,须要各系统负责人参加;那么这个活动的基础信息包括时间(11月1日10:00-12:00)、主题(双十一准备会),维度包括地点(第一会议室)、与会人员(各系统负责人),工具(动做)包括议题以及讨论自己。
那么推而广之,理论上,只要有相应的工具对接,能够用这个极简的活动模型,去管理任何一类活动,这样模型就变为了两层:
实际业务中咱们遇到过的一些关于促销计算单元的头疼问题。买了一堆商品,到底哪几个应该做为一组计算条件和优惠,在促销叠加的场景这一点显得更为复杂。因此咱们引入做用域来定义这个计算单元的范围。例如常规的限时抢促销,每一个SKU有本身的价格,那么SKU就是这个促销的计算单元,也就是促销的做用域;例如第二件5折,可能会按SPU来作,你买一个红的一个蓝的,仍是能享受促销,那么SPU成为了这个促销的计算单元;诸如此类,现有及将来可扩展的还有店铺、品类、品牌等等。简言之,这个做用域成为促销计算引擎进行计算单元分组的依据。因而模型又变成了这样:
举个例子,咱们要在11月11日11:00-12:00针对IT技术类图书进行满200元减100元促销,购买过此类图书的客户每本书每人限购一册。那么这个活动的基础信息包括时间(11月11日11:00-12:00)、主题(程序猿光棍节福利);维度包括商品品类(IT技术)、用户范围(购买过此类图书的客户);工具是满额减促销、以金额满200元为条件、减100元为优惠,此外还有限购策略为限购1本,做用域为参与活动的全部商品;
可能这里会引起困扰,基础信息的时间为什么不能算作时间维度?维度也定义了一些限制条件,那和促销工具模型里的条件有什么区别?时间之因此不纳入维度,是基于前面对活动的定义,时间范围是必须的,而维度是可选的;促销模型中的条件只对于促销工具备效和有意义,而维度则有更普遍的普适性,例如平台、渠道、地区、用户、商品等,与工具是什么并没有关系。
基础模型定型以后,咱们开始着手解耦方面的设计:
首先是系统交互解耦,将直读DB和存储冗余促销数据的系统修改成调用服务及监听MQ;而后是逻辑回收,包括将促销校验与促销计算提取为交易服务,将原先由购物车、交易系统自行处理的促销逻辑回收;从业务上,将促销工具的属性进行提取,诸如类型枚举、促销标签、限购策略、库存策略等,以期外围系统尽可能少的关注促销类型,经过促销ID拿到所需信息直接使用;将来则关注于业务层面的梳理与整合,逐步回收适用于活动模型的其余“类促销”业务。
系统解耦后,促销系统须要提供各系统所须要的服务,必须具有更强大的数据处理能力和更好的性能表现。应用架构实现上,从前端页面到后端逻辑,尽可能避免有逻辑与促销类型直接绑定,所有以插件化方式与促销模型对接,彻底根据促销类型的配置进行组装。针对不一样维度、条件、优惠、促销属性,定制页面模板及业务逻辑,使得新增一种促销类型(在已有维度、条件、优惠下)仅需配置便可完成。
促销系统的查询服务须要同时为多个系统提供数据,对TPS要求很高,同时促销的时效性又要求很高的实时性。咱们采用的方式是在数据库前加Redis缓存,提升响应速度,同时监听MQ,根据事件清理相应的缓存数据。
这种设计方案也有一些可能的坑,例如Redis缓存虽然减轻了DB压力,但对于计算密集型应用并未减轻应用服务器压力,IO没有节省还增长了序列化的开销;事件驱动清理缓存在读写分离场景下,有可能比主从同步更快,形成缓存数据错误。这也是具体应用中须要注意的地方。
促销系统重构上线后,使多渠道(终端)、多区域化营销成为简单易行的配置操做,显著提升了当当运营能力,当当双十一呈现出更多的想象空间。
交易系统是客户购物流程中最重要的环节,主要任务是完成购物车中商品信息获取、拆单、促销计算、配货计算、运费计算、非现金支付的使用以及生成订单等操做,聚合各方面业务逻辑,计算很是复杂,并且响应速度影响购买转化率,一旦出现故障,直接影响营业收入,可谓电商最为敏感的核心系统,决定对其进行重构须要极大的魄力。
当当原有交易系统采用.NET技术框架,运行多年,很好的支撑了购买流程,可是弊端逐渐显露。首先是技术体系属于微软系,每一年要花费大量成本购买服务;其次是随着业务需求的不断叠加,其结构及可维护性逐年降低,尤为是众多小版本结算的存在,使得功能扩展异常艰难。
基于以上因素,交易系统团队在2014年末启动重构项目,2015年10月底新老版本完成切换。这次重构耗费约1500人天,重构代码17万行,所有切换至Java开源技术架构,为公司节约大量成本,并进行了架构优化,总体性能平均提高25%。
交易系统业务主流程图以下:
交易系统重构引入了许多业界成熟的技术实现方案,主要有如下几点:
集中化配置方式,一点配置,全部实例可见,更易于管理,并且配置修改后,经过热加载方式,马上生效,快速便捷。而原有交易系统修改配置后,必须重启系统才能生效。
用户请求一次交易结算页面,会调用各类后端服务,而因为逻辑的复杂性,每次服务调用都会调用订单计算大流程,致使页面刷新缓慢。新交易系统将大流程计算结果进行缓存,在一次页面请求范围内,后续调用直接用缓存结果,极大提升了页面的刷新速度。
因为历史缘由,交易系统存在不少版本的结算逻辑。最经常使用的是统一结算,还有一些特殊类型的结算,如秒杀、一键下单、补发货等等,逻辑与统一结算稍有不一样,统称为小版本结算。因小版本结算与统一结算大部分逻辑相同,所以新交易系统将两者合到了一块儿,共享基础逻辑,而不一样的逻辑则单独处理,极大提升了可维护性。
借助了Nginx在运行状态下能够reload配置,而基本不影响对外提供服务的能力。每一个Nginx负载两台应用服务器,灰度发布时,将Nginx配置更改成只负载一台应用服务器,便可对另外一台进行部署。用户请求不会导向正在部署中的服务器,从而不影响用户下单。
(点击放大图像)
交易系统重构后,尽管进行了大量的测试,仍不能放心部署上线。由于交易系统的计算都和金钱有关,必须慎之又慎,咱们提出了线上并行比对方案,根据老交易系统比对新交易,保证其逻辑正确。原理以下:
1) 用户请求到达老交易系统
2) 根据条件将部分请求数据复制,发送至调用mock服务的新交易系统
3) 新老交易同时计算,结果存入各自的数据库,但只有老交易结果对用户公开
4) 对新老计算结果进行比对
这样,既实现了比对目的,又不会影响线上环境。
比对以后,新交易系统也不能当即全面上线,那样可能有巨大风险。咱们开发了分流功能,按照用户id来分流,正式分流前,先使用测试白名单中的用户进行预验证。预验证经过后,再按比例由低至高逐步切换。
基于前面所讲的灰度发布技术,新交易系统很容易作到按需伸缩。正常状况下,每一个Nginx负载两台应用服务器。双十一须要扩容时,将待扩服务器ip地址加入Nginx配置,从新reload,该Nginx就可负载更多台应用服务器了。
交易系统上线后为备战双十一,确保万无一失,利用老交易系统还未下线的条件进行了线上压测。为达到最准确的测试效果,且不影响正常系统运行,进行了如下的准备:
1. 测试环境、数据与生产环境一致
在准备测试环境方面,为了保证测试结果更接近真实结果,本次测试使用线上环境,经过大量测试帐号对线上的真实促销商品进行测试,这样也对新交易系统所依赖的各系统服务作了检验。
2. 线上业务运行保障
测试阶段线上的请求切到老交易系统,压测请求发送到新交易系统,使测试和生产业务进行分离,保证了各自服务器资源的独立性。在应用服务器层面使测试过程不会影响到线上正常交易。
3. 拦截订单回收库存
因为使用线上环境测试,须要对测试订单进行拦截,避免进入生产流程,并回收占用的库存,使商品不会耗尽库存,采用的方法是在自动审单系统中将测试帐户加入黑名单,测试订单提交后会被拦截,而后取消订单释放库存。为防止测试过程占用了商品的所有库存而影响线上销售,测试商品池基数很大,而且过滤掉了库存数量较少的商品,在执行测试过程当中控制每一个商品的使用次数,保证可销售库存占用在安全范围内。
4. 恶意用户策略控制
由于在交易下单过程当中包含恶意用户断定的策略,会对用户进行隔离,禁止连续大量下单,线上压测时根据实际状况短期内调整了安全级别,保证订单成功率。
通过多轮线上压测,新交易系统的高可用性获得验证,获得了实际性能指标,并根据双十一流量估算进行了扩容部署,将以崭新的面貌为广大客户提供稳定可靠便捷的网购服务。