百度交易中台之内容分润结算系统架构浅析

在这里插入图片描述

作者 | 交易中台团队

导读

随着公司内容生态的蓬勃发展,内容产出方和流量提供方最关注的“收益结算”的工作,也就成为重中之重。本文基于内容分润结算业务为入口,介绍了实现过程中的重难点,比如千万级和百万级数据量下的技术选型和最终实现,满足了业务需求的同时,最终实现了高效,准确的资金结算,文章旨在抛砖引玉,希望能给读者带来思考和帮助。

全文5185字,预计阅读时间13分钟。

01 业务介绍

什么是内容分润平台呢?简单来说,百家号等平台负责内容的生产和引入,手百等渠道方负责内容的分发,凤巢等广告平台负责在此流量上进行变现。而分润平台,则是根据上述各方提供的数据,通过核心策略模型,赋予作者、媒体、小程序主和用户,合理的、差异化的、有竞争力的分润收益,以吸引更加优质的内容和流量的入驻和合作。通过这种多方相互协作模式,实现互惠共赢的目的。

1.1 三大功能点

针对上述的业务特点,结算系统需要包含三大功能,用于支撑内容分润业务的准确性、合规性、及时性。

功能一:结算模型

这是我们最关键的功能,它负责将出色的文章转化为作者的分润收益。该模型的输入数据包括数据中台生成的用户维度的日分润明细和日补贴明细,而输出则是每月的结算账单,这些账单会被发送到统一业务平台用于付款。在这个过程中,我们经历了一系列步骤,包括每日的计算、每月的总结、预提、计提和账单生成等,所有这些步骤都是按照不同的维度逐层计算和聚合的,最终实现了账单的付款。

功能二:C端内容交易平台

这个功能主要面向用户,旨在帮助作者及时查看他们的收益,并进一步激励他们的创作动力。作者只需登录平台,即可查看每日的预估收益、文章的分发情况、浏览量等数据,还可以查看每月实际的付款账单,提供发票等相关数据。

功能三:O端管理端平台

为了确保资金结算更加合规和准确,整个结算体系引入了运营管理和反作弊等不同角色。这些角色在管理端负责资金管控、发票审核、黑名单管理等各种操作,以确保整个过程的合规性。

1.2 名词解释

PALO:百度数据仓库,是基于开源ApacheDoris构建的企业级MPP云数据仓库,可有效地支持在线实时数据分析。

BNS(Baidu Naming Service):是指百度名字服务。BNS提供服务名称或服务组名称到服务所有运行实例的映射,你可以根据一个名字(服务名或服务组) 获取服务的信息,包括实例的主机名和IP、实例的运行状态、端口、负载、实例自定义配置标签以及其他实例自定义信息。用于满足服务交互中常见的资源定位、IP白名单维护、查询服务下的机器列表、负载均衡以及其他任何依赖于这些信息的开发、测试和运维需求。目前BNS已经在全百度各业务线中广泛使用,UB、RAL等框架的支持和各语言SDK也已经发布。

02 业务架构

2.1 架构分层介绍

图1是整个内容分润的业务架构。内容分润结算面向数据中台,业务方,用户(作者)和运营管理提供服务。

图片

△图1.内容分润结算平台系统架构

2.2 关键汇总文件

对于数据中台,我们是直接下游,同时在整个内容分润流程的流程中,我们扮演的是最末端的角色。百家号、问一问、百度文库等业务会将作者的内容分发数据、广告贡献等给到数据中台,数据中台按照各种分润计算模型归一化数据结构,产出三份较为详细的明细文件,包括日分润明细,日内容分发明细,日补贴明细。

日分润明细:作者内容分发或流量贡献所获得的分润详情,明细中包括分润金额,文章分发渠道,父子账号等字段。

日补贴明细:基于运管管理的二次资金分配详情。

日内容分发明细:作者的内容分发贡献报表。

数据中台会将这些数据以离线文件的形式提供给我们,结算系统每日基于配置规则,进行离线计算,最终将数据进行降维汇总。后续每月月初,基于这些汇总数据,做二次汇聚产出用户收益账单。

2.3 服务提供方式

结算系统根据外部需求,提供多种接入方式。面对业务方,结算系统提供API、网页嵌入模式接入方式。若业务有其自建平台,可将结算系统提供的网页嵌入其平台内部,用于展示用户的收入信息或上传发票等。若无自建平台,也可API形式接入。新用户在业务侧申请入驻作者后,业务调用结算系统API完成用户注册,开通计费单元,维护财务信息等。后续作者在内容分润平台查看其收入,文章分发报表,重新维护财务信息等。若有重要变更或通知,系统通过站内信方式通知作者。

系统整体支持三种账号体系,面向作者提供两类百度常用账号登录方式,面向管理端提供内网账号登录方式,基于此账户体系做了灵活权限控制,不同用户登录管理端,看到的可操作菜单栏各不相同,避免出现越权操作。同时基于此账号体系,能灵活获取上下级,构建了自动化的审批流程。

结算系统的平稳、合规、高效运行离不开各类协同生态的合力支持。反作弊能力贯穿整个内容分润的始终,着力于打击黑产,识别作弊用户。OCR、发票平台为发票识别,发票鉴定提供了通用服务。财务的各类审核,业务的多维度监管则进一步为资金结算的合规安全保驾护航。各类角色、各个系统协同合作,促成了目前内容分润结算系统。

03 技术难点和细节

上文以整体的视角介绍了内容分润结算系统的架构设计,下面我们将枚举几种业务场景构建过程中的技术选型,来详细介绍该系统的技术落地。

3.1 千万级数据日度任务的技术选型

场景:每日上游会给我们产出明细数据,数据为细粒度,量级为大几千万级别,格式为AFS文件(离线文件),需要基于某些过滤规则和计算规则做二次汇聚,后续支持多维度查询,作者端展示报表。

3.1.1 DB批处理方案

最初任务是在物理机上通过sql批处理,任务串行执行,简单明了,同时成功同时失败。但随着数据量持续递增,串行执行可能面临着实效性问题。基于原始的DB思路,我们构建了基于DDBS(关系型分布式数据库系统)的解决方案,全部依赖于DB,因汇聚是基于用户维度,所以基于子账号uid计算shardingKey分表,过滤规则也落入库中,后续使用表之间连接过滤,相同分表中的同子用户数据汇聚。使用在线服务,按照分表规则,启动多线程执行任务,实时写入日汇总数据表。具体方案如图2。

图片

△图2.基于DDBS的解决方案

3.1.2 离线计算

利用SPARK天然的分布式计算能力,采用离线计算方案,汇聚时使用SPARK计算。基于上游提供的离线文件,构建RDD1文件,后续基于一些过滤规则过滤数据和然后基于集合规则,使用reduceBykey聚合,产出新的RDD2文件。这个RDD2文件就是我们后续使用的日表数据。因有各类在线查询需求,需持久化到数据库中,又因产出的日表需支持各角色多维度查询,调研后采用PALO数据仓库,具体方案如图3所示。

图片

△图3.基于SPARK+PALO+DB解决方案

对比两种方案后,我们最终选择方案二实施。方案二的优点比较突出:1.SPARK集群自带分布式计算能力,无需我们按照方案一方式自行实现分布式计算;2.数据存储于PALO,相比于传统的MYSQL,在大批量数据和多维度报表场景,PALO性能优势更加明显。3.方案一有一个最大也是我们最踩坑的性能问题,实时大批量写入DDBS数据库导致较高的主从延迟,影响了其他业务场景。

3.2 百万级数据的月度任务

场景:基于上述场景会产出月表,数据量大约在百万级别,遵循月度出账计算模型,产出最终的预提数据。日度任务和月度任务的最主要区别在于日度任务计算过程密集,月度任务过滤过程密集。

月度产出计提任务实际就是计算用户本月收入以及本月可结算的收入,可结算收入=以前累积未结算金额+本月收入。目前该任务输入的数据量相对较少,且以过滤为核心,因此此类任务未采用SPARK计算。而各类过滤规则与当前用户各种属性息息相关,因此任务围绕用户uid展开,采用以用户uid为底表,先通过各类策略过滤uid,后置再计算的方案。数据量虽然相对日度任务较少,但毕竟在百万级别,如果使用单一线程处理所有用户,速度会极其缓慢,所以必须拆分任务,使用并行计算的方式提升效率,而如何拆分任务,如何保障任务全部执行是月度任务模型需要考虑的核心问题。

3.2.1 幂等的分布式数据批处理框架master节点

我们设计了主从任务模型,用于支持上述任务拆分执行,主结点先置启动,用于数据备份、初始化出账任务,以及调度从节点。从结点则等待主结点启动子任务指令,启动后获取子任务执行。具体模型如下图4,5所示。

图片

△图4.主节点生命周期

图5描述了主节点的生命周期,主节点收到出账指令后,优先做的是账户余额类表的数据备份,这个动作归因于我们月度任务的特殊性,月度任务产出的数据表在其他时间不会更新,即上个月出账结束后,账户余额类的相关表会在下一次出账完毕才更新。

备份表的环节非常重要:

1.是可以在月度任务结束后做数据总额验证工作;

2.是可以用于兜底,一旦月度任务产出数据异常,也可回退到备份数据,重新启动任务。

主节点任务的第二步则是确认出账任务的用户uid范围,我们系统为了既支持C端用户体系,也支持商家账号体系,重新设计了一套内部用户id,不论是用户账号还是商家账号的id均会唯一映射成一个内部uid,后文提到的该任务的uid均为内部uid。内部uid为自增id,因此查询数据库,即可获取到最大uid和最小uid,也就确定了我们本次任务的uid范围。在redis中设置两个key代表uid的最值。至此,出账任务的前置准备工作就完成了。主节点获取执行子任务配置的BNS,基于BNS解析出所有实例,发送子出账任务指令,子实例获取到指令后,启动N个线程执行任务,即假设有M个子实例,那最终就是M*N个线程同时执行任务。从主节点的任务可看出,该任务无其特殊性,即主节点实际和从结点是平等关系,任何实例都可成为主,也可成为从,这就为调度任务进一步提高了灵活性。

3.2.2 woker节点的任务流程

图片

△图5.从节点生命周期

图5以上述实例中的一个线程作为示例,详细描述了线程启动后,执行的子任务的过程。首先获取目前的最大uid和最小uid,最大uid为主节点固定值,最小uid则是一个游标。若最小uid已经大于最大uid,则代表所有uid已经处理完毕,线程结束。若不满足上述条件,则继续执行任务,利用redis的incryBy指令,将最小uid向前移动N个数值,这N个uid就是本次子任务的执行范围。拿到uid后,先将uid变为N条任务批量落入Job表,并设置初始化状态。落库失败,引入报警机制。落库成功后,按照出账模型,启动过滤规则。所有被过滤的用户uid均批量写入job表,设置任务结束状态,并且标记过滤原因,便于后续运营查询。过滤规则执行完毕,剩余uid十不存一,此时我们利用sql计算本月用户结算金额。计算完毕,写入jobDB的临时产出表,设置job任务完结态,此时一轮子任务就执行完毕。线程继续重复执行上述过程,直至所有线程均结束,代表出账任务执行完毕。

3.2.3 出账确认任务

所有任务执行完毕后,主节点会收到出账任务确认指令。

图片

△图6.出账确认任务

该任务的主要目的就是确认所有uid均执行完毕,无疏漏,具体如图6所示。上文提到,子任务执行时,都是先置落库job表的,确认任务的第一步:扫描job表,看是否有非完结态的任务,若有,则启动子任务,重新执行这批数据。确认任务第二步:获取job表中所有执行的uid数量和需要执行任务的uid数量,确认数量是否一致,若不一致,重新执行出账任务,任务基于uid和业务期间重入,已经被执行的任务会被跳过。多次兜底策略执行完毕后,数据总量校验一致后,会将临时月度产出数据写入正式DB,清理临时数据。之所以设置临时表:1.是为了数据校验工作,若数据校验异常,可快速清理该表,重新启动任务;2.若直接写入正式线上库,大量数据的并发写入会导致数据库的主从延迟,会影响其他线上实时业务场景。后置写入实现了另类的『读写分离』,任务过程中仅读正式表,任务完毕临时表往正式表写入数据。

04 总结

本文主要介绍了在构建结算系统过程中的几个技术重点和难点,而要维护整套系统的平稳运行,不仅有这些技术重点,也有看似微不足道但却环环相扣的细枝末节,保障每个环节不掉链子是运维工作的重要一环,后续我们将着力于提升运维效率,节省人力成本,向着运维自动化、智能化改造。另外目前的技术方案取决于我们的数据量级,未来业务蓬勃发展,业务架构也会持续迭代,期待我们向着更加完备的架构前进。

——END——

推荐阅读

小程序编译器性能优化之路

百度APP iOS端包体积50M优化实践(六)无用方法清理

基于异常上线场景的实时拦截与问题分发策略

极致优化 SSD 并行读调度

AI文本创作在百度App发文的实践

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/92261.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用Java打印长方形、平行四边形 、三角形、菱形、空心菱形

今天复习使用嵌套for来完成一些任务,于是想着打印一些图形来练习 思考感悟 长方形 行数 和 每行的星星数嵌套遍历即可 平行四边形 核心:每行空格数总行数-行数 行数空格数132231 三角形 核心:每行星星数2*当前行数-1 行数星星数1123…

【VIM】VIm-plug插件

如何查找需要的插件 https://github.com/mhinz/vim-startify https://github.com/vim-airline/vim-airline https://github.com/Yggdroot/indentLine github.com/w0ng/vim-hybrid github.com/altercationi/vim-colors-solarized guithub.com/morhetz/gruvbox github.com/sc…

kotlin aes 加密解密

文章目录 1. key填充2. 加密3. 解密 1. key填充 aes算法对key的字节数有要求 所以对输入的key要做填充处理 fun fillKey(key: String): ByteArray {val random SecureRandom.getInstance("SHA1PRNG")random.setSeed(key.toByteArray())val generator KeyGenerato…

【2023保研】双非上岸东南网安

个人情况 学校:henu 专业:信息安全 排名:1/66 英语:六级500 竞赛:蓝桥杯PB国一,ISCC国一,密码数学挑战赛国三,还有其他一些省级水奖 论文:一篇EI在投(三作通…

C++:红黑树

目录 一、关于红黑树 1、红黑树和AVL树区别 2、红黑树规则 二、红黑树 1、红黑树变色举例 2、红黑树具体情况分析 ①、情况一:只变色 ②、情况二:单旋 变色 ③、情况三:双旋 变色 三、红黑树的模拟实现 一、关于红黑树 1、红黑树…

王道考研计算机网络——传输层

一、传输层概述 复用:发送方不同的应用进程都可以使用同一个传输层的协议来传送数据 分用:接收方的传输层在去除报文段的首部之后能把数据交给正确的应用进程 熟知端口号就是知名端口号0-1023 客户端使用的端口号是动态变化的,不是唯一确定…

某房产网站登录RSA加密分析

文章目录 1. 写在前面2. 抓包分析3. 扣加密代码4. 还原加密 1. 写在前面 今天是国庆节,首先祝福看到这篇文章的每一个人节日快乐!假期会老的这些天一直在忙事情跟日常带娃,抽不出一点时间来写东西。夜深了、娃也睡了。最近湖南开始降温了&…

Unity Urp无线延申的网格效果

无线延申的网格 该项目必须是再Urp项目 shader代码实现 Shader "Unlit/infTutorial1" {Properties{_Alpha ("Alpha", Range(0, 0.5)) 0.5}SubShader{Tags{"RenderPipeline""UniversalRenderPipeline""RenderType""…

Pikachu靶场——PHP反序列化漏洞

文章目录 1. PHP反序列化1.1 反序列化代码审计1.2 漏洞防御 1. PHP反序列化 可参考我写的另一篇博客:反序列化漏洞及漏洞复现。 序列化serialize() 序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象: class S{publi…

【MySQL】初识数据库

目录 ♫什么是数据库 ♫数据库的分类 ♪关系型数据库 ♪非关系型数据库 ♫显示已有的数据库 ♫创建数据库 ♫删除数据库 ♫使用数据库 ♫数据类型 ♪数值类型 ♪字符串类型 ♪日期类型 ♫创建表 ♫查看表 ♪查看当前数据库下所以表: ♪查看指定表结构&#x…

java多线程相关介绍

1. 线程的创建和启动 在 Java 中创建线程有两种方式。一种是继承 Thread 类并重写其中的 run() 方法,另一种是实现 Runnable 接口并重写其中的 run() 方法。创建完线程对象后,调用 start() 方法可以启动线程。 2. 线程的状态 Java 的线程在不同阶段会处于…

SimpleCG动画示例--汉诺塔动画演示

前言 SimpleCG的使用方法在前面已经介绍了许多,有兴趣的同学如果有去动手,制作一些简单动画应该没多大问题的。所以这次我们来演示一下简单动画。我们刚学习C语言的递归函数时,有一个经典例子相信很多同学都写过,那就是汉诺塔。那…

hadoop生态现状、介绍、部署

一、引出hadoop 1、hadoop的高薪现状 各招聘平台都有许多hadoop高薪职位,可以看看职位所需求的技能 ----> hadoop是什么,为什么会这么高薪?引出大数据,大数据时代,大数据与云计算 2、大数据时代的介绍 大数据的故事…

buuctf-[WUSTCTF2020]CV Maker

打开环境 随便登录注册一下 进入到了profile.php 其他没有什么页面&#xff0c;只能更换头像上传文件&#xff0c;所以猜测是文件上传漏洞 上传一句话木马看看 <?php eval($_POST[a]);?>回显 搜索一下 添加文件头GIF89a。上传php文件 查看页面源代码&#xff0c;看…

【分布式云储存】Springboot微服务接入MinIO实现文件服务

文章目录 前言技术回顾准备工作申请accessKey\secretKey创建数据存储桶公共资源直接访问测试 接入springboot实现文件服务依赖引入配置文件MinIO配置MinIO工具类 OkHttpSSLSocketClient兼容ssl静态资源预览解决方案资源上传预览测试测试结果 前言 上篇博客我们介绍了分布式云存…

Unity之Hololens如何升级MRTK内置shader支持URP

一.前言 什么是Hololens? Hololens是由微软开发的一款混合现实头戴式设备,它将虚拟内容与现实世界相结合,为用户提供了沉浸式的AR体验。Hololens通过内置的传感器和摄像头,能够感知用户的环境,并在用户的视野中显示虚拟对象。这使得用户可以与虚拟内容进行互动,将数字信…

php时间选择器插件与安全过滤参数发生空格冲突

php参数过滤时&#xff0c;将“ ”作为隐患予以禁止&#xff0c;但是在时间传递时&#xff0c;如2023-09-30 10:00:00作为变量传递时&#xff0c;被禁止。 php安全参数过滤 function safe_replace($str) {$disallow_str array(%27, %2527, *, ", "", ;, <…

Qt Creator 预览界面 快捷键

一般来说&#xff0c;我们运行Qt程序所花费的时间是比较长的&#xff0c;那有时我们只改变了界面&#xff0c;那么此时花费如此长的时间去运行程序来观察界面改动的效果是非常浪费时间的行为。 此时我们可以选择预览界面来观察界面改动后的效果&#xff1a;

Java性能调优必备知识学习路线

性能调优是Java开发中一个非常重要的环节&#xff0c;它可以帮助我们提高系统的性能、稳定性、可靠性和用户体验&#xff0c;从而提高用户体验和企业竞争力。 目录 一、为什么要学习Java性能调优&#xff1f; 二、如何做好性能调优&#xff1f; 2.1 扎实的计算机基础 2.2 …

通过Nginx重新认识HTTP错误码

文章目录 概要一、HTTP错误码1.1、1xx1.2、2xx1.3、3xx1.4、4xx1.5、5xx 二、Nginx对常见错误处理三、参考资料 概要 在web开发过程中&#xff0c;通过HTTP错误码快速定位问题是一个非常重要的技能&#xff0c;同时Nginx是非常常用的一个实现HTTP协议的服务&#xff0c;因此本…