猫眼交易数据的整合优化

一、猫眼交易数据的背景和现状

1.1 交易数据中心是什么?

交易数据中心用于收集在交易过程中产生的订单相关的数据,包括该笔订单详情、资金明细、分账明细、支付明细、商品明细、商家以及影院明细等信息,如果说订单中心是存储订单基本数据的,那么数据中心就是在其基础上的拓展,将订单相关所有数据全部收集于此,生成订单大宽表,服务于公司内各业务部门。

1.2 为什么要做交易数据中心?

1)统一复杂订单模型,数据实时性较低
猫眼内部一直有大数据团队对交易数据做采集、处理等工作。且大数据的数据运用到了猫眼内部多种不同的场合,比如我们的财务系统、还有诸多统计系统等。但同样大数据收集也有他自己的弊端,由于监听底层业务数据库,因此会缺少一定的实时性,且数据源的不同也会导致在大数据内部存在多套的数据模型。就订单层面而言,一笔订单的所有相关数据或多或少涉及多个业务方以及多个数据库集群,可能订单资金明细在资金流系统,支付明细在支付系统等,大数据数据采集只是对不同数据源数据按不同模型进行收集,由于他们不关心业务,因此在订单模型统一上也是比较困难的。对于一些实时性要求较高的服务,大数据也是很难去保证的。交易数据中心通过rpc接口形式去获取到交易相关数据,对数据进行统一模型处理,做到模型统一化、降低实时性等效果。

2)降低业务服务与财务、对账、结算等服务耦合性
财务、对账、结算等服务都是一个公司的底层数据服务,它们依赖于各业务产生的交易等数据,针对业务数据进行分析、统计等操作。就目前而言,猫眼内部这些服务的数据直接来源于各业务系统。由于各业务系统数据模型不一致,从而导致需要对不同业务数据做不同的逻辑处理,就结算系统而言,针对多个业务存在多套结算系统模型,在大数据层面,对各业务数据的存储处理也有多套数据模型,这无疑增加的数据复杂性以及各业务使用的成本。除此之外,这些底层数据服务也需要时刻去关心业务系统,如果业务系统发生故障或逻辑修改,会直接造成底层服务数据异常、缺失等,届时底层服务还需要配合业务服务区获取丢失数据、纠正错误数据等各种操作,对底层系统而言,这些关心业务系统的成本甚至高过于自身系统开发维护成本。交易数据中心的目标就是去统一去获取各业务数据,对各业务数据进行强校验,做到模型统一,对丢失业务数据进行数据监听补偿,打造一个完整的交易数据大宽表,用于服务底层财务、结算等系统,解决底层数据系统和业务系统耦合性等。

实时数仓数据流转图.png

1.3 交易数据中心带来的收益是什么?

  1. 从订单数据模型上做到了统一,做到数据处理近实时性等。降低了大数据收集数据延迟性、多数据源模型难以统一等缺陷
  2. 解决财务、对账、结算等服务与业务服务的耦合性
  3. 从数据本身进行数据检查、做到数据异常监听,保证了数据的准确性、完整性
  4. 给予不同业务、运营等提供更加便利的数据支持

二、问题与目标

2.1 问题归纳

  • 猫眼财务相关需要打造一套精确的财务系统,财务系统主要是对用户针在不同商家、不同影院进行的交易进行统计,包括用户交易额、优惠明细、商家信息等多项信息,最终根据相关数据汇总处理,生成公司相关财务报表。历史的财务数据由来都是取自于大数据,但是大数据的数据可能会与真正的交易数据存在差异化,从而导致财务数据的不准确,最终导致生成财务报表存在一定差异;

  • 历史的猫眼结算系统相当复杂,针对不同的业务,都有自己相关的结算系统,导致结算系统没有一套整体的规则以及系统,这主要是因为针对不同的业务,数据源不一样导致,像猫眼商品相关业务数据均出自于猫眼电商中后台,但是电影票相关交易是专门有一套选座交易系统,还有一些其他业务数据源均在自己的业务平台,这样就导致结算对接的业务不同,且结算规则不同,从而演变了成多个结算系统这样一个场景。

老结算-历史.png

  • 从电商中台的角度出发,目前也没有一套完整的订单数据收集处理系统,除了订单中心有相关订单部分数据之外,其余相关数据均在各个业务系统,从中台角度看,没有一套从订单层面出发的统一的订单模型去针对不同的订单数据进行统一处理。

订单查询-历史.png

2.2 系统目标与挑战

为了公司相关业务发展,我们着力于打造一套完整、准确的交易数据采集准实时系统,在数据收集方面,该系统不仅包含交易订单相关数据,也包含订单资金明细、商家、库存、分账、支付等多方信息,该系统不仅要对交易订单数据实时收集,同时也需要对订单相关数据进行归纳整理,最终入库。在数据精准度方面,由于数据来源于不同的业务方,数据的准确性、完整性以及一致性尤为重要,为了防止数据出现问题以及丢单等情况出现,该系统也需要对数据进行多维度监控,发现数据问题可以及时触发报警,以便于及时处理。在数据监控层面,我们也要尽可能做一些自动化数据补偿机制,当有问题订单出现时,在第一时间触发自动补偿系统进行订单校对与补偿,进而确保订单数据的完整性。

数据中心.png

2.3 挑战

在打造中台数据中心过程中,主要面临以下挑战:

  • 高性能:中台交易包含公司几乎所有的业务,在高并发的复杂场景下,作为承接猫眼所有交易数据的数据中心服务如何保证在不影响用户交易的情况下高效、快速的收集交易数据
  • 高扩展:随着业务增多,业务数据逻辑层出不穷,该系统如何做到灵活通用,用接近于0的成本去快速接入
  • 近实时:系统如何快速对采集到的交易数据进行处理,保证数据在尽可能短的时间内被处理完毕
  • 完整性:该数据系统如何保证采集数据的正确性与完整性,如何保证丢单问题
  • 数据量:当数据量达到一定量级以上,如何保证数据存储空间没有问题

三、技术设计与实现

3.1 系统架构

数据中心整体架构图如下:

数据中心系统架构图.png

数据中心系统主要有几个大的组成部分:

业务系统:业务系统是指数据中心数据采集来源业务方,主要包含中台交易、资金流、分账、支付几个大的业务平台
复制代码

    数据处理:数据处理部分又分为数据采集(Receiver)以及数据加工(Processor)两大模块,数据采集主要是对业务元数据信息进行收集、校验、存储,数据加工主要是对元数据进行解析、包装、入库等操作。

    数据存储:数据存储方面我们使用了mysql以及elasticsearch,mysql主要用来存储采集数据以及加工后的元数据信息,es主要用来做数据检索使用

3.2 功能架构

 功能组件:数据中心要面对的是数据的采集、验证、加工、入库、监控等需求,为了完成相应需求,在数据中心内部也包含了多个功能组件,主要有数据采集(Receiver)、数据检查处理器(CheckerEngine)、数据加工(Processor)、数据加工处理器(GeneratorEngine)、数据监控报警(Argos)、数据任务调度(Crane)、数据存储(Mysql&Eagle)等,具体的功能架构图如下所示:

功能架构设计.png

3.2.1 功能组件介绍

数据采集(Receiver):主要作用是数据采集处理,对业务数据进行采集、解析以及数据检查,生成任务数据以及元数据存入元数据表,且保证数据幂等性,提交数据任务等工作,其主要流程如下:

receiver流程.png

数据加工(Processor):主要作用是数据加工处理,对已提交的任务数据进行解析、校验、组装以及存储,最终对处理完成的任务进行更新,对失败任务进行监控,达到条件触发数据报警,具体流程如下:

generator流程.png

数据检查处理器(Checker Engine):在数据采集阶段,主要完成对数据字段的检查,保证数据合法性,在数据任务提交阶段,主要保证任务数据完整、保证任务状态机流转等工作

数据加工处理器(Generator Engine):主要负责数据加工的数据解析与组装,对任务元数据进行解析,对解析后的数据进行组装集成处理

数据监控报警(Argos):在数据接收异常、处理失败、加工数据不完整、丢单等情况下,当达到报警要求,会触发相关报警规则进行业务报警,便于相关人员进行快速处理

伏羲系统:伏羲为猫眼所有服务提供通用的可流程编排动态任务调度服务。比如一个订单支付流程有提交支付、支付通知、支付数据写入资金流三部操作,我们将这三个操作作为伏羲一个流程的三个节点,伏羲会顺序的帮我们调度我们要执行的节点,如果执行失败,会不断重试执行,尽可能保证任务执行成功。伏羲大体流程如下:

伏羲任务流程 (1).png

任务调度(Crane):Crane是一个高可用、可分片、支持分布式定时任务调度器。其支持5中作业类型,包括进程内、Docker、Crane-Agent、Dag和独立进程。可以更加灵活的帮助我们配置定时任务。

3.3 数据采集

3.3.1 数据检查

在数据采集阶段,会对每一条数据字段进行严格检查,保证数据写入的有效性与正确性,在检查通过后,会对采集到的数据存储到元数据表,数据检查主要流程如下:

数据检查流程.png

3.3.2数据幂等

为防止交易元数据被多次采集,造成相关数据问题,我们在数据采集阶段还加入了数据幂等性校验逻辑,对已存在数据不做处理,幂等处理流程如下:                           

幂等处理.png

3.3.3 数据任务的生成规则                  

数据中心在采集元数据的同时,会根据采集到的交易元数据生成任务,任务分类主要分为交易时订单待支付任务、已支付任务、待销费任务、已完成任务、退款任务等,在采集到不同数据时,会生成其相对应的任务,然后在利用任务调度的形式去处理加工采集的元数据。  那么如何根据元数据生成任务数据、如何根据任务表数据找到元数据,就是我们在设计之初要考虑的事,其本质还是任务表与元数据表的数据对应,当两张表数据存在一定关系时,我们可以很方便根据任务数据查找当前要处理的元数据,具体的任务生成以及两表之间的映射关系如下:                       

 (1)数据中心任务是根据业务写入数据的orderId、operationType以及unique生成,且任务有且只有一个,里边的operationType指的就是上述任务类型。

 (2)元数据信息存储也会将operationType、orderId以及unique进行存储,与任务保持一致,保证任务执行时准确捞取对应元数据信息。

数据任务与元数据信息关联.png

3.3.4 防止数据丢失与写入失败策略

  • 数据丢失
    1. 由于数据中心数据都是由业务方写入,如果某一个订单各个业务方均没有数据写入,那么数据中心是检测不到的,针对这种情况,数据中心会与外部系统进行数据比对,保证数据全部写入。
    2. 针对某一订单的某一种操作,如果写过来一条订单相关数据,则会根据该订单生成的订单任务对订单该操作流程数据进行校验, 如果校验失败,则会报警通知,以及记录到任务失败记录表。
  • 写入失败 
    1. 数据写入失败,可以对失败原因进行捕捉,增加监控报警,同时对失败业务数据进行记录、报警,防止因数据中心内部原因导致数据写入失败。

3.3.5 数据纠错或重新写入

由于各个业务方写过来的数据可能会存在误差,会导致数据记录不正确,针对这种问题,数据中心内部实现纠错机制,如果业务数据写入存在问题,可再次发起重新写入,数据中心会用新的数据将之前旧的数据进行覆盖,具体做法就是为新写入的数据单独生成新的任务来执行数据写入。

3.4 数据处理

数据处理就是对数据的解析、加工、存储等,其主要处理流程如下图所示:

数据中心任务执行流程.png

具体流程解释:

         步骤1:接收业务收据写入,对业务数据进行检查,最终生成对应的task以及mataData元数据,存入数据库表;

         步骤2:Crane定时调度任务定时扫描数据库任务表,对任务进行捞取,提交伏羲,由伏羲流程把控任务执行;

         步骤3:伏羲调度任务处理,对任务相关元数据信息,进行解析、组装,最终更新到数据库实时表;

         步骤4:伏羲调度任务处理,将实时表数据,打入快照,存入数据快照表,以保存订单历史快照数据;

         步骤5:伏羲调度任务处理,将实时表数据进行解析、组装,最终存入ElasticSearch,方便对外提供查询等服务,最终更新任务状态到已完成。

3.4.1  什么是实时表与快照表   

实时表:以订单id为唯一索引生成的,每个订单只会在实时表里边有一条数据,且随着不同任务执行实时更新,实时表的数据是最新最全的数据,像大数据等公司多个业务方在使用数据中心数据时,都是对该表进行监听。

快照表:以订单id和当前操作任务类型operationType为唯一索引,针对一个订单多个状态,会生成多条快照数据,方便我们对问题订单进行追溯,一般只保存三个月,会对历史订单定期清除。   

实时表高并发解决方案

由于实时表数据是不断被更新的,如果在高并发场景下,对同一个订单的操作极有可能造成数据覆盖或丢失的情况,针对这种情况,在实时表上我们主要做了两点处理:

① 乐观锁:在实时表里边增加版本号,实现乐观锁机制,防止数据并发更新操作

② 状态机:针对一个订单不同的状态,我们生成一个状态机模型,尽可能保证一个订单多个任务有序执行,具体的状态机模型会在下边介绍 

多条件复杂查询处理

我们收集的订单数据,字段达到100个以上,如果在数据库层面直接展开,将会是一张或多张复杂的订单关系表,不利于我们对DB的维护,且针对数据中心数据,需要从多个不同的维度进行数据查询,如果使用数据库查询,开发成本也是相当大的,且对于高qps的查询,在数据库各个字段上都需要建立索引,导致数据容量急剧增大,为了满足这种多条件查询场景,我们使用ElasticSearch进行数据检索查询处理,这样不仅减少了DB的负载,也能用尽可能少的开发量完成多条件的复杂查询

3.4.2 任务失败处理

在任务执行阶段,难免会因为各种原因导致任务执行失败,比如查询某些关键数据超时、阶段任务提交超时等,针对此类异常,我们重试一次就可能成功,所以在数据中心内部做了容错处理,对失败任务我们设置了重试策略。

任务重试策略

  1. 数据中心任务执行是有任务重试机制的,如果执行失败,不会更新任务状态,下次同样会被任务捞起执行,直到成功或者达到最大重试执行次数为止;

  2. 如果任务达到最大重试次数也没有执行成功,则会记录失败任务,汇总、统计以及报警,以便及时对失败任务进行解决,针对数据丢失导致的任务执行失败,倘若业务数据补齐,我们会重置任务重新执行。 

3.4.3.任务恢复重试机制

任务失败大多是由于业务方数据写入缺失导致,所以每次当业务数据写入时,数据中心会判断当前所采集的业务数据对应任务是否已经彻底执行失败,如果达到此状态,我们会对当前任务进行恢复重试,进而最大可能让任务执行成功。

3.5 状态机模型

由于数据中心内部任务是并发去捞取执行的,且每个订单都会根据不同的订单状态生成多个不同的子任务,在任务捞取执行时,如果不加以控制,那么可能会造成订单最终数据的一致性和部分数据丢失。因此在数据中心内部,我们也根据不同订单数据状态维护了一个状态机,用来保证任务执行的先后顺序,即下一个任务执行前,要校验前置任务有且已执行。确保数据顺序性、准确性以及数据最终一致性。

数据中心-状态机.png

3.6 业务数据总览

目前数据中心根据订单操作类型,总共有以下几种,每一种订单操作都有以下三个流程:

  • 任务写入阶段,对任务相关元数据信息进行严格检查(字段维度)
  • 任务提交阶段,对任务相关数据是否完整进行检查(各业务方数据条数),以及对前置任务状态检查
  • 任务执行阶段,对任务相关元数据进行筛选,组装,存入数据库表以及ES

数据中线任务数据 .png

3.7 数据库表设计

数据库逻辑模型图.png

数据库表含义如下:

任务表:在业务数据写入时,数据中心会针对订单不同阶段数据写入生成各个阶段的任务,比如下单、支付等任务

元数据信息表:当业务数据被采集并通过校验后,会将业务元数据信息存入该表,待后续任务执行时使用

实时数据表:各个阶段任务执行结果,均会对实时表该订单数据进行更新,实时表就是存储当前订单最新、最全数据的一张表

数据快照表:各个阶段任务执行结果,都会打成快照数据,存入快照表,快照表存储了一个订单生命周期不同状态的数据,方便我们对订单各个阶段数据回顾,针对一些问题订单也可通过此表追溯

3.8 Crane调度任务设计

3.8.1 设计背景

我们需要打造一个近实时数据收集处理系统,那么就不仅仅需要在数据收集时做到高效,在我们数据任务处理阶段,也需要快速完成,任务处理就设计到任务的捞取与提交,我们需要快速的去数据库任务表里边对未执行任务进行捞起,然后去提交到伏羲系统执行,只有这个流程够快,后续任务处理才能有保障。

数据中心目前是4库4096张表,如果单任务扫描则耗时会比较长,在春节或国庆这样的高峰流量面前,单任务扫描势必会影响数据执行速度,造成任务积压,订单数据更新速度变慢等,为了让订单任务近可能实时的完成更新,我们针对任务这块采用多服务器同时扫描来执行,从而提高任务捞取提交速度。

3.8.2 设计原理

Crane:一个任务定时调度框架,特点是可以对任务进行分片处理,比如有10台机器,我在配置任务的时候配置了20个分片,那么每个机器会分到两个分片,如果配置了10个分片,那么每个机器将拿到一个分片,如果配置了5个分片,那么有5台机器不会分配到分片。

实现原理:在任务调度上,我们灵活运用了Crane的分片设计,数据中心机器数是40台,我们在任务配置上配置了20个分片,那么每次任务执行时,会有20台机器获取到分片,我们会让这些获取到分片的机器去执行任务;

eg:  机器1获取到分片1,那么他将捞取任务表1,表21,表31的任务去执行;

       机器2获取到分片3,那么他将捞取任务表3,表23,表33的任务去执行;

       机器3获取到分片2,那么他将捞取任务表2,表22,表32的任务去执行;

       每个任务每次会捞取每张表的100条数据;

下图为任务调度模型:   基本分库分表.png

3.8.3 任务调度流程

任务调度的主要作用就是将任务从数据库捞取出来,提交到伏羲平台,而后由伏羲平台来帮助管理任务具体执行流程。

任务提交流程.png

3.8.4 任务提交幂等处理

Crane定时任务扫描,在一个扫描周期内,如果说我当前任务在上个扫描周期已经提交,但是还没有执行完,正常情况下这个任务还有可能会被再次捞取提交,这样就导致了任务重复提交执行。因此在任务捞取调度阶段,会对提交的任务添加分布式锁,根据操作类型(operationType)以及订单号(orderId),如若任务提交失败,则会主动释放掉锁,如果提交成功,则等待伏羲调度任务执行完成会释放掉锁,否则60min以后锁自动释放。

3.8.5 分片数量衡量

从我们上边的介绍来说,如果我分片越多,机器越多,那么任务执行的效率也会不断提高,但是我们要结合实际场景,考虑整个服务其他接口的新能以及db的性能,还有我们提交任务到伏羲系统,也要考虑伏羲系统的性能,所以不能随意的进行分片与机器的扩张,我们主要考虑到以下两个方面来权衡我们分片数据:

  1. 考虑到对数据库的压力,如果我们设置40个分片,每次sql读取100条数据,对同一个库每次读取的量就是 40*100=4000条,假设一秒读库5次,那么qps将达到20000,这样对数据压力可能会存在性能问题了;

  2. 考虑到对伏羲的压力,同样的,每秒qps将在2w左右,对伏羲的性能也有很大的考验;

3.9.Engine实现原理

3.9.1 Checker Engine

Checker Engine 处理器:主要是在数据写入时对数据进行合法校验以及在任务执行时保证采集数据就绪以及状态机流转。由于中台交易数据是根据订单状态的不同分多个阶段来写入的,每个阶段都会有不同的数据,针对每个阶段的数据校验策略也都是不一样的,为了方便统一管理这样的多个校验策略,Checker Engine模型采用策略模式去处理,具体的模型图如下:

Checker.png

不同的检查策略针对的是不同的数据,比如SubmitChecker针对的是待支付订单时的数据检查,CancelChecker针对的是取消订单数据检查等。

3.9.2 Generator Engine

Generator Engine 处理器:主要使用在任务执行阶段,在任务执行期间,会将任务关联的元数据从元数据表查询出来,再对数据进行组装加工处理,将多条分散的订单元数据加工成一条完整的订单数据,此处也同Checker处理器一样,使用了策略模式。

Generator.png

类似Checker Engine模型,SubmitGenerator是用来处理订单待支付阶段元数据,PayGenerator是用来处理订单已支付阶段元数据等。

3.10 数据中心监控报警机制

数据中心报警机制是针对数据做的一套监控规则,当订单不符合规则时,就会触发报警,报警规则对数据敏感的系统来说,是必不可少的,通过报警机制我们可以快速发现订单数据问题且快速处理,避免因数据问题对公司业务造成不便。

我们的报警机制从数据、任务、数据库等多个层面做了监控,主要针对数据任务执行失败、数据字段非法,加工后数据不完整以及与数据源数据一致性等方面做了监控,进而通过监控快速去发现并解决问题,在后续的规划中,会将监控检测出来的数据问题进行数据自动修复处理,尽可能降低人为干预成本。下图主要是数据任务执行失败模型,在任务执行失败时,会分析出任务执行失败的原因并及时报警,对每天的失败任务会进行邮件汇总,发送给相关负责人处理。

数据中心报警处理流程图.png

四. 数据中心未来规划

4.1 技术升级

  • 尽最大可能减少对业务依赖,做到核心数据写入,绝大部分数据自取的一个目的
  • 挑战更高的性能问题,做到更高级别的qps写入,做到更快速的数据处理,做大更大量级的数据存储
  • 完成对数据中心内部业务扩展的配置化,做到业务接入零开发的状态
  • 完善对数据的监控措施,做到数据失败自动修复补偿的目标,降低人为干预数据处理的场景

4.2 业务扩展规划

数据中心目前已经接入了多个业务的交易数据,但是还有部分业务还没有进行接入,后续会持续将各个业务交易数据接入,同时针对后期新的业务,也会是一个不断接入的状态,我们的目标就是猫眼所有业务交易数据全部收集于此,我们期望将数据中心打造成为猫眼交易业务的数据天堂。

数据中心未来规划.png

4.3 数据应用规划

  • 数据中心数据应用于统一对账、统一结算以及EBS三个业务。
  • 数据中心数据已经实现可视化页面展示,提供相关订单数据查询功能。
  • 后续数据会为大数据、风控等更多团队等提供数据服务。
  • 数据中心数据应用于交易中台内部实时大盘,提供可视化的数据大盘服务。

数据中心未来规划方向.png

猜你喜欢

转载自juejin.im/post/7085561268035125261