百度交易中台之账房系统架构浅析

点击上方“服务端思维”,选择“设为星标”

回复”669“获取独家整理的精选资料集

回复”加群“加入全国服务端高端社群「后端圈」

3e369c27bb5baa1ddd5e03e8580134f0.png

作者 | 百度交易团队

出品 | 百度Geek说

导读:百度交易中台作为集团移动生态战略的基础设施,面向收银交易与清分结算场景,为赋能业务提供高效交易生态搭建。目前支持百度体系内多个产品线,主要包含:小程序,地图打车,百家号,招财猫,好看视频等。本文主要介绍了百度交易中台的商户财务对账相关的帐房系统,主要从业务模型以及系统设计来介绍该系统。


一、系统介绍

帐房系统是建立在百度交易系统[1]下,收拢聚合了商家/平台/宿主等接入方的收入/支出流水的对账系统。商家通过该系统可直接看到自己的收入/其他款项/支出等流水信息,实现按天/月/年的财务对账。

二、业务场景

针对不同业务背景,交易清结算系统产生了不同的流水类型。目前主流的业务场景包含:1.直播带货等场景下的流量主带货[2]。2.小程序宿主内的宿主带货。3.地图打车等业务场景下的平台分帐。

255a9f3b65f0781a599d960893310ec0.png

图(2-1) 交易中台业务背景

这些业务场景下,交易流水产生的过程如图(2-2)所示。一个订单经过支付、支付通知(购物车拆子订单)、订单维度结算、结算流水推送商家资金池,最后资金池流水才会到帐房系统,交易流水产生在图(2-2)中的商家订单结算过程中,一个订单会产出多条交易流水,推送到下游资金池系统进行商家账户记账,同时产生了对应的资金池流水,帐房系统的数据来源就是资金池的流水记录。目前商家结算产出流水类型有以下几种:

100ec2085082db8b9ed8531866e5ef10.png

图(2-2) 交易流水产生流程

  1. 分帐流水(货款):对于入驻交易的平台方,平台方为商家提供了平台上的功能,平台方期望从商家售卖的货款中收取一定的佣金,作为平台的收入。基于这种业务场景,产生了平台的分帐流水。对应图(2-2)商家结算中的分帐方式产出,分帐方式包含:按照固定比例,按照固定金额,自主比例分帐以及多方分帐,接入方根据实际的业务场景选择对应的分帐方式。

  2. 技术服务费:技术服务费为交易中台(网讯主体)对使用收银台支付的商家,会收取一定比例的钱作为技术服务费,因此产生了对应的技术服务费流水,对应图(2-2)商家结算中的分帐方式的佣金模式产出,佣金模式包含:固定比例、固定金额以及按照渠道收取。对应商家的其他款项数据。

  3. 小程序带货流水:小程序带货流水为流量主收取的带货佣金,流量主为商家通过文章、视频、直播带货后,卖出的货款会分一部分给带货的流量主,从而产生了小程序带货流水。与分帐流水不同的时,分帐的流水是给入驻的平台,而带货流水最后的结算对象是个人。

  4. 宿主带货流水:业务背景是智能小程序开源联盟,为宿主和小程序共建生态。宿主为小程序提供分发流量及展现入口,有效提升小程序的使用时长及频次,基于此,宿主产生对在其APP上发生的交易进行抽佣的诉求,从而实现宿主新商业变现模式拓展,带动宿主商业收入增长。 宿主带货流水的产生方式与小程序带货类似,区别是宿主在交易进行和入驻,属于企业/公司类型。一个商家属于一个平台,也可以和宿主进行绑定,与二者同时进行分账。

  5. 打款流水:打款流水为给商家银行卡打款的流水。

  6. 调整款流水:指打款银行退汇的流水。

帐房系统将以上的流水划分为3个类别:收入、支出以及其他款项。

  • 收入:指分帐流水

  • 其他款项:包含交易中台收取的技术服务费、打款退回的流水、小程序带货流水以及宿主带货流水

  • 支出:指打款流水

商家整体财务数据核对收支平衡的公式为: 

总体对账公式:商家余额 = 收入 + 其他款项 - 支出

若公式成立则收支流水数据准确无误。若商家想要核对账期内的财务数据,则需要看两个账期之间的收入和支出是否一致。例如商家每隔7日进行一次打款(即是支出),则商家只需要核对这7天内的流水数据是否满足以下公式即可。

结算账期对账公式:收入 + 其他款项 - 支出= 0


例子说明

交易中台所支持的业务场景中,一个订单会产生多条流水,每一条流水的结算对象也不一样,因此,这里举例简单说明流水属于的对象。

例子:针对小程序带货的场景,一个订单金额为100元,带货流量主分佣10%,平台分帐5%,交易中台收取6‰技术服务费。因此各个对象的流水金额如下:

5354f3a79d3ec78ada520ac7867e0356.png

从表中可以看出最后的总金额只有84.4+10+5=99.4元,缺少的0.6元就是交易中台收取的技术服务费。技术服务费的收取是通过从商家口扣除0.6元实现的,而不是产生0.6元的流水给交易中台。如果打款周期到了,对应给结算对象的打款金额就分别为84.4元,10元和5元,这样收入和支出就一致了。

三、系统构架

e18c6cc48f57c0493c93ee86852bf484.png

图(3-1) 帐房系统架构图

帐房的整体架构如图3-1所示,帐房的数据来源为上游的资金池流水数据,canal监听binlog,解析binlog日志将流水数据发布到bigpipe,帐房系统通过监听bigpipe数据,拿到流水数据后通过akka完成数据的校验、补充,得到一条完备的流水数据。最后通过esClient将流水数据写入百度云es,业务的查询以及导出功能都是基于百度云es的数据来完成的。与此同时,交易中台也建立了离线计算系统,通过spark拉取es的集群数据,存储在AFS上,基于此完成离线数据统计的功能。 帐房系统以资金池流水数据为主,根据流水类型的不同,补充了来自其他不同系统的数据,丰富该条流水的信息,来满足业务侧查询的需求,补充的数据存储在es以及数据库中,针对热点的数据,系统使用LoadingCache本地缓存的方式提升处理速度。系统对外输出数据的方式有:第三方API、电商开放平台、财务运营平台、业务商家后台以及AMIS发票系统。

四、系统功能拆解

4.1 基于canal的数据同步

帐房系统的数据来源为上游账户资金池系统的流水数据,资金池流水数据存储在ddbs数据库中。帐房需要实现准实时数据的获取,同时避免代码的侵入,因此采用了基于cacal监听ddbs数据库binlog日志的方式,进行数据的同步;由于每日的流水产生存在流量高峰,直接将数据请求下游帐房系统,可能会对帐房系统产生冲击,引起系统异常的问题。为了避免这种情况的出现,我们引入了中间件消息队列(bigpipe)进行流量削峰填谷处理,canal将解析的库表变更数据发送到消息队列中,帐房系统采用监听者模式从消息队列中获取对应的数据,通过java的akka方式进行并发的数据处理。帐房系统通过异步消息以及akka并发的方式完成数据的异步化同步,解决流量高峰问题,实现了数据的准实时同步,当前系统的数据同步延时控制在秒级别。

4.2 Elasticsearch数据存储

帐房系统业务需求为商家/用户对账需求,主要是为了满足商家/用户对于财务相关的对账数据的查询以及导出。基于这样的特点,需要查询大量的数据,同时需要完成各个维度的数据聚合,而且商家的流水数据量远大于订单的数据量,一个订单将会产生2-6条的流水。交易订单中心以及上游账户资金池系统的存储都是采用数据库分度分表的方式进行的,这样的方式并不适用于帐房系统,引入分表的方式会导致数据不均匀的情况产生,对于热点账户的问题难以解决,同时难以完成多维度的数据查询。基于此系统采用了es的存储方式,通过es支持对外的多维度、准实时的数据查询。

帐房系统早期的数据写入时自定义了routing,使用商家id作为routing,随着业务发展,热点商户的数据量不断增加,从而导致es分片出现了数据倾斜的情况,进而会引发es聚合查询偶发超时以及偶现写入失败的情况。因此系统进行了es数据迁移,从而解决数据倾斜的问题。同时Elasticsearch 使用一种称为倒排索引的结构,它适用于快速的全文搜索,因此es对于字段的变更修改无法直接在原来的索引上进行,都是重建索引,进行数据的迁移完成的。es数据的迁移方式有很多(BOS快照迁移、Logstash、通过Spark迁移数据、HDFS快照迁移等),鉴于交易侧es数据量以及迁移的场景,使用了Logstash同步的方式进行了数据的迁移,迁移过程中将文档的routing设置去除,解决了数据倾斜的数据。

4.3 数据一致性保障

帐房系统其主要功能为商家的对账,因此商家的流水数据的缺失必然会导致商家财务数据的错误,给商家带来对账上的问题。因此保障帐房的数据与上游系统一致,是该系统重要且必须的能力。数据一致性的保障,帐房系统通过接入交易平台的一致性服务系统完成,其流程如图4-1所示。

2e4efd31bca169e09fdbd64c911887c1.png

图(4-1) 数据一致性保障流程图

一致性服务通过接收来自上游canal发送的bp消息,以及帐房系统写入es成功后发送的bp消息,将二者的消息存储至mysql数据库中,每日定时对上下游系统的数据进行对比分析,得出对应的差异数据,然后通过调用对应的修复接口完成数据的修复。一致性服务留存了7日内的消息数据,过期定时清理,保证服务的数据量不会过大,不影响数据库性能。除了一致性服务的保障之外,每月会通过spark进行离线数据核对,确保当月的数据上下游一致。

4.4 数据聚合

115b25f64fa2a1cb1615713197a6be02.png

图(4-2)商家对账页面

商家对账的页面如图4-2所示,可以看出,对于帐房系统的要求是需要按照商家维度查询对应的财务数据,同时需要按照月份进行聚合,返回商家每一个月的收入/支出金额。在使用es进行聚合查询时,需要关注以下信息,保障查询的效率。

聚合查询字段,设置为keyword,能够提升查询的效率。(当前系统数据量下,查询时间差异在2倍左右。)

es查询时must和filter的使用,must 返回的文档必须满足must子句的条件,并且参与计算分值;filter 返回的文档必须满足filter子句的条件。但是跟must不一样的是,不会计算分值, 并且可以使用缓存。简单来讲,filter查询效率高于must,根据自己的实际业务场景选择合适的查询语句,在不需要相关性算分的查询场景,尽量使用filter context让查询更高效。(当前系统数据量下,查询时间差异在2-4倍左右。)

ES中的路由(routing)机制决定一个document存储到索引的哪个shard上面去,即文档到shard的路由。计算公式为:shard_num = hash(_routing) % num_primary_shards。一般情况下,不建议使用写入时设置routing,如果routing设置的不合理,会导致数据倾斜的问题,数据倾斜会导致查询问题以及集群不稳定。若能够保证设置的routing分布均匀,且使用routing作为数据隔离方式,在这样的情况下,后面检索的时候,同样使用隔离参数作为routing,就可以精准的从某个shard获取数据了,提升查询的效率。早期帐房系统使用商户ID作为routing,在一定程度上提升了查询的效率,但是随着业务的增加,出现了热点商户的问题,导致了es数据倾斜问题,从而引起了一些问题,后续进行了数据的迁移,不再使用资金池id作为routing,而是使用系统默认的文档id作为routing。

es深分页问题,es分页查询有三种方式:1.form size 。2.scroll方式。3.search after方式。这里简单做一下对比,查询速度上scroll>search after>form size。帐房系统设计中三种查询方式均有使用,适用于不同的场景,form size方式用于前端页面上的展示,仅仅展示少量的分页数据;scroll查询方式用于大量数据的文件导致任务,快速完成文件的导出任务;search after方式用于对外的API批量数据导出,业务侧可重复获取某一页数据进行处理。

9704a3a64e5cc26c8c3b9d3436b24c86.png

五、结束语

基于当前交易中台所支撑的业务场景,建立了如上的帐房系统,我们也在不断的进行完善和升级,助力上游的业务不断的前进,提升商家的对账体验。随着业务的不断发展,帐房系统也在不断的进行升级改造,不断地完善自身。后续我们将持续升级系统,与业务共同发展成长。

— 本文结束 —

bc9d115758c7174ddb59fd087fedfa21.gif

● 漫谈设计模式在 Spring 框架中的良好实践

● 颠覆微服务认知:深入思考微服务的七个主流观点

● 人人都是 API 设计者

● 一文讲透微服务下如何保证事务的一致性

● 要黑盒测试微服务内部服务间调用,我该如何实现?

89dee0be16f8cb1f87d7db0912a7ceda.png

关注我,回复 「加群」 加入各种主题讨论群。

对「服务端思维」有期待,请在文末点个在看

喜欢这篇文章,欢迎转发、分享朋友圈

a418d393172e12f537b97dcf092daad8.png

在看点这里

6f539a56e99e2f51ccba83a130e3e5ba.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值