Apache Paimon 在抖音集团多场景中的优化实践

news2025/3/22 22:39:37

资料来源:火山引擎-开发者社区

本文将基于抖音集团内部两大业务的典型实时数仓场景,介绍Paimon在抖音集团内部的生产实践。


作者:李明、苏兴、文杰
抖音集团大数据工程师



目前抖音集团内部主要使用 Lambda 架构进行实时数仓建设,其中实时处理链路主要采用 Flink + MQ 进行实现。 在 Lambda 架构体系下,主要优势是数据新鲜度高,但采用两条处理链路也带来了其它问题:
1.维护成本高: 需要维护实时、离线两条不同技术栈的处理链路,开发和维护成本高;
2.计算口径难对齐: 没有统一的 Table 抽象,Schema 难对齐;两条链路同时跑,计算语义难对齐;
3.OLAP 查询能力差: 消息队列只支持 APPEND 流,从流式数据转化为 Table 的成本开销高,需要不断处理 changelog,导致 OLAP 查询能力差;
4.问题排查困难: 如果数据有问题,用户需要排查数据 Pipeline,但由于中间结果不可查,导致排查难度高;
5.数据订正困难: 实时链路数据订正需要大量的人工介入,修改逻辑、双跑等,数据订正困难。
随着流式计算引擎的不断完善,以 Flink 为代表的流式计算引擎提出了新的目标: 为有限数据和无限数据提供一套统一的处理 API。
流批一体的计算模式进一步简化了数仓生产体系,将计算链路收敛到了相同的技术栈,降低了开发和维护成本。
同时随着数据湖技术的兴起,它能够支持高效的数据流 / 批读写、数据回溯以及数据更新,进一步解决了Lambda 架构体系下的其它问题。
Apache Paimon是一项流式数据湖存储技术,基于Flink Table Store独立孵化出来的项目, 主要目标是解决流式场景中的常见问题,为用户提供高吞吐、低延迟的数据摄入、流式订阅和实时查询, 支持主流的计算 / OLAP 引擎,尤其对 Flink 的支持最佳。
因此在经过调研后,最终决定采用 Apache Paimon 作为数据湖底座,和业务进行新一代实时数仓建设。
本文将基于抖音集团两个业务的典型实时数仓场景,介绍 Apache Paimon 在抖音集团内部的生产实践。
01
场景一:游戏视频指标上卷
/ 业务场景
游戏-新游场景在公测宣发、测试上线首日、首发等相关节点,产品和运营需要根据游戏短视频的点赞、曝光、评论等实时指标在第一时间挖掘优质作者和发现潜力热点。
游戏实时数仓团队当前通过接入短视频实时数仓团队的分钟粒度流并关联游戏相关维表,通过分钟粒度上卷到天粒度指标的方案来提供相关指标。
/ 原有方案


/ 方案痛点
1.于短视频 topic 流量在 100w+/s 左右,即使 Lookup Join HitRate 平均在 90% 左右,但是全链路峰值仍有60w+/s 的流量打到维表存储, 给维表服务带来比较大的访问压力。


Lookup Join HitRate


Lookup Join Request Per Second
2.由于上卷任务的 source 是 append 流,分钟粒度的指标会实时的变化,所以需要消费 source 后通过 MAX / LAST_VALUE 等聚合函数去构建 retract 流、处理乱序等问题, 开发效率低且增加额外的状态成本。
`CREATE VIEW view_01 AS`

`SELECT id,`

`f1,`

`f2,`

`MAX(f3) AS f3,`

`f4,`

`f5,`

`MAX(f6) AS f6,`

`MAX(f7) AS f7,`

`LAST_VALUE(f8, f5) AS f8`

`FROM source_table`

`GROUP BY`

`id,`

`f1,`

`f2,`

`f4,`

`f5;`

`INSERT INTO sink_table`

`SELECT id,`

`f1,`

`SUM(f3) AS f3,`

`CAST(f2 AS BIGINT) AS f2,`

`MAX(f4) AS f4,`

`MAX(f5) AS f5,`

`MAX(f6) AS f6,`

`MAX(f7) AS f7,`

`LAST_VALUE(f8, f5) AS f8`

`FROM view_01`

`GROUP BY`

`id,`

`f1,`

`f2;`


/ Paimon实践
使用 Paimon 作为游戏维表,在 Flink 中 Lookup Join 将打宽结果写入 Paimon 表中,Paimon 表基于 lookup changelog producer 产生完整的 changelog,下游消费 changelog 做上卷计算。在存储层基于 Paimon 的 Sequence Field 能力处理乱序。


1.维表打宽
`--维表模型DDL`

`create table dim_table01 (`

``id` BIGINT,`

``f1` STRING,`

``f2` BIGINT`

`PRIMART KEY (f1) NOT ENFORCED`

`) WITH (`

`'changelog-producer'='lookup',`

`'changelog-producer.row-deduplicate'='true',`

`'sequence.field'='f2',`

`...`

`)`

`create table dim_table02 (`

``id` BIGINT,`

``f1` STRING,`

``f2` BIGINT`

`PRIMART KEY (f1) NOT ENFORCED`

`) WITH(`

`'changelog-producer'='lookup',`

`'changelog-producer.row-deduplicate'='true',`

`'sequence.field'='f2',`

`...`

`)`

`--分钟指标流关联维度`

`SELECT`

`AA.id,`

`BB.f1 as bb_f1,`

`CC.f1 as cc_f1`

`FROM source_table AA`

`LEFT JOIN`

`paimon.db_name.dim_table01 /*+ OPTIONS('lookup.async'='true', 'lookup.async-thread-number'='8') */`

`FOR SYSTEM_TIME AS OF proctime AS BB`

`ON AA.id = BB.id`

`LEFT JOIN`

`paimon.db_name.dim_table02 /*+ OPTIONS('lookup.async'='true', 'lookup.async-thread-number'='8') */`

`FOR SYSTEM_TIME AS OF proctime AS CC`

`ON AA.id = CC.id;`


2.指标上卷
`--分钟指标模型DDL`

`create table `db_name`.`table_name` (`

``id` BIGINT,`

``f1` STRING,`

``f2` BIGINT,`

``f3` BIGINT,`

``f4` BIGINT,`

``f5` STRING,`

``f6` BIGINT,`

``f7` STRING,`

``f8` map<STRING, STRING>`

`PRIMARY KEY (id, f1, f2, f4, f5, date, hour) NOT ENFORCED`

`) PARTITIONED by (`

``date` STRING comment '日期',`

``hour` STRING comment '小时'`

`) WITH (`

`'changelog-producer'='lookup',` 

`'partition.expiration-time'='30 d',`

`'partition.timestamp-pattern'='$date',`

`'partition.expiration-check-interval'='3h',`

`'sequence.field'='f8,f3',`

`...`

`);`

`--分钟指标上卷`

`INSERT INTO sink_table`

`SELECT id,`

`f1,`

`SUM(f3) AS f3,`

`f2,`

`MAX(f4) AS f4,`

`MAX(f5) AS f5,`

`MAX(f6) AS f6,`

`MAX(f7) AS f7,`

`LAST_VALUE(f8, f7) AS f8`

`FROM paimon.db_name.table_name`

`GROUP BY`

`id,`

`f1,`

`f2;`


/ 方案收益
1.流批一体模式开发: 原有链路需要使用 MAX、LAST_VALUE 等函数来构造 retract 消息,以保证下游 SUM 计算结果正确,流与批的开发模式是分割的。
基于 Paimon 存储数据并补齐 changelog,开发模式流与批是对齐的,获得流批一体的开发体验,提高了开发效率。
2.维表新鲜度更高: 原有链路中为了减少维表服务压力,所以本地 Cache TTL设置为 50 min,数据新鲜度较低,在Paimon 维表中默认每 10s 会主动检查维表数据是否有更新,并主动更新本地缓存,数据新鲜度更高。
3.数据乱序问题: 原链路中需要使用 LAST_VALUE 来处理数据乱序问题,增加了额外的状态成本。Paimon 合并数据时可以根据 sequence.field 来排序,从而在存储层解决数据乱序问题,不需要在 Flink 中维护状态。

`insert into sink`

`select id,`

`last_value(f1) as f1,`

`last_value(f2) as f2,`

`last_value(f3) as f3,`

`last_value(f4) as f4,`

`...`

`from (`

`select id,`

`f1,`

`f2,`

`cast(null as STRING) as f3,`

`cast(null as STRING) as f4,`

`...`

`from table1`

`union all`

`select id,`

`cast(null as STRING) as f1,`

`cast(null as STRING) as f2,`

`f3,`

`f4,`

`...`

`from table2`

`union all`

`......`

`)`

`group by id;`


02
场景二:财经多流拼接
/ 业务场景
由于前端业务过程是由于多个功能模块通过接口拼接而成的,历史链路无法打通,关键节点指标缺失, DA同学需要投入大量时间找数据拼凑数据,用数成本高、数据精度低、无法实时看到增长策略表现。
想要获得完整的用户交易过程的明细数据,财经侧在发起支付交易的时候创建了 trace_id,然后从支付开始透传到用户支付结束的所有流程中,利用 trace_id 构建用户交易行为宽表;
宽表打宽的过程中,会去组合前后端埋点、会员、标签、策略、交易、营销等多个主题域的数据,降低业务同学用数、找数成本。
/ 原有业务方案


/ 方案痛点
1.资源开销和运维成本高: 当前基于 MQ 和 Flink 做打宽任务的多流 Join,状态大小超过了 10TB,计算资源 1600+ CU。
大状态会导致资源开销变高、任务吞吐抖动、故障恢复时间变长等问题。在当前场景下,宽表任务的异常抖动会带来下游超 10 min 的断流感知,运维成本较高,亟需优化。

`CREATE TABLE t (`

`trace_id BIGINT,`

`f1 STRING,`

`f2 STRING,`

`g_1 BIGINT,`

`f3 STRING,`

`f4 STRING,`

`g_2 BIGINT,`

`PRIMARY KEY (trace_id) NOT ENFORCED`

`) WITH (`

`'merge-engine'='partial-update',`

`'fields.g_1.sequence-group'='f1,f2', -- f1,f2字段根据 g_1 排序`

`'fields.g_2.sequence-group'='f3,f4' -- f3,f4字段根据 g_2 排序`

`);`

`insert into t`

`select trace_id,`

`f1,`

`f2,`

`g_1,`

`f3,`

`f4,`

`g_2,`

`...`

`from (`

`select trace_id,`

`f1,`

`f2,`

`g_1,`

`cast(null as STRING) as f3,`

`cast(null as STRING) as f4,`

`cast(null as BIGINT) as g_2,`

`xxx`

`from table1`

`union all`

`select trace_id,`

`cast(null as STRING) as f1,`

`cast(null as STRING) as f2,`

`cast(null as BIGINT) as g_1,`

`f3,`

`f4,`

`g_2,`

`xxx`

`from table2`

`union all`

`......`

`)`

2.数据乱序问题: 由于打宽任务的超大状态,因此在 Flink 任务中状态的 TTL 配置相对较小(小时级)。在状态过期后,乱序数据会导致拼接结果不正确问题,产生额外的运维和排查成本 。
/ Paimon实践
结合 Paimon 的 Partial Update 能力,对财经用户行为打宽任务进行了改写,数据直接写入到 Paimon 表,原链路中的聚合算子得以消除,任务状态大幅下降。
同时基于 Paimon 的 Sequence Group 机制,为每个流定义了相应字段的顺序,避免因为乱序出现的数据不一致问题。


/ 方案收益
1.计算资源下降: 计算资源优化 50%+ (1600 CU 缩减到 800 CU),收益主要来源于状态管理成本下降;
2.状态优化: 消除聚合状态后,作业状态由 10TB 缩减到小于 20GB;
3.开发和运维成本下降: 中间数据可查可复用,同时指标增减可以通过 DDL 直接操作 Paimon 表;
4.数据乱序问题解决成本低: 基于 Paimon 的 Sequence Group 机制可以对多流数据按序进行合并,处理更长时间范围内的乱序问题,并且不额外新增状态成本,较之于原链路方案,数据质量提升6% 。


03
未来展望
我们期望未来以 Flink 为核心,以数据湖为底座,为用户提供全链路数据生产和管理的实时数仓解决方案,进一步简化用户的开发和使用成本。
我们也将继续针对实际业务场景进行 Apache Paimon 优化,包括:
1.千列大宽表合并性能优化: LSM Tree 架构使得 Apache Paimon 有很高的点查与合并性能,但在超大列数的业务场景中性能下降较多,内部将针对这一场景进行优化;
2.维表性能优化: Apache Paimon 的本地维表可以极大的减少传统外部 KV 存储的请求数量,但在大流量场景中,我们注意到本地维表刷新是同步的,同时没有按照 bucket 进行 shuffle,导致维表变化较快时,吞吐有明显尖刺,我们将结合 Flink 继续优化维表的访问性能;
3.Merge Engine 扩展: 部分业务场景中,业务需要自定义的 Merge Engine 来实现更加复杂的合并策略,因此我们将扩展 Merge Engine,使其支持业务进行扩展以应对更加复杂的业务场景。

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

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

相关文章

当下主流 AI 模型对比:ChatGPT、DeepSeek、Grok 及其他前沿技术

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 人工智能&#xff08;AI&#xff09;领域近年来取得了巨大的突破&#xff0c;特别是在大语言模型&#xff08;LLM&#…

【自用】NLP算法面经(5)

一、L1、L2正则化 正则化是机器学习中用于防止过拟合并提高模型泛化能力的技术。当模型过拟合时&#xff0c;它已经很好地学习了训练数据&#xff0c;甚至是训练数据中的噪声&#xff0c;所以可能无法在新的、未见过的数据上表现良好。 比如&#xff1a; 其中&#xff0c;x1和…

体育直播视频源格式解析:M3U8 vs FLV

在体育直播领域&#xff0c;视频源的格式选择直接影响着直播的流畅度、画质以及兼容性。目前&#xff0c;M3U8 和 FLV 是两种最为常见的视频流格式&#xff0c;它们各有优劣&#xff0c;适用于不同的场景。本文将从技术原理、优缺点以及应用场景等方面对 M3U8 和 FLV 进行详细解…

Ubuntu20.04安装并配置Pycharm2020.2.5

一. 下载pycharm 社区版 1. 下载地址&#xff1a; PyCharm: the Python IDE for data science and web developmentThe Python IDE for data science and web development with intelligent code completion, on-the-fly error checking, quick-fixes, and much more.https:/…

Filter Solutions学习-02 【高级设计】界面介绍

这是高级界面的各种控件的功能。 其中说一下filter type。这不是根据自己想当然决定的&#xff0c;而是根据实际的需要&#xff0c;比如带外衰减的程度&#xff0c;带内波动&#xff08;平坦&#xff09;如何&#xff0c;还有群时延等等决定的。比如不要求矩形系数选什么。。 …

用Python实现交互式数据可视化:从基础图表到动态仪表板

用Python实现交互式数据可视化&#xff1a;从基础图表到动态仪表板 一、项目背景 本文将通过一个完整的Python项目&#xff0c;展示如何使用Plotly和ipywidgets构建从基础统计到动态交互的全栈数据可视化方案。 二、核心功能模块 1. 数据生成与预处理 np.random.seed(100)…

【深度学习与大模型基础】第6章-对角矩阵,对称矩阵,正交矩阵

一、对角矩阵 对角矩阵&#xff08;Diagonal Matrix&#xff09;是一种特殊的方阵&#xff0c;其非对角线上的元素均为零&#xff0c;只有对角线上的元素可能非零。具体来说&#xff0c;对于一个 nn的矩阵 A[]&#xff0c;如果满足 则 AA 称为对角矩阵。对角矩阵通常表示为&am…

初识R语言饼状图

目录 基础饼图 标签个性化 边界修改 密度条纹 边框颜色 基础饼图 rm(list ls())# Create Data Prop <- c(3,7,9,1,2) # Make the default Pie Plot P1 <- pie(Prop) dev.off() 标签个性化 P2 <-pie(Prop , labels c("Gr-A","Gr-B","…

Spring MVC 拦截器使用

javaweb过滤器和springmvc拦截器&#xff1a; 拦截器的概念 拦截器使用 1/创建拦截器类&#xff0c;类中实现 handler执行前&#xff0c;执行后与渲染视图后的具体实现方法 public class GlobalExceptionHandler implements HandlerInterceptor {// if( ! preHandler()){re…

汽车机械钥匙升级一键启动的优点

汽车机械钥匙升级一键启动的优点主要包括&#xff1a; 便捷性&#xff1a;一键启动功能的引入极大地提升了用车便捷性。车主无需翻找钥匙&#xff0c;只需在车辆感应范围内轻触启动键&#xff0c;即可轻松发动汽车。 安全性&#xff1a;移动管家专车专用一键启动系统配备了防…

中小企业如何低成本构建高效专属网络?

对于许多中小企业管理者而言&#xff0c;构建一套安全、灵活且可扩展的专网系统是数字化转型的“必修课”。本文将从实际业务场景出发&#xff0c;拆解企业组网的核心步骤&#xff0c;并提供可落地的实施方案建议&#xff0c;帮助您快速匹配适合自身需求的网络服务商。 一、组网…

【C++】 —— 笔试刷题day_6

刷题day_6&#xff0c;继续加油哇&#xff01; 今天这三道题全是高精度算法 一、大数加法 题目链接&#xff1a;大数加法 题目解析与解题思路 OK&#xff0c;这道题题目描述很简单&#xff0c;就是给我们两个字符串形式的数字&#xff0c;让我们计算这两个数字的和 看题目我…

pytorch 网络结构可视化Netron安装使用方法(已解决)

首先 要把保存的训练模型 转为onnx格式的文件&#xff0c;然后打开下面的链接&#xff0c;选择刚刚转的onnx文件。 下载 Netron&#xff1a; 您可以访问 Netron 的官方网站 在线使用&#xff0c;或者下载桌面版本。 mnist_cnn_model.onnx 确定后&#xff0c; 2、TensorRT学习…

第六:go 操作 redis-go

Redis 在项目开发中redis的使用也比较频繁&#xff0c;本文介绍了Go语言中go-redis库的基本使用。 Redis介绍 Redis是一个开源的内存数据库&#xff0c;Redis提供了多种不同类型的数据结构&#xff0c;很多业务场景下的问题都可以很自然地映射到这些数据结构上。除此之外&am…

【蓝桥杯】每天一题,理解逻辑(4/90)【Leetcode 二进制求和】

题目描述 我们解析一下题目 我们可以理解到两个主要信息 给的是二进制的字符串返回他们的和 我们知道&#xff0c;十进制的加减法需要进位&#xff0c;例如&#xff1a;9716是因为91之后进了一位&#xff0c;二进制也是如此&#xff0c;只不过十进制是逢10进1&#xff0c;二…

快速入手-基于Django的mysql配置(三)

Django开发操作数据库更简单&#xff0c;内部提供了ORM框架。比如mysql&#xff0c;旧版本用pymysql对比较多&#xff0c;新的版本采用mysqlclient。 1、安装mysql模块 pip install mysqlclient 2、Django的ORM主要做了两件事 &#xff08;1&#xff09;CRUD数据库中的表&am…

docker部署dify

1.安装docker 参考链接 https://ascendking.blog.csdn.net/article/details/136407383 设置docker源 vim /etc/docker/daemon.json {"registry-mirrors": ["https://docker.registry.cyou", "https://docker-cf.registry.cyou", "http…

网络安全红蓝对抗实战演练,沉浸式对抗训练场上线!

在网络安全的世界里&#xff0c;没有永恒的盾牌&#xff0c;只有不断磨砺的利剑。近年来&#xff0c;某金融机构因系统漏洞导致千万级用户数据泄露&#xff0c;某制造企业因生产线遭遇勒索攻击被迫停产数日——这些真实案例揭示了一个残酷现实&#xff1a;传统的理论教学已无法…

舞狮表演(dp)

#include <bits/stdc.h> using namespace std; const int N1e35; int main() {int t;cin>>t;while(t--){int n;cin>>n;int a[N][N];for(int i1;i<n;i){for(int j1;j<n;j){int x;cin>>x;if(x&1) a[i][j]1; // 如果金额是奇数&#xff0c;a[i]…

【Qt】Qt + Modbus 服务端学习笔记

《Qt Modbus 服务端学习笔记》 1.因为项目的需要&#xff0c;要写一个modbus通信&#xff0c;csdn上感觉有些回答&#xff0c;代码是人工智能生成的&#xff0c;有些细节不对。我这个经过实测&#xff0c;是可以直接用的。 首先要包含Qt 的相关模块 Qt Modbus 模块主要包含以…