Dinky 和 Flink CDC 在实时整库同步的探索之路

news2025/4/18 16:03:44

摘要:本文整理自 Dinky 社区负责人,Apache Flink CDC contributor 亓文凯老师在 Flink Forward Asia 2024 数据集成(二)专场中的分享。主要讲述 Dinky 的整库同步技术方案演变至 Flink CDC Yaml 作业的探索历程,并深入讲解Flink CDC Yaml的一些细节能力。其主要分为三个部分:

1、起源

2、探索

3、未来

01.起源

1.1 数据集成的背景

本次分享围绕数据集成,它也是 Flink CDC Yaml 作业的出现背景。在 Dinky 的众多用户中,我们总结出以下在传统的数据集成方案中普遍会遇到的问题:需要将业务库中的业务数据同步到分析库中,起到解耦分析的作用,一般有三点要求。要求数据必须一致、链路要求稳定、数据时效性尽可能要高。

1.2 传统数据集成方案

在传统的数据集成方案中可以通过离线和实时两条链路进行,离线通常会选择开源的方案 DataX 或 Sqoop 来做一些快照同步,实时方案会根据数据库类型进行选择,例如 Mysql 数据库采用 Debezium 或 Canal 实现增量同步,但是最终在分析库中是两种表的存在形式。需要在下一步数据加工治理过程中先将快照表和增量表合并为一张表,才能进行完整的一个统计分析。这样会造成一个影响:全量和增量割裂,并且使用到的技术组件和链路较长,导致整体的数据时效性偏低。

1.3 Flink CDC 数据集成方案

Flink CDC 自发布以来,其中 2.0 版本带来了重大更新,尤其是增量快照方法。可以将数据库中的全量数据和增量实时数据合并,保证数据的一致性。其次采用 Flink CDC 时可以不需要部署 Debezium 或 Kafka 等其他组件,只需要 Flink CDC 一个组件就可以完成从业务库到分析库的实时一致性快照的同步。数据链路缩短,数据时效性比传统的方案高。

1.4 数据集成面临的挑战——整库同步

在去年经常会遇到一个场景:Flink CDC 在大面积使用的情况下,业务比较多,分析需求会逐步增长,所以构建了一个整库同步的作业,将业务库中的全部表或部分表同步到分析库中。以往在技术瓶颈的限制下,开发方式是通过 Flink CDC 的 SQL 来完成对每一张表的处理。例如源库中有一千张表,可能就需要开发一千个 Flink SQL 的作业,每一个作业会建立一个单独的数据源连接,会消耗额外的连接数,Binlog 也会重复读取。整个过程中会产生大量的 Flink 流作业,导致 Flink 集群越来越难以运维。这是遇到的第一个挑战。

1.5 数据集成面临的挑战——模式演变

第二个挑战是模式演变的问题。业务库如果发生表结构变更,下游分析库无法感知到。如果下游库无法感知进行同步变更,此时数据链路仍然在进行同步,就会丢失一些新增的数据信息。例如增加了一个 age 列,如果下游库没有同步更新表结构就会丢失最新列的一些数据。

1.6 用户渴望——端到端数据集成

用户所渴望的是可以有全增量的自动切换、元数据可以自动发现、表结构可以自动同步、整库同步只需要一个链接一个作业、在开发过程中只需一个 SQL 完成。

02.探索

2.1整库同步的探索之路

先介绍一下 Dinky。Dinky 是一个以 Apache Flink 为内核构建的开源实时计算平台,具备实时应用的作业开发、数据调试及运行监控能力,助力实时计算高效应用。

2.2 Dinky的介绍

Dinky 可以连接众多的开源框架,例如 Paimon、Hudi、Iceberg 等其它数据库和数据湖。Dinky 主要有两个核心能力,第一是实时计算 IDE,可以对 Flink 作业、Flink SQL 和整库同步作业进行调试,在 IDE 界面上实时展现任务的流数据,便于排查数据问题。第二是提供实时运维的能力,将 Flink 集群进行统一管理,可以对任务进行实时监控,触发自定义的告警规则时,进行多渠道的告警通知。

2.3 Dinky基于Flink CDC的整库同步探索

对于整库同步,Dinky 还提供 CDC Source 的方案。此分享将对两个方案进行对比。

Dinky 在实现 Flink CDC 整库同步的探索上,通过实现一个 EXECUTE CDCSOURCE 的语法,让用户通过正则表达式等其他配置来完成整库同步任务的定义,来实现全增量自动切换、元数据自动发现、结构变更自动同步、只用一个库连接、一句 SQL 部署作业。此外,还支持写入各种数据源、支持各种部署模式,这些额外能力在一定程度上缓解了 Flink CDC 在各种连接器 Source 和 Sink 上的不足。

2.4 Dinky CDC Source 整库同步数据链路

Dinky CDC Source 整库同步数据链路分析如下。在分库分表的场景下,由 Source 节点将 Binlog 日志解析成 Debezium 格式的 Json,将 Json 数据按表名和主键进行分区,来支持下游多并行度的处理。下游按表名合并后进行分发,此处的表名合并主要用于分库分表的场景,可以通过一些正则表达式和条件来指定分库分表的规则。Route 可以将符合规则的表合并为一张表进行输出。按表名合并后,会为下游每一张表产生对应算子。示例中有两张表,就可以产生 Table1 和 Table2 两条路线进行输出。该 Pipeline 的实现主要基于 Process 和 Data Stream 来开发。为了适配更多的连接器,例如适配输出到 Hudi 或 MySQL 数据库,在最后一步 Data Sink 时也支持使用 Flink 的 SQL API 进行,这样就可以兼容所有的 Flink SQL API,最终实现将 Flink CDC 支持的数据源整库同步到任意一个 Flink SQL API 实现的数据库。

由于基于 Data Stream 开发,所以模式演变比较受限,会导致模式演变受下游数据库影响。例如 Doris Sink 支持下游演变,需要将数据流转换为字符串的格式。所以我们可以进行一个链路的复用,将前面的 Debezium json 进行相关处理,到最后环节序列化成字符串,将字符串传输给 Doris Sink,由 Doris Sink 进行模式演变的处理。此时可能存在问题:当有多并行度任务时,例如多并行度为 2 时有两个 Doris Sink 写入同一张表,会存在模式演变时数据的丢失,一个算子在进行模式演变,另一个算子在进行数据写入,这就是一个弊端。所以只能在并行度为 1 时正常使用。

2.5 Dinky CDC Source的局限性

Dinky CDC Source 存在一些局限性。

首先不支持自定义转换,Dinky CDC Source 只支持宽容数据类型的转换。

第二,由之前的算子拓扑图可以发现,面对一些表同步时会构建大量的算子节点,这样作业会非常庞大,从而会导致作业的恢复成本增加。

第三点是模式演变受限。本身框架不支持模式演变,需要由下游 Sink 连接器独立实现。

2.6 Dinky CDC Source整库同步的数据转换探索

在 Dinky CDC Source 整库同步的数据转换探索上,由于下游可以支持 Table API 的使用,所以下游可以直接使用 Flink CTAS 语法,通过 Select 语句定义转换,本质上使用 Flink SQL 的处理来进行。但是仍然会构建大量算子节点,且不支持模式演变。

2.7 Flink CDC YAML定义的Pipeline作业

去年 Flink CDC 3.0 发布,并贡献给 Apache 孵化器。由于 Dinky CDC Source 存在严重的架构瓶颈,只能满足一些特定情况下的整库同步场景。经过调研后发现 Flink CDC YAML(Flink CDC Pipeline)作业完全重构了整库同步的底层设计,支持模式演变和数据转换的能力。

2.8 Flink CDC YAML核心架构

Flink CDC YAML 作业的架构主要核心是基于Flink 的运行环境来完成自定义算子的编排。在设计数据流时摒弃了 Flink SQL 的数据流,自定义了一些高效的数据结构。通过 Data Source、Data Sink、Schema Registry、Router 和 Transformer 五个算子来完成整个作业的编排。上游通过 Flink CDC Cli 和 Yaml 脚本来指定作业细节,完成整库同步作业定义。

2.9 Flink CDC Pipeline 整库同步链路

这是一张 Flink CDC Pipeline 的数据链路图,模式演变、数据转换和分库分表三种场景结合使用。在经历每个算子节点计算后,流数据的结构会发生变化。首先通过 Data Source 节点读取到原始的 Schema 结构,使用数据转换时引入 PreTransform 和 PostTransform 两个算子。PreTransform 对无关的列进行删除,裁剪后 Schema 更加简洁。PostTransform 进行一些计算及投影等能力,包括两部分,第一部分添加计算列,第二部分添加过滤条件,实现整库同步链路中自定义数据转换的能力。数据在投影后字段会增加,通常投影 Schema 会比之前的结构更宽。其中链路图中的数据流长度可以反映出 Schema 大小的变化。下一步在 Schema operator 算子中对分库分表场景下的一些结构进行进一步合并。不同的库表可能会存在表结构不同、数据类型不同的问题。为了保证数据可以完整输出到下游目标库,通过对分库分表场景的一些数据进行宽容处理,最终合并后的 Schema 大于等于投影后的 Schema 结构。此处在触发模式演变时,通过对 DataChangeEvent 进行阻塞处理,保证下游数据库数据正确一致性。解决了 Dinky CDC Source 在多并行度下进行模式演变的丢失部分变更数据的问题。

2.10 Flink CDC Pipeline的Transform

接下来介绍数据在 Flink CDC Pipeline 上如何变化。首先定义了一个 Transform,增加了一个计算列,使用 UDF(age_year)来计算年龄,过滤条件为保留成年人。这样一个 DEMO 可以覆盖 Flink CDC YAML 作业中 Transform 相关的核心能力。注意,进入 Data Source 后的数据不包含 Schema,此处将 Schema 和 Data 放在一起是为了方便理解数据,而下面的 Data 更接近 Flink CDC 数据的传输格式。经过 PreTransform 后,会裁剪无关的列,可以发现前面的 name 列没有被使用到,所以被裁剪。下一步 PostTransform 进行年龄的计算,其中所使用到的出生日期列,被定义为引用列,保留所有引用列。目前 Projection 所引用的两个列是 id 和 birthday。此处的 filter 可以对投影后的结果进行进一步过滤,对年龄不满足该条件的数据进行丢弃。此处输入的四条数据中有两条不满足,所以被丢弃。最后的 Data Sink 环节,会将这两条数据输出到分析库或数据湖,最终的数据形态由各个库的特性决定,例如要输出 Doris 数据库,要求主键是 id,最终实现 upsert 能力。该示例涵盖条件过滤、列投影、UDF 的使用、主键定义,可以很好在测试环境中体验和模拟 Transform 的特性。

2.10 Flink CDC Pipeline的Transform

随着整库同步作业的普及,可能会将数据清洗工作前置到整库同步作业中,提前将不合适的数据或垃圾数据进行清洗,从而使用到 Transform。
下面是 Transform 的实现细节。首先分为两部分:前置处理和后置处理。前置处理是对数据进行裁剪,消费 SchemaChangeEvent,通过 ChangeEvent 进行表结构的推导。其表结构不能在作业创建前被预先定义,在 YAML 作业中所定义的配置只是一些规则。当 YAML 作业读取到数据时会创建对应的 CreateChangeEvent,通过消费建表语句的事件来完成引用列及下游表结构的推导。此处包含主键分区键的定义,同时丢弃掉未使用的列来提升传输效率。后置的 Transform 操作是用于计算,首先推导出计算列,将计算投影到数据集中,并通过条件规则进行过滤。

2.11 Transform的表达式计算

在计算列和条件过滤中使用的是表达式。在表达式中,为了方便将 Flink SQL 作业迁移到 YAML 作业上,定义了投影规则与过滤规则,接近于 Flink SQL 原始写法,但不等于 Flink SQL。其中在表达式中处理都是对单表进行操作。为了满足 Transform 模块中进行动态的表达式计算,引入了一个新的框架 Janino。Janino 是一个轻巧的 Java 动态编译器,在 Apache Flink 中使用。同时引入 Apache Calcite 进行语法解析,也在 Apache Flink 中使用。基于这两个技术栈实现了动态表达式计算,可以在预定义的规则上结合变更的表结构来进行计算。

Transform 主要包含六大部分:投影规则、过滤规则、自定义函数、内置函数、运行时 Schema、运行时 Data。Transform 通过 Calcite 将类 SQL 的规则转换成最终的编译器脚本。具体步骤为 Calcite 将投影规则和过滤规则转换成一个 SQL 查询语句,进行语法树的解析,最终推导出 AST。由于是单表的处理任务,不需要进行相关的逻辑优化。再遍历 AST 生成对应的 Janino 的语法树,然后生成 Janino 的表达式,这样可以将 YAML 的脚本转换成一个动态的 Janino 的表达式,并且通过缓存来提升处理效率。

2.12 模式演变的机制与策略

在 Flink CDC YAML 中支持模式演变的机制与策略。该机制解决了 Dinky CDC Source 由于架构的限制不支持模式演变的缺点。提供了一些细粒度的策略和全局策略,可以进行灵活控制。例如,不要求下游进行模式演变或者要摒弃某些模式演变,可以通过这种全局策略和细粒度策略进行控制来满足多样化使用。

2.13 其他方面比较

其他方面的比较有三大点:数据结构、分库分表、输入输出。

2.14 Flink CDC的高性能数据结构

Flink CDC Pipeline 带来一个高性能的数据结构。Dinky CDC Source 的实现基于 Flink Data Stream 实现,结果是一个宽的结构,每条数据都包含完整的 Schema 信息。在 Flink CDC Pipeline YAML 作业中,将数据结构进行压缩,将 Schema 和 data 进行分离,最终根据数据的实际内容进行分配,此处的传输效率和资源使用得到了一定提升,对事件变更进行了合并。图中左侧 Dinky CDC Source 有四条 Flink 流事件语义,而 Flink CDC 则将 Update 合并为 Before 和 After 进行统一处理,减少了需要处理的流事件数量。

2.14 Flink CDC的分库分表宽容机制

Flink CDC Pipeline 具有分库分表的宽容机制。而 Dinky CDC Source 不具备该能力,虽然可以对分库分表的数据进行合并,但不具备对不同列冲突或不兼容的列进行处理,强要求表结构必须相同。Flink CDC Pipeline 作业引入一些宽容机制,可以自动打宽表结构,保证在分库分表合并过程中为用户保留更多的数据和信息,不至于丢失。

下面案例第一个是新增列,两个分表的结构完全一致,但是之后其中一张表的结构增加了一个地址列,此时 Flink CDC Pipeline 会自动为旧数据补充上值为空的地址列。第二个是修改列,列类型的变更有一些兼容机制,保证列类型进行宽容的转换。第三个删除列可以自动删除数据进行过滤。

2.15 Source与Sink

Dinky CDC Source 架构基于 Data Stream 开发,支持所有 Flink CDC Source,支持所有 Flink SQL 的 Sink。而 Flink CDC Pipeline 支持的连接器比较少,需要二次开发。目前有很多用户使用 Dinky CDC Source 来处理 Flink CDC Pipeline 作业不支持的场景。

2.16 两者差异总结

两者差异总结如下。

  1. Dinky CDC Source 作业通过类 SQL 语句进行定义,Flink CDC Pipeline 作业通过 YAML 脚本定义。

  2. Dinky 是一个实时计算平台,拥有完善的前端 IDE 交互,所以作业通过界面进行提交。Flink CDC Pipeline 作为一个后端框架使用,提供通过脚本来启动 YAML 作业任务,但是该启动模式在生产环境中不太适用。

  3. Flink CDC Pipeline 具备完整的模式演变,Dinky CDC Source 受限于下游 Sink 连接器的实现。

  4. 分库分表方面,Flink CDC Pipeline 支持不同的表结构宽容合并。

  5. Flink CDC Pipeline 支持完整的 Transform,基于 Transform 架构,可以实现更多能力,例如调用 API 能力,后续会有一些向量计算的能力在 Pipeline 作业中进行扩展。

  6. Dinky CDC Source 的 Source 支持 Flink CDC 所有的 Source,可以理解为原生 Source,所提供的是 API Source,不是 Pipeline Source。

  7. Dinky CDC Source 的 Sink 支持所有的 Flink SQL Sink,而 Flink CDC Pipeline 支持的较少。

  8. Flink CDC Pipeline 的数据结构上具有高性能的二进制结构。

  9. Dinky CDC Source 算子节点有大量节点,而 Flink CDC Pipeline 节点非常少。

  10. 部署模式上 Dinky CDC Source 支持所有部署模式,Flink CDC Pipeline 支持少,不支持 Yarn。

  11. 由于上述的一些条件,例如数据结构、算子拓扑节点,会导致数据资源的消耗有明显差异。

2.17 在Dinky中使用Flink CDC Pipeline

由于 Dinky CDC Pipeline 作业有局限性,所以在使用过程中会有一些痛点。Dinky 在最新版本中提供了 Flink CDC Pipeline 作业,可以在 Dinky 中定义一个 EXECUTE PIPELINE 语句来定义 Flink CDC YAML 脚本配置,通过 Dinky 平台提交到 Flink 集群。同时可以解决上述提到的 CDC 的缺点:不支持 Yarn、提交方式不方便等。

在 Dinky 中使用 Flink CDC Pipeline 可以完全兼容 Flink SQL 生态管理的功能,例如托管作业状态、告警等功能。下一步会增加相关功能帮助用户调试 Flink CDC Pipeline 作业,帮助用户在页面上看到 Pipeline 作业的输出。

03.探索

Dinky CDC Source 是作为一个过渡工具来保证用户在 Flink CDC Pipeline 普及前有业务需求时使用。目前 Dinky CDC Source 已经有近百家用户在使用,未来也会为 Dinky CDC Source 添加一个 Pipeline 转换功能,将 Dinky CDC Source 转为 Flink CDC YAML 作业,帮助用户快速架构到 Flink CDC YAML 上。其次会进行一些细粒度策略,试图尝试扩展 Transform 来满足用户需求。最后探索实时湖仓的治理,同时我们的项目也在寻找 Apache 孵化器的导师。

我们会与 Flink CDC 进行紧密合作,将 Flink CDC 各种能力应用在 Dinky 上,并投入精力在 Flink CDC 上,帮助社区完成对应的一些 Transform 优化及其他场景的完善。

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

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

相关文章

视频融合平台EasyCVR搭建智慧粮仓系统:为粮仓管理赋能新优势

一、项目背景 当前粮仓管理大多仍处于原始人力监管或初步信息化监管阶段。部分地区虽采用了简单的传感监测设备,仍需大量人力的配合,这不仅难以全面监控粮仓复杂的环境,还容易出现管理 “盲区”,无法实现精细化的管理。而一套先进…

3D Gaussian Splatting as MCMC 与gsplat中的应用实现

3D高斯泼溅(3D Gaussian splatting)自2023年提出以后,相关研究paper井喷式增长,尽管出现了许多改进版本,但依旧面临着诸多挑战,例如实现照片级真实感、应对高存储需求,而 “悬浮的高斯核” 问题就是其中之一。浮动高斯核通常由输入图像中的曝光或颜色不一致引发,也可能…

C++初阶-C++的讲解1

目录 1.缺省(sheng)参数 2.函数重载 3.引用 3.1引用的概念和定义 3.2引用的特性 3.3引用的使用 3.4const引用 3.5.指针和引用的关系 4.nullptr 5.总结 1.缺省(sheng)参数 (1)缺省参数是声明或定义是为函数的参数指定一个缺省值。在调用该函数是…

STM32_USB

概述 本文是使用HAL库的USB驱动 因为官方cubeMX生成的hal库做组合设备时过于繁琐 所以这里使用某大神的插件,可以集成在cubeMX里自动生成组合设备 有小bug会覆盖生成文件里自己写的内容,所以生成一次后注意保存 插件安装 下载地址 https://github.com/alambe94/I-CUBE-USBD-Com…

STM32 的编程方式总结

🧱 按照“是否可独立工作”来分: 库/方式是否可独立使用是否依赖其他库说明寄存器裸写✅ 是❌ 无完全自主控制,无库依赖标准库(StdPeriph)✅ 是❌ 只依赖 CMSIS自成体系(F1专属),只…

MFC工具栏CToolBar从专家到小白

CToolBar m_wndTool; //创建控件 m_wndTool.CreateEx(this, TBSTYLE_FLAT|TBSTYLE_NOPREFIX, WS_CHILD | WS_VISIBLE | CBRS_FLYBY | CBRS_TOP | CBRS_SIZE_DYNAMIC); //加载工具栏资源 m_wndTool.LoadToolBar(IDR_TOOL_LOAD) //在.rc中定义:IDR_TOOL_LOAD BITMAP …

大厂机考——各算法与数据结构详解

目录及其索引 哈希双指针滑动窗口子串普通数组矩阵链表二叉树图论回溯二分查找栈堆贪心算法动态规划多维动态规划学科领域与联系总结​​ 哈希 ​​学科领域​​:计算机科学、密码学、数据结构 ​​定义​​:通过哈希函数将任意长度的输入映射为固定长度…

10:00开始面试,10:08就出来了,问的问题有点变态。。。

从小厂出来,没想到在另一家公司又寄了。 到这家公司开始上班,加班是每天必不可少的,看在钱给的比较多的份上,就不太计较了。没想到8月一纸通知,所有人不准加班,加班费不仅没有了,薪资还要降40%…

基于ueditor编辑器的功能开发之给编辑器图片增加水印功能

用户需求,双击编辑器中的图片的时候,出现弹框,用户可以选择水印缩放倍数、距离以及水印所放置的方位(当然有很多水印插件,位置大小透明度用户都能够自定义,但是用户需求如此,就自己写了&#xf…

【CSS基础】- 02(emmet语法、复合选择器、显示模式、背景标签)

css第二天 一、emmet语法 1、简介 ​ Emmet语法的前身是Zen coding,它使用缩写,来提高html/css的编写速度, Vscode内部已经集成该语法。 ​ 快速生成HTML结构语法 ​ 快速生成CSS样式语法 2、快速生成HTML结构语法 生成标签 直接输入标签名 按tab键即可 比如 div 然后tab…

【码农日常】vscode编码clang-format格式化简易教程

文章目录 0 前言1 工具准备1.1 插件准备1.2 添加.clang-format1.3 添加配置 2 快速上手 0 前言 各路大神都说clangd好,我也来试试。这篇主要讲格式化部分。 1 工具准备 1.1 插件准备 照图安装。 1.2 添加.clang-format 右键添加文件,跟添加个.h或者.c…

金融数据分析(Python)个人学习笔记(7):网络数据采集以及FNN分类

一、网络数据采集 证券宝是一个免费、开源的证券数据平台(无需注册),提供大盘准确、完整的证券历史行情数据、上市公司财务数据等,通过python API获取证券数据信息。 1. 安装并导入第三方依赖库 baostock 在命令提示符中运行&…

死锁 手撕死锁检测工具

目录 引言 一.理论联立 1.死锁的概念和原因 2.死锁检测的基本思路 3.有向图在死锁检测中的应用 二.代码实现案例(我们会介绍部分重要接口解释) 1.我们定义一个线性表来存线程ID和锁ID 2.表中数据的查询接口 3.表中数据的删除接口 4.表中数据的添…

软考高级-系统架构设计师 案例题-软件架构设计

文章目录 软件架构设计质量属性效用树,质量属性判断必背概念架构风格对比MVC架构J2EE四层结构面向服务架构SOA企业服务总线ESB历年真题【问题1】 (12分)【问题2】(13分) 参考答案历年真题【问题1】(12分)【…

vue+d3js+fastapi实现天气柱状图折线图饼图

说明: vued3jsfastapi实现天气柱状图折线图饼图 效果图: step0:postman 1. 生成天气数据(POST请求):URL: http://localhost:8000/generate-data/?year2024&month3&seed42 方法: POST Headers:Content-Type:…

vue:前端预览 / chrome浏览器设置 / <iframe> 方法预览 doc、pdf / vue-pdf 预览pdf

一、本文目标 <iframe> 方法预览 pdf 、word vue-pdf 预览pdf 二、<iframe> 方法 2.1、iframe 方法预览需要 浏览器 设置为&#xff1a; chrome&#xff1a;设置-隐私设置和安全性-网站设置-更多内容设置-PDF文档 浏览器访问&#xff1a; chrome://settings/co…

【NLP 56、实践 ⑬ LoRA完成NER任务】

目录 一、数据文件 二、模型配置文件 config.py 三、数据加载文件 loader.py 1.导入文件和类的定义 2.初始化 3.数据加载方法 代码运行流程 4.文本编码 / 解码方法    ① encode_sentence()&#xff1a; ② decode()&#xff1a; 代码运行流程 ③ padding()&#xff1a; 代码…

【力扣hot100题】(076)买卖股票的最佳时机

终于来到了最考验智商的贪心算法。 之前做过&#xff0c;但花了不少时间思考&#xff0c;所以这次做的很快。 思路就是记录最小价格&#xff0c;然后一路遍历边调整新的最小价格边比较目前价格和最小价格差价。 class Solution { public:int maxProfit(vector<int>&am…

c#的form实现叠叠乐游戏

说明&#xff1a; 我希望用c#的form实现叠叠乐的游戏&#xff0c;玩家需要堆叠方块来建造高塔。 效果图&#xff1a; step1:游戏规则 游戏实现步骤&#xff1a; a. 处理事件&#xff0c;玩家可以释放摆动的方块&#xff0c;方块会下落。 b. 更新摆动方块的位移&#xff0c;根…

Qt中的元对象系统

Qt的元对象系统(Meta-Object System)提供了对象间通信的信号和槽机制、运行时类型信息和动态属性系统。 元对象系统基于以下三个方面&#xff1a; (1).QObject类&#xff1a;为可以利用元对象系统的对象提供了基类。 (2).Q_OBJECT宏&#xff1a;用于启用元对象功能&#xff0c;…