【实时计算 Flink】SQL作业大状态导致反压的调优原理与方法

状态管理不仅影响应用的性能,还关系到系统的稳定性和资源的有效利用。如果状态管理不当,可能会导致性能下降、资源耗尽,甚至系统崩溃。本文为您介绍SQL作业大状态导致反压的调优原理与方法。

运行原理:状态算子的产生

作为一种特定领域语言,SQL的设计初衷是隐藏底层数据处理的复杂性,可以通过声明式语言来进行数据操作。而Flink SQL由于其架构的特殊性,在实现层面通常需要引入状态后端配合系统检查点(Checkpoint)来保证计算结果的最终一致性。目前Flink SQL由优化器根据配置项以及SQL语句来推导生成状态算子,想要高效处理有状态的大规模数据和性能调优,需要对SQL状态算子生成机制和管理策略有一定了解。

基于优化器推导产生的状态算子

主要有如下三种状态算子:

状态算子

状态清理机制

ChangelogNormalize

生命周期TTL

SinkUpsertMaterlizer

LookupJoin(*)

ChangelogNormalize

ChangelogNormalize旨在对涉及主键语义的数据变更日志进行标准化处理。通过该算子,可以有效地整合和优化数据变更记录,确保数据的一致性和准确性。该状态算子会在以下两种场景出现:

  • 使用了带有主键的upsert源表

    upsert源表特指在保持主键顺序一致性的前提下,仅产生基于主键的UPDATE(包括INSERT和 UPDATE_AFTER)及DELETE操作的变更数据表。例如,Upsert Kafka便是支持这类操作的典型连接器之一。此外,您也可以通过重写自定义源表连接器中的getChangelogMode方法,实现upsert功能。

    @Override
    public ChangelogMode getChangelogMode() {return ChangelogMode.upsert();
    }
  • 显式设置'table.exec.source.cdc-events-duplicate' = 'true'

    在使用at-least-once语义进行CDC事件处理时,可能会产生重复的变更日志。在需要exactly-once语义时,您需要开启此配置项来对变更日志进行去重。例如

  • 当出现该算子时,上游数据将按照Flink SQL源表DDL中定义的主键做一次hash shuffle操作后使用ValueState来存储当前主键下最新的整行记录。更新状态并向下游发送变更的过程如下图所示。处理第二条-U(2, 'Jerry', 77)时State已经empty,说明截止目前+I/+UA和-D/-UB已经两两抵销,当前这条retract消息是重复的,可以丢弃。

SinkUpsertMaterializer

专门用于处理具有主键定义的结果表,并确保数据的物化操作符合upsert语义。在数据流更新过程中,如果无法保证upsert的特定要求,即按照主键进行更新时保持数据的唯一性和有序性,优化器会自动引入此算子。它通过维护基于结果表主键的状态信息,来确保这些约束得到满足。更多信息及常见场景请参见Flink SQL中Changelog事件乱序处理原理。

LookupJoin

在处理LookupJoin操作时,若主动配置了系统优化选项'table.optimizer.non-deterministic-update.strategy'='TRY_RESOLVE',且优化器识别到潜在的非确定性更新问题(如何消除流查询的不确定性影响),则系统会尝试采取特殊措施以解决这一问题。具体而言,若通过引入一个状态算子能够消除非确定性,优化器便会自动创建一个带状态的LookupJoin算子。

带状态的LookupJoin算子主要适用于以下情况:结果表被定义了主键,而这些主键完全或部分来自于维表,同时维表中的数据可能会发生变化(例如通过变更数据捕获,即CDC Lookup Source机制)。此外,用于Join操作的字段在维表中并非主键。在这种情况下,带状态的LookupJoin算子能够有效地处理数据的动态变化,确保查询结果的准确性和一致性。

基于SQL操作产生的状态算子

基于SQL操作产生的状态算子,按状态清理机制可以分为TTL过期和依赖watermark推进两类。具体说来,Flink SQL里有部分状态算子的生命周期不是由TTL来控制,例如Window相关的状态计算(WindowAggregate、WindowDeduplicate、WindowJoin、WindowTopN等)。它们的状态清理主要依赖于watermark的推进,当watermark超过窗口结束时间时,内置的定时器就会触发状态清理。

状态算子

如何产生

状态清理机制

Deduplicate

使用row_number语句,order by的字段必须为时间属性(time attribute)字段(事件时间event time或处理时间processing time),且只取第一条。

TTL

RegularJoin

使用join语句,等值条件里不包含时间属性字段。

GroupAggregate

使用group by语句进行分组聚合,如sum、count、min、max、first_value、last_value,或使用distinct关键字。

GlobalGroupAggregate

分组聚合开启local-global优化。

IncrementalGroupAggregate

当存在两层分组聚合操作并开启两阶段优化时,内层聚合对应的状态算子GlobalGroupAggregate和外层聚合对应的状态算子LocalGroupAggregate被合并成一个IncrementalGroupAggregate。

Rank

使用row_number语句,order by的字段必须为非时间属性字段。

GlobalRank

使用row_number语句,order by的字段必须为非时间属性字段,并开启local-global优化。

IntervalJoin

使用join语句,等值条件里包含时间属性字段(事件时间或处理时间)。例如:

L.time between R.time + X and R.time + Y -- 或 
R.time between L.time - Y and L.time - X

watermark

TemporalJoin

使用基于事件时间的inner或left join语句。

WindowDeduplicate

基于Window TVF的去重操作。

WindowAggregate

基于Window TVF聚合。

GlobalWindowAggregate

基于Window TVF聚合,并开启两阶段优化。

WindowJoin

基于Window TVF的Join。

WindowRank

基于Window TVF的排序。

GroupWindowAggregate

基于legacy语法的Window聚合。

问题诊断方法

在Flink作业遭遇性能瓶颈时,系统往往表现出明显的反压现象。这种反压可能由多种因素引起,但主要的原因之一是作业状态规模的持续膨胀,直至超出内存限制。此时,状态存储引擎会将部分不频繁使用的状态数据移至磁盘,而磁盘与内存在数据存取速度上的巨大差异,使得磁盘IO操作成为数据处理效率的瓶颈。尤其在Flink的计算过程中,如果算子频繁地从磁盘读取状态数据,将显著增加作业的延迟,降低整体处理速度,成为性能问题的根源。

为了准确识别是否由状态访问引发反压,需要对作业的运行状态和算子行为进行深入分析。利用监控工具追踪和诊断性能瓶颈,可以有效地发现并解决由状态访问引起的性能问题,从而提升Flink作业的性能,具体方法请参见问题诊断方法。

调优方法

主动避免生成不必要的状态算子

基于SQL操作产生的状态算子一般很难避免,因此主要针对优化器自动推导的算子进行讨论。

  • ChangelogNormalize

    在使用upsert source进行数据处理时,需注意其ChangelogNormalize状态节点的生成。通常情况下,除了事件时间的时态关联(event time temporal join)外,其他upsert source应用场景都会产生该状态节点。因此,在选择Upsert Kafka或类似的Upsert连接器时,应首先评估具体的使用场景,对于非事件时间关联场景,应特别关注状态算子的状态指标(state metrics)。由于状态节点是基于KeyedState的,当源表的主键数量庞大时,状态节点的规模也会相应增加。如果物理表的主键更新频繁,状态节点也将频繁地被访问和修改。从实践角度而言,像数据同步类的场景,建议避免使用Upsert Kafka作为源表连接器,同时也最好选择能够保证exactly-once语义的数据同步工具。

  • SinkUpsertMaterializer

    auto作为table.exec.sink.upsert-materialize配置项的默认值,表明系统会自动判断数据的一致性,尤其是在变更日志(changelog)出现无序的情况下。该机制确保了通过引入SinkUpsertMaterializer来维持数据处理的准确性。但并不意味着每当该算子被激活,数据就一定存在无序问题。例如,将多个分组键(group by key)合并的操作,这种情况下优化器无法准确推导出upsert键,因此出于安全考虑,会默认添加SinkUpsertMaterializer。如果对数据的分布有充分的了解,不使用该算子也能够确保输出结果的正确性,可以将参数设置为none,从而在数据正确性和性能上都得到保证。

    您可以通过检查作业的最后一个节点来确认SinkUpsertMaterializer是否被激活使用。在作业的运行拓扑图中(如下所示),该算子通常会与sink算子一起显示,形成一个算子链。通过这种方式,可以直观地监控和评估SinkUpsertMaterializer在数据处理过程中的实际应用情况,从而做出更加合理的优化决策。

    image.png

    image.png

    在检测到生成了特定算子且数据计算无误的情况下,可以调整配置项为 'table.exec.sink.upsert-materialize'='none'(配置步骤请参见如何配置作业运行参数?),以避免自动添加SinkUpsertMaterializer。实时计算引擎VVR 8.0及以上版本中引入了SQL执行计划智能分析功能,协助您更好地识别此类问题,如下图所示。

    image.png

减少状态访问频次:开启mini-batch

在对延时要求不高(比如分钟级别更新)的场景下,开启mini-batch攒批优化将会减少State的访问和更新频率(具体操作请参见开启MiniBatch),提升吞吐。

实时计算Flink版可以应用mini-batch的状态算子如下:

状态算子

说明

ChangelogNormalize

无。

Deduplicate

可配置table.exec.deduplicate.mini-batch.compact-changes-enable,在基于事件时间去重时是否压缩Changelog。

GroupAggregate

GlobalGroupAggregate

IncrementalGroupAggregate

无。

RegularJoin

需额外配置table.exec.stream.join.mini-batch-enabled开启mini-batch join优化。适用于更新流和outer join场景。

减少状态大小设置合理生命周期

说明

开启或关闭TTL不能保证完全兼容。当尝试在已开启TTL的作业上关闭TTL配置时,或者反过来操作时,将会导致兼容性失败并引发StateMigrationException异常。

在优化计算系统时,关键在于精简状态数据以提高性能。您可以在作业运维页面配置State数据过期时间(参数详情请参见运行参数配置)来控制作业状态的生命周期,以满足不同的运维需求和策略。

image.png

过短的TTL可能导致数据未能及时处理,从而产生不符合预期的计算结果,例如,在聚合或连接操作时,部分数据晚到,而相关状态已过期,导致结果异常。相反,过长的TTL会消耗资源,降低作业的稳定性。因此,在对Flink SQL作业进行TTL配置时,建议根据数据特性和业务需求进行恰当的TTL设置。例如,如果计算周期以自然天为单位,并且数据跨天漂移不会超过1小时,那么将TTL设定为25小时即可满足需求。数据开发人员应深入了解业务场景和计算逻辑,以实现最佳的平衡。

此外,针对双流连接场景,Flink SQL自实时计算引擎VVR 8.0.1版本起,支持通过JOIN_STATE_TTL Hint为左流和右流分别设置不同的生命周期。这一改进允许为各自数据流定制生命周期,有效减少不必要的状态存储开销,从而优化作业性能。您可以根据左右流数据的实际生命周期需求,灵活配置,以达到节省资源和提高作业效率的目的,具体操作请参见查询提示。

SELECT /*+ JOIN_STATE_TTL('left_table' = '..', 'right_table' = '..') */ *
FROM left_table [LEFT | RIGHT | INNER] JOIN right_table ON ...

下面是一个作业使用JOIN_STATE_TTL Hint前后的State大小对比示例。

对比

作业情况

状态大小

优化前

  • 双流join操作,左流数据量大,约为右流的20至50倍。右流需长期保存数据,原定为18天。为提升性能,实际将右流的保存周期缩短至10天,导致数据正确性受损。

  • join操作的状态大小约为5.8 TB。

  • 单作业所需资源高达700 CU。

22

优化后

  • 通过合理设置JOIN_STATE_TTL Hint,左流可缩短至12小时,右流保持18天的保存周期,无需牺牲数据完整性。

  • join操作的状态大幅减少至约590 GB,仅约为原来的十分之一。

  • 资源消耗显著降低,从700 CU降至200-300 CU,节省了50%-70%的资源。

23e

减少状态大小:命中更优的执行计划

在生成执行计划时,优化器会结合输入SQL和配置选择相应的State实现。

  • 利用主键优化双流连接

    • 当连接键(Join Key)包含主键时,系统采用ValueState<RowData>进行数据存储,这样可以为每个连接键仅保留一条最新记录,实现存储空间的最大化节省。

    • 如果连接操作使用了非主键字段,即使已定义主键,系统会使用MapState<RowData, RowData>进行存储,以便为每个连接键保存来自源表的、基于主键的最新记录。

    • 在未定义主键的情况下,系统将使用MapState<RowData, Integer>存储数据,记录每个连接键对应的整行数据及其出现次数。

    因此,建议在建表DDL中声明主键,并在双流连接时优先使用主键,以优化存储效率。

  • 优化append_only流去重操作

    使用ROW_NUMBER函数替代FIRST_VALUE或LAST_VALUE函数进行去重,可以更有效地保留首次(ROW_NUMBER函数生成的Deduplicate算子仅保留出现过的Key)或最新出现的记录(保留Key及其最后一次出现的记录)。

  • 提升聚合查询性能

    在进行多维度统计,例如计算全网UV、手机客户端UV、PC端UV等,推荐使用AGG WITH FILTER语法替代传统的CASE WHEN语法。SQL优化器能够识别Filter参数,使得在同一个字段上根据不同条件计算COUNT DISTINCT时能够共享状态信息,减少状态的读写次数。根据性能测试结果,采用AGG WITH FILTER语法相比CASE WHEN可以提升高达一倍的性能。

减少状态大小:调整多流Join顺序,缓解State放大

Flink在处理数据流时,采用了二进制哈希连接(Binary Hash Join)的方式。在下图示例中,A与B的连接结果会导致数据存储的冗余,这种冗余程度与连接操作的频率成正比。随着加入连接的流数量增加,State的冗余问题会变得更加严重。

image.png

您可以策略性地调整连接的顺序来优化该问题。具体来说,可以先将数据量较小的流进行连接,而将数据量大的流放在最后进行。这样的顺序调整有助于减轻状态冗余带来的放大效应,从而提高数据处理的效率和性能。

尽可能减少读盘

为了提升系统性能,可以通过减少磁盘读取次数并优化内存使用来实现。

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

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

相关文章

【Python】Twisted:让自定义网络应用开发变得简单

Twisted 是 Python 中一个成熟、功能强大的事件驱动网络编程框架。它支持多种协议&#xff0c;如 HTTP、FTP、SMTP 等&#xff0c;可以用于构建高性能的网络应用&#xff0c;包括网络服务器、客户端、代理服务器等。Twisted 的核心是基于事件驱动模型&#xff0c;能够有效处理大…

基于方块编码的图像压缩matlab仿真,带GUI界面

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 编码单元的表示 4.2编码单元的编码 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 下图是随着方块大小的变化&#xff0c;图像的压缩率以及对应的图像质量指标PSN…

Python OpenCV精讲系列 - 三维重建深入理解(十七)

&#x1f496;&#x1f496;⚡️⚡️专栏&#xff1a;Python OpenCV精讲⚡️⚡️&#x1f496;&#x1f496; 本专栏聚焦于Python结合OpenCV库进行计算机视觉开发的专业教程。通过系统化的课程设计&#xff0c;从基础概念入手&#xff0c;逐步深入到图像处理、特征检测、物体识…

SpringBoot项目-Thymeleaf安装

SpringBoot项目-Thymeleaf安装 参考文章:SpringBoot 整合Thymeleaf教程及使用方法 参考视频:模板引擎Thymeleaf快速入门 其实,参考的文章和视频,他们丢失了一些细节,我搞的时候还是有错 第1步:pom.xml增加依赖 <!-- SpringBoot集成thymeleaf模板 --><depe

QD1-P6 HTML常用标签:列表

本节视频 https://www.bilibili.com/video/BV1n64y1U7oj?p6 ‍ 本节学习HTML列表标签。HTML 列表有多种形式&#xff0c;最重要的有两种&#xff1a; 有序列表无序列表 一、有序列表 1.1 写法 <ol><li>首先</li><li>其次</li><li>最…

Window11 安装Java21教程

随着Java版本的迭代&#xff0c;最新的长期支持版本已经更新到Java21了&#xff0c;虽然笔者许多代码还是当年用Java8写的&#xff0c;但抱残守缺从来不适合IT人员&#xff0c;该来的我们始终要欣然面对。 其实随着各项技术的发展&#xff0c;Java许多组件现在其实都不需要或者…

Linux shell编程学习笔记86:sensors命令——硬件体温计

0 引言 同事们使用的Windows系统电脑&#xff0c;经常莫名其妙地装上了鲁大师&#xff0c;鲁大师的一项功能是显示系统cpu等硬件的温度。 在Linux系统中&#xff0c;sensors命令可以提供类似的功能。 1 sensors命令 的安装和配置 1.1 sensors命令 的安装 要使用sensors命…

华为OD机试 - 单向链表中间节点(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

使用Spring Security实现用户-角色-资源的权限控制

文章目录 一、基于角色的请求控制二、加载用户角色信息三、角色与资源的关联四、测试角色权限控制1. 未登录用户访问受保护资源2. 登录用户访问受保护资源3. 角色不足的用户访问受保护资源&#xff08;把前面改成.roles("USER")&#xff09; 五、自定义异常处理1. 自…

数学建模算法与应用 第3章 非线性规划及其求解方法

目录 3.1 非线性规划概述 3.2 约束优化问题 3.3 无约束优化问题的Matlab求解 3.4 牛顿法与梯度下降法 Matlab代码示例&#xff1a;梯度下降法求解简单非线性问题 3.5 非线性规划在机器学习中的应用 习题 3 总结 非线性规划&#xff08;Nonlinear Programming, NLP&…

华为OD机试 - 人数最多的站点(Java 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;E卷D卷A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加…

A2P云短信,是什么意思?

中国联通国际公司产品之 A2P 云短信 一站式国际通信服务&#xff0c;助力企业拓展国际业务&#xff0c;轻松触达全球客户 在全球化日益加深的今天&#xff0c;企业要想在竞争激烈的国际市场中脱颖而出&#xff0c;不仅需要优质的产品和服务&#xff0c;更需要高效的沟通渠道来…

系统架构设计师 - 案例特训专题 - 架构设计篇

案例特训专题 - 架构设计篇 架构设计篇软件架构风格 ★★★★质量属性与架构评估 ★★★★★Web 架构综合考查 ★★★★★单台机器到数据库与Web服务器分离应用服务器集群负载均衡技术Session共享机制持久化技术 ORM数据库读写分离化缓存常见缓存技术Redis 集群切片的常见方式R…

DAMA数据管理知识体系(第5章 数据建模和设计)

课本内容 5.1 引言 概要 常见6种数据模式 关系模式多维模式面向对象模式事实模式时间序列模式NoSQL模式按照描述详细程度不同分类 概念模型逻辑模型物理模型包含组件 实体、关系、事实、键、属性业务驱动因素 1&#xff09;提供有关数据的通用词汇表。2&#xff09;获取、记录组…

SQL Server 2022 RTM Cumulative Update #15 发布下载

SQL Server 2022 RTM Cumulative Update #15 发布下载 最新的累积更新 (CU) 下载&#xff0c;包含自 SQL Server 2022 RTM 发布以来的所有更新。 请访问原文链接&#xff1a;https://sysin.org/blog/sql-server-2022/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留…

职称申报材料整理需要注意哪些方面呢?

相信不少小伙伴都想评完职称&#xff0c;最后可以升职加薪领补贴等等&#xff0c;但是不知道申请具体需要哪些材料❓❗ 今天甘建二给大家整理出20个工程专业职称评审的必备材料&#xff0c;必须码住&#xff0c;千万别错过啦 &#xfffd;&#xfffd;01、业绩材料 ⭕反应任现…

PCL 计算点云AABB包围盒

目录 一、概述 1.1原理 1.2实现步骤 1.3应用场景 二、代码实现 2.1关键函数 2.1.1 计算AABB 2.1.2 可视化AABB 2.2完整代码 三、实现效果 PCL点云算法汇总及实战案例汇总的目录地址链接&#xff1a; PCL点云算法与项目实战案例汇总&#xff08;长期更新&#xff09;…

ChatGPT国内中文版镜像网站整理合集(2024/9/30)

一、GPT中文镜像站 ① yixiaai.com 支持GPT4、4o以及o1&#xff0c;支持MJ绘画 ② chat.lify.vip 支持通用全模型&#xff0c;支持文件读取、插件、绘画、AIPPT ③ AI Chat 支持GPT3.5/4&#xff0c;4o以及MJ绘画 1. 什么是镜像站 镜像站&#xff08;Mirror Site&#xff…

如何实现不同VLAN间互通?

问题描述 客户要求不同VLAN的PC机互通&#xff0c;如下图拓扑所示。 此外&#xff0c;仅允许在设备 LSW3 上进行配置修改。 分析 由于所有的PC都在同一个网段&#xff0c;当任何一个设备想要和另一个设备通信时&#xff0c;它会首先根据数据交互的流程广播一个ARP请求报文来获…

微服务架构Gin-etcd-gRPC接合的入门实践

最近在学习微服务&#xff0c;先后学习gRPC、etcd。学习过这两个技术之后&#xff0c;结合Gin框架&#xff0c;简单实现了一个微服务的小demo了。 以下是各技术在微服务架构中的功能。 Gin框架作为网关&#xff0c;外部请求的统一出口。负责将外部的HTTP请求转化为RPC请求&…