京东自营返利系统于2014年开始上线试运行,主要服务于京东各大采销事业群和涉及财务相关部门,有助于提高京东返利的规范性管理、决策效率以及人员操作效率,且能够在一定程度上避免返利漏收、少收及迟收的损失。面对日益不断增长的订单数据和返利政策数据,如何保证在海量数据下财务数据计算的准确性以及高效性。本文将为大家介绍京东自营返利平台的发展历程以及关键技术和实践经验。
京东自营返利系统是面向整个京东集团,覆盖所有自营业务线包括3C家电事业群、时尚居家平台事业群在内的多个采销事业群以及京东健康等子集团;服务于业务、财务、审计、供应商,已形成一套标化的返利全流程管理模式,包括规则设置、规则审核、数据统计、返利计算、金额确认、返利结算、风险监控、数据分析等功能;并且支持多业务场景的返利管理,包括采购规模返利、销售返利、回款返利、毛保返利、价保返利、促销返利、优惠券返利、定额返利、非结构化返利、综合返利等;系统已经具备海量数据的分析计算能力和全链路数据质量监控能力,提供高可用的查询服务能力,拥有精准权限控制和流程管理功能,保证可靠高效稳定的数据服务。
返利系统是以规则为基础,返利计算为核心,返利账单为结果的一套业务财务系统,业务人员通过系统 可以进行线上对账,下传结算等操作;返利系统通用的业务处理流程可以参考如图所示:
该流程主要分为三个阶段:规则生成、返利计算、账单结算。
返利规则:返利规则信息主要包括基本信息、商品信息、界限信息、时间排除等,不同的返利类型 对应的返利规则内容也有区分,目前主要是通过返利岗直接在返利系统人工录入或者直接打通合同、促销、优惠券、VC、零智等系统将返利规则相关信息自动集成到返利系统中,当前返利规则支持多种集成方式,主要包括http接口、jsf接口、mq集成、人工录入以及提供html页面嵌入集成方式;当返利规则审批通过后,在生效期间内便可开始进行返利计算。
返利计算:返利规则生效后需要依据规则、数仓业务订单模型表数据进行返利金额计算。主要包括如下几个步骤:规则计算任务划分、数据抽取、订单清洗、订单金额统计、返利金额分摊、数据推送;返利计算触发主要依赖划分的计算任务,计算任务划分是非常重要的一个步骤,它根据返利规则中的规则开始、规则结束时间、循环方式和循环周期等属性决定生成返利单期间,计算任务是返利计算的核心,贯穿着整个返利计算的流程;数据抽取将数仓模型经过加载转换成返利口径数据,然后经过清洗、汇总等步骤将返利规则与订单进行匹配计算,最终将计算结果数据推送到数据库中;
账单结算:返利计算生成返利单后需要将返利单金额与供应商进行结算,主要包括如下几个步骤:返利下传业务侧确认(包括返利调整),返利下传供应商确认,返利下传结算;其中业务侧确认时可以进行返利调整,对账单金额进行调增或调减,待审批生效后将最终金额由供应商确认无误后下传到结算系统进行结算操作,同一个账单支持分批下传,并且可申请撤回。
返利系统的发展可以归纳为三个阶段:早期阶段:2014~2015年,业务场景相对比较简单,系统支持返 利类型也比较少;发展阶段:2016年~2019年,业务快速发展,返利类型也愈加丰富,返利规则数据和 订单数据也急剧增加;现状:2020年之后,业务高速发展,数据量持续不断增加,对返利系统的准确性 和时效性要求越来越高。
在返利系统上线初期,为了快速支持业务的发展,采用的是”烟囱式“架构,系统架构上的局限性无法满 足业务高速多维发展的需求,主要表现在如下四个方面:
系统扩展性弱:代码模块度耦合严重,硬编码多,代码质量持续恶化;
系统稳定性差:核心接口及功能性能较差,严重影响下游使用和用户体验;
计算流程冗长:计算时效性不高;数据抽取逻辑冗长复杂;
系统维护成本高:系统自上线以来,不断叠加业务需求,导致系统臃肿;
具体表现在:
1. 系统扩展性方面:早期返利系统的整个结构趋于传统的单体架构,业务逻辑耦合在一个工程中,而且为快速支持业务发展的多样性,需要在原业务逻辑下不断叠加业务逻辑,当现有功能不能满足需求时,会不断新增表来满足需求,慢慢的整个系统相似功能的数据库表不断累加,导致整个表关系比较混乱,下图是部分返利类型规则相关的表的血缘关系。
上图中可以看到,返利类型都依赖一张基础表,而且每种返利类型依赖的规则条件表可以是相同的,也可以是不同的,同时不同的返利类型还有个性化的表,例如图中的表1、表2等等。把这些表的依赖关系抽象出来,可以如下图所示,这是一种典型的复用性差的模型设计。
从整个表结构的血缘关系和模型设计中,可以看到这种”烟囱式“的架构,显而易见的问题就是功能的重复开发,每当来一个返利类型的需求就需要进行重新开发,导致系统功能的重复建设,代码的复用性差;除此之外,这种架构也不利于业务沉淀和系统的持续发展,系统架构的局限性已无法满足业务高速多维发展的需求。
2.系统稳定性方面:由上述描述可知,返利规则涉及到的表比较多且数据分布广而且表结构相对不统一,导致规则数据难以打通,而要获取全量数据情况下,需要通过sql的join操作进行操作,随着返利类型的增多,表数量也会相应变多,导致整个连接查询越来越复杂,下图是关联查询语句的伪代码:
在不断增长的业务数据量的情况下,数据量达上千万甚至过亿时,接口和服务的性能比较差,影响 下游的使用和用户的体验;通过接口性能监控上可以看到,返利规则查询接口的tp99在2s左右。
3. 返利计算引擎方面:除了系统架构上的问题之外,整个返利计算流程也比较冗长。首先是整个ETL流程比较冗长复杂,返利计算依赖业务订单数据,在计算之前需要将业务数据按照返利口径进行ETL,从hivesql数据加工到云存储再到hdfs,不仅拉长了任务执行时间,也压缩了之后的返利计算时间,造成计算任务压力大。其次是返利计算采用的是MapReduce计算模型,该模型是多进程模型,进程的启动和销毁开销比较大,MR编程不够灵活,仅支持map和reduce两种操作,当一个计算逻辑复杂的时候,需要写多个MR任务运行,并且这些MR任务生成的结果在下一个MR任务使用时需要将数据持久化到磁盘才行,这就不可避免的进行遭遇大量磁盘IO影响效率。下图是返利计算的流程图。
4. 系统功能方面:同时系统功能还有一些体验类的问题,返利系统建设初期,权限系统和审批流等功能是独立建设的,没有和集团ERP系统打通,从而导致系统权限控制纷乱复杂不够灵活,代码中硬编码编写情况较多,系统维护成本高,代码可读性差,问题解决效率低。
针对早期返利系统存在的一些问题,我们在2020年开始搭建全新的返利平台,也叫金帆平台,能够更好的支持高速发展的多业务场景、提供高可用的查询服务,同时也具备高效准确的海量数据分析计算能力、全链路数据质量监控能力,在经过不断的数据建模、工程实践和系统优化后,平台的功能逐渐完备并且已经线上提供服务,高效的支持业务发展,同时也提升研发效率,降低开发成本。
在进行平台架构设计时,遵循一些通用的架构设计来进行标准化设计。在系统的高可用上通过数据库读写分离、异步化处理、缓存机制、多机房部署等方式保证系统的性能以及高可用,系统可扩展性通过模板化设计和配置化能力来保障,同时系统的易用性方面,考虑用户的体验,用户可视化界面的风格以及操作习惯统一,保证操作流程符合业务规则。在数据计算层的设计也遵循着一些基本原则,数据模型上采用宽表化的设计构建公共数据层;返利计算的公共处理逻辑下沉,保证公用逻辑的可用性;返利计算的可重跑,支持在返利计算的各阶段可进行重跑,并且保证数据计算结果的确定性。
当前平台的架构图如下所示:
整个金帆返利平台架构设计,从下往上总共分成了六层:
1. 源表层:返利计算时依赖上游源表数据多达上百张,主要是依赖京东数仓业务源表模型数据,返利计算使用的模型主要涉及fdm层、gdm层、adm层、app层,其中fdm层为基础数据模型,一般用来保存业务系统快照,将数据永久保存;gdm层为通用数据模型,负责统一的数据清洗、整合,实现各主题的数据标准化,屏蔽生产系统干扰,保障基础数据的高可用;adm层聚合数据模型,负责统一的数据口径封装,提供各主题统一维度和指标的最细粒度数据,为各业务方提供统一口径的共享数据服务;app层为数据应用层,面向应用场景,提供特定场景的聚合数据。
2. 抽取层:数据抽取包括两种场景,分别为离线抽取及实时抽取,离线抽取是指将数仓源表数据及业务逻辑依据sparksql等离线计算方式统一加工成返利口径的模型数据,返利口径模型数据与财务口径统一,经过返利的etl过程后将数据写入返利结果模型表;实时抽取主要是利用mysql数据库的binlake监听,并通过京东大数据平台的DTS传输作业将生产数据库中的数据实时同步至数仓,便于后续返利计算使用。数据采集到数仓里面后,会对数据进行各种的加工,然后产生相应的宽表,这些宽表被后续的返利计算使用。
3. 存储层:数据存储层主要包括如下几部分:规则数据存储、数仓模型表存储、返利计算结果数据存 储;其中返利规则等基础数据主要存储于京东JED弹性数据库及Elasticsearch,其中ES主要用于分散JED数据库查询压力,也会存储一些报表类数据;数仓模型表数据主要存储于Hive表,包括返利计算使用的源表数据及返利计算记录的订单明细数据,方便采销与供应商进行对账;返利计算结果的账单及应收数据会推送到JED库,对账业务明细数据也会使用MR方式推送Hbase数据库方便查询。
4. 计算层:返利计算主要是批量计算,包括以下几个步骤:订单清洗、订单加工、数据统计、返利分摊、数据推送;返利计算触发主要依赖计算任务,即计算任务到期会自动触发返利金额的计算;订单清洗主要是将计算任务与业务订单进行精准匹配,筛选出计算任务对应的订单范围,然后统计出返利金额后还会将总的返利金额按照指定业务逻辑分摊到具体SKU上,保证商品的精准分摊以及后续采销的业绩考核、财务的数据分析等业务需求。
5. 服务层:返利服务主要包括规则相关数据的集成服务以及返利按照不同业务逻辑的数据查询服务,例如返利规则集成服务、返利账单服务、返利数据统计服务、返利主数据查询服务等,数据服务层主要实现了与各业务方数据的打通,例如促销系统、优惠券系统、合同系统、VC系统、零智系统,也为京东集团采销以及财务等业务的展开提供了很大的便利性。
6. 应用层:主要包括返利服务、计算相关监控等大屏展示以及返利相关数据报表、采销业绩报表、决策分析类等数据报表数据展示,作用主要体现在两方面:一是帮助返利系统异常能够及时报警及后续流程处理;二是报表类数据主要用于返利运营决策分析及为返利政策提供正确的指引及引导,也能够使返利业务方及时关注到自己的返利现状及时做出调整,最大程度降低甚至避免公司损失。
在进行平台化建设过程中,也会考虑解决早期返利系统中存在的问题,主要从如下几个方面进行建设:
动态字段配置化扩展:针对早期系统中的问题,多种返利类型规则字段除了个性化字段,大部分字段内容可以复用,而在早期系统中这些规则表都是通过单独的表来实现,导致规则集成需求开发时每种返利类型代码独立,复用性差,代码重复建设现象严重;因此在进行平台化建设时,需要实现动态字段的配置化功能,规则的个性化字段通过配置化管理,使得每种返利类型个性化部分通过设置规则配置表实现,在通用基础表上增加个性化部分组成每种返利类型完整的规则内容,实现规则内容可动态调整。
通过上图可以看到,返利平台中增加了规则项配置表和规则项表,表设计采用横向表纵向存储扩展 方式,规则项配置表用来定义每种返利类型个性化字段,规则项表则可以理解为kv的存储方式,k使用规则配置表中定义的个性化字段,v则是字段的具体的值。该设计可以抽象为如下图的模型设计,是一种复用性比较好的设计。
返利计算引擎升级:返利计算引擎替换升级,由MR改为Spark方式,Spark是基于内存的迭代式运算框架并基于DAG计算模型,而且可以直接基于hive表进行数据读写,迭代过程的数据会缓存到内存中,缓存的数据可根据需要多次重复利用,并且Spark的RDD数据结构,每次transformation之后不会立即执行,只有触发action操作之后才会真正触发数据的计算执行,Spark支持丰富算子,不止map、renduce两种,操作更方便。返利计算过程优化,先是统一ETL流程,通过spark-sql方式直接读取数仓模型表数据进行ETL加工,加工后的数据直接写入集市hive表,不仅缩短ETL流程, 也为后面返利计算任务节省了时间,缓解返利计算压力。
高可用服务能力建设:返利主数据读服务能力建设,主要是基于ES搭建的一套主数据读服务,同时具备服务容灾能力。主要处理方式是利用公司的BinLake平台,订阅BinLog日志将多张表的数据实时同步到ES宽表中,减少数据表之间的关联查询,降低数据库的压力,提升查询性能;同时报表统计类数据也会经过离线加工之后,推送到ES集群中,使得数据查询更方便快捷。
下图是数据同步的简单流程:
当通过使用ES作为数据源提供服务时,接口的性能可见下图,性能比使用多表的关联查询时大大提升;
平台管控能力提升:返利计算依赖的数据源非常多,涉及到数据抽取、加工、清洗、计算、对外服务等多种场景,因此新版返利平台新增了全链路数据质量管控能力,监控和管理的对象不仅仅是数 据本身,也包括数据生产和使用等全链路的过程,同时在权限管理、审批流方面也与集团进行打通 并且做了精细化的管理,保证了用户的体验。
新版返利平台上线之后,在不到3个月内快速支持了5个重点复杂业务场景的项目落地,有效降低了研发人员的开发成本,项目需求交付周期也缩短了50%。
下面以具体的项目接入案例简单说明一下平台化之后的效果:
京东社区团购返利项目,该项目是集团的重点项目,横跨多个业务线涉及上下游系统几百个,时间紧任务重,返利系统涉及到几乎全流程的改造,返利计算方面涉及到定额、非结构化、销售、优惠券四种返利类型,需要近一半的返利类型改造。
返利规则:社区团购的规则存在个性化的字段,虽然规则基本信息信息可以复用,但是在规则集成、录入、审批等功能上改造,通过动态字段配置化扩展的能力,仅仅需要规则配置表添加个性化字段即可满足改项目要求,相比于早期系统的开发周期能缩短80%;
返利计算:针对该项目需求,返利计算ETL功能,可以通过配置化的方式通过单独的模型表中,进行抽取加工成返利计算模型表,所需要的开发工作量只是抽数的SQL的开发;而在数据清洗和数据 计算汇总方面,由于业务的逻辑个性化,需要针对性的开发;相比于早期系统来看,这块的开发复 杂度和返利计算的整体流程,有了大大的简化;
流批一体能力建设:当前返利平台以离线批处理方式为主对数据进行全量计算,这样能很好的保证数据的最终一致性,而随着业务的发展,增量计算的的需求也在日益增长,需要补充流式实时处理的能力,为保障实效性以便更好的经营决策,同时也需要在全链路数据质量监控及预警、返利计算性能优化等方面持续探索和建设。