Flink 维表关联方案

Flink 维表关联方案
1、Flink DataStream 关联维表
1)概述
1.分类

实时数据库查找关联(Per-Record Reference Data Lookup)

预加载维表关联(Pre-Loading of Reference Data)

维表变更日志关联(Reference Data Change Stream)

根据实现上的优化可以衍生出多种关联方式,且这些优化还可以灵活组合产生不同效果。

2.衡量指标

实现简单性: 设计是否足够简单,易于迭代和维护。

吞吐量: 性能是否足够好。

维表数据的实时性: 维度表的更新是否可以立刻对作业可见。

数据库的负载: 是否对外部数据库造成较大的负载(负载越低分越高)。

内存资源占用: 是否需要大量内存来缓存维表数据(内存占用越少分越高)。

可拓展性: 在更大规模的数据下会不会出现瓶颈。

结果确定性: 在数据延迟或者数据重放情况下,是否可以得到一致的结果。

2)实时数据库查找关联
1.概述

在 DataStream API 用户函数中直接访问数据库进行关联。

开发量最小,会给数据库带来很大压力,而且关联基于 Processing Time,如果数据有延迟或重放,会得到和原来不一致的结果。

2.同步数据库查找关联
a) 概述

在一个 Map 或者 FlatMap 函数中访问数据库,处理好关联逻辑后,将结果数据输出。

在这里插入图片描述

b) 优缺点

优点:

实现简单、不需要额外内存且维表的更新延迟很低。

缺点:

每条数据都需要请求一次数据库,给数据库造成的压力很大;

访问数据库是同步调用,导致 subtak 线程会被阻塞,影响吞吐量;

关联是基于 Processing Time 的,结果并不具有确定性;

瓶颈在数据库端,但实时计算的流量通常远大于普通数据库的设计流量,因此可拓展性比较低。

c) 应用场景

适合流量比较低的作业,但通常不是最好的选择。

3.异步数据库查找关联
a) 概述

通过 AsyncIO 利用数据库提供的异步客户端,AsyncIO 可以并发地处理多个请求,很大程度上减少对 subtask 线程的阻塞。

在这里插入图片描述

b) 优缺点

优点:

实现简单

缺点:

有序输出模式下的 AsyncIO 需要缓存数据,且这些数据会被写入 checkpoint,占用内容资源;

相比数据库查找关联的吞吐量更高,但仍存在数据库负载高和结果不确定的问题。

c) 应用场景

适合流量低的实时计算。

4.带缓存的数据库查找关联
a) 概述

引入一层缓存来减少直接对数据库的请求,缓存一般不需要通过 checkpoint 持久化,可用 WeakHashMap 或 Guava Cache 实现。

在这里插入图片描述

b) 优缺点

优点:

数据库压力小;

缺点:

冷启动时会给数据库造成压力,后续取决于缓存命中率,数据库的压力将得到缓解;

维表的更新不能及时反应到关联操作上,需要根据维度表更新频率和业务对过时维表数据的容忍程度来设计缓存剔除的策略;

c) 应用场景

适合流量比较低,且对维表数据实时性要求不太高或维表更新比较少的业务场景。

3)预加载维表关联
1.概述

相比实时数据库查找在运行期间为每条数据访问一次数据库,预加载维表关联是在作业启动时就将维表读到内存中,在后续运行期间,每条数据都会和内存中的维表进行关联,而不会直接触发对数据库的访问。

与带缓存的实时数据库查找关联相比,区别是后者如果不命中缓存还可以 fallback 到数据库访问,而前者如果不命中则会关联不到数据。

2.启动预加载维表
a) 概述

在作业初始化时,比如用户函数的 open() 方法,直接从数据库将维表拷贝到内存中,维表不需要用 State 保存。

在这里插入图片描述

b) 优缺点

优点:

对数据库的压力只持续很短时间,在运行期间不需要再访问数据库。

缺点:

拷贝整个维表对 TaskManager 内存的要求较高;

运行期间维表数据不能更新。

c) 应用场景

适合于维表较小、变更实时性要求不高的场景,比如根据 ip 库解析国家地区,如果 ip 库有新版本,重启作业即可。

3.启动预加载分区维表
a) 概述

将数据流按字段分区,每个 Subtask 只需要加载对应分区范围的维表数据;

注意:

分区并不是用 keyby 这种通用的 hash 分区,而是需要根据业务数据定制化分区策略,调用 DataStream#partitionCustom;

比如按照 userId 的区间划分,0-999 划分到 subtask 1,1000-1999 划分到 subtask 2,在 open() 方法中,再根据 subtask 的 id 和总并行度来计算应该加载的维表数据范围。

在这里插入图片描述

b) 优缺点

优点:

维表的大小上限可以线性拓展,解决了维表大小受限于单个 TaskManager 内存的问题(取决于所有 TaskManager 的内存总量);

缺点:

设计和维护分区策略较复杂;

c) 应用场景

适合维表较大而变更实时性要求不高的场景,比如用户点击数据关联用户所在地。

4.启动预加载维表并定时刷新
a) 概述

引入定时刷新机制解决维度数据的更新问题;

定时刷新可以通过 Flink ProcessFucntion 提供的 Timer 或者在 open() 初始化一个线程(池)来完成;

在这里插入图片描述

b) 优缺点

优点:

复杂性小,缓解了维度表更新问题;

缺点:

给维表数据库带来更多压力,每次 reload 都是一次请求高峰。

c) 应用场景

适合维表变更实时性要求不高的场景;

取决于定时刷新的频率和数据库的性能,可以满足大部分关联维表的业务。

5.启动预加载维表 + 实时数据库查找
a) 概述

将预加载的维表作为缓存使用,若未命中则 fallback 到数据库查找。

在这里插入图片描述

b) 优缺点

优点:

相比冷启动时未命中缓存导致的多次实时数据库访问,直接拉取整个维表效率更高;

缺点:

可能拉取到不会访问的多余数据;

c) 应用场景

适合流量较低,且对维表数据实时性要求不高或维表更新较少的场景。

4)维表变更日志关联
1.概述

将维表以 changelog 数据流的方式表示,将维表关联转变为两个数据流的 join;

changelog 数据流类似于 MySQL 的 binlog,需要维表数据库端以 push 的方式将日志写到 Kafka 等消息队列中;

changelog 数据流称为 build 流,待关联的主要数据流成为 probe 流,可以获取某个 key 数据变化的时间,在关联中使用 Event Time 或 Processing Time。

2.Processing Time 维表变更日志关联
a) 概述

基于 Processing Time 关联,利用 keyby 将两个数据流中关联字段值相同的数据划分到 KeyedCoProcessFunction 的同一个分区,用 ValueState 或者 MapState 将维表数据保存下来。

在普通数据流的一条记录进到函数时,到 State 中查找有无符合条件的 join 对象,若有则关联输出结果,若无则根据 join 的类型决定是直接丢弃还是与空值关联。

**注意:**State 的大小要控制,首先只保存每个 key 最新的维度数据值,其次要给 State 设置 TTL,让 Flink 可以自动清理。

在这里插入图片描述

b) 优缺点

优点:

不需要直接请求数据库,不会对数据库造成压力;

利用 Flink 的 RocksDB StateBackend,将大部分的维表数据存在磁盘而不是内存中,并不会占用很高的内存;

缺点:

需要使用 changelog 在 Flink 应用端重新构建一个维表,会占用一定的 CPU 和比较多的内存和磁盘资源;

基于 Processing Time 的关联对两个数据流的延迟要求较高,当其中一个数据流出现 lag 时,可能会关联到未来时间点的维表数据。

c) 应用场景

适用于不便直接访问数据的场景(比如维表数据库是业务线上数据库,出于安全和负载的原因不能直接访问)

对维表的变更实时性要求较高的场景(因为数据准确性的关系,一般用 Event Time 关联会更好)

3.Event Time 维表变更日志关联
a) 概述

将维表 changelog 的多个时间版本都记录下来,每当一条记录进来,会找到对应时间版本的维表数据来关联,而不是总用最新版本,因此延迟数据的关联准确性将提高;

目前 State 并没有提供 Event Time 的 TTL,需要设计和实现 State 的清理策略,比如设置一个 Event Time Timer(注意 Timer 太多会导致性能问题),对于单个 key 只保存最近的 10 个版本,当有更新版本的维表数据到达时,要清理掉最老版本的数据。

在这里插入图片描述

**注意:**Event Time 要求 build 数据流的延迟低,否则可能一条数据到达时关联不到对应维表数据或者关联了过时版本的维表数据;

b) 优缺点

优点:

可以确保准确性;

缺点:

多个维表版本导致空间资源要求更大;

c) 应用场景

适合维表变更较多且对变更实时性要求较高的场景;

适合不便直接访问数据库的场景;

4.DataStream 的 Temporal Table Join
a) 概述

对两个数据流的输入都进行缓存,比起基于 Event Time 的维表变更日志关联,可以容忍任意数据流的延迟,数据准确性更好。

实现:

使用 CoProcessFunction,将 build 数据流以时间版本为 key 保存在 MapState 中,再将 probe 数据流和输出结果也用 State 缓存起来(同样以 Event Time 为 key),直到 Watermark 提升到它们对应的 Event Time,才把结果输出和将两个数据流的输入清理掉。

Watermark 触发是用 Event Time Timer 实现,但要注意不要为每条数据都设置一个 Timer,否则 Watermark 提升会触发多个 Timer 导致性能急剧下降。

建议为每个 key 只注册一个 Timer,记录当前未处理的最早的一个 Event Time,并用来注册 Timer,每当 Watermark 触发 Timer 时,检查未处理的最早 Event Time 到当前 Event Time 的所有数据,并将未处理的最早 Event Time 更新为当前时间。

在这里插入图片描述

注意:

如果维表变更太慢,导致 Watermark 提升太慢,会导致 probe 数据流被大量缓存,要确保 build 数据流尽量实时,同时给 Source 设置一个比较短的 idle timeout。

b) 优缺点

优点:

对两边数据流延迟的容忍度较大;

缺点:

会引入一定的输出结果的延迟;

因为吞吐量较大的 probe 数据流也需要缓存,对空间资源的需求较大;

c) 适用场景

适合对数据准确性要求高且可以容忍一定延迟(一般分钟级别)的业务。

2、Flink SQL 实现数据流的 Join
1.Regular Join
a) 概述

Regular Join 和离线 Hive SQL ⼀样,通过条件关联两条流数据输出。

b) 分类
  • Inner Join(Inner Equal Join):流任务中,只有两条流 Join 到才输出,输出 +[L, R]
  • Left Join(Outer Equal Join):流任务中,左流数据到达之后,⽆论有没有 Join 到右流的数据,都会输出(Join 到输出 +[L, R] ,没 Join 到输出 +[L, null] ),如果右流数据到达之后,发现左流之前输出过没有 Join 到的数据,则会发起回撤流,先输出 -[L, null] ,然后输出 +[L, R]
  • Right Join(Outer Equal Join):与 Left Join ⼀样,左表和右表的执⾏逻辑完全相反
  • Full Join(Outer Equal Join):流任务中,左流或者右流的数据到达之后,⽆论有没有 Join 到另外⼀条流的数据,都会输出(对右流来说:Join 到输出 +[L, R] ,没 Join 到输出 +[null, R] ;对左流来说:Join 到输出 +[L, R] ,没 Join 到输出 +[L, null] )。如果⼀条流的数据到达之后,发现另⼀条流之前输出过没有 Join 到的数据,则会发起回撤流(左流数据到达为例:回撤 -[null, R] ,输出+[L, R] ,右流数据到达为例:回撤 -[L, null] ,输出 +[L, R] )
c) 注意

实时 Regular Join 可以不是 等值 join,等值 join 和 ⾮等值 join 区别在于,等值 join 数据 shuffle 策略是 Hash,会按照 Join on 中的等值条件作为 id 发往对应的下游;⾮等值 join 数据 shuffle 策略是 Global,所有数据发往⼀个并发,按照⾮等值条件进⾏关联。

在这里插入图片描述

Join 的流程是左流新来⼀条数据后,会和右流中符合条件的所有数据做 Join,然后输出。

流的上游是⽆限的数据,关联需要 Flink 将两条流的所有数据都存储在 State 中,所以 Flink 任务的 State 会⽆限增⼤,需要为 State 配置合适的 TTL,以防⽌ State 过⼤。

2.Interval Join
a) 概述

Interval Join 可以让⼀条流去 Join 另⼀条流中前后⼀段时间内的数据。

b) 分类
  • Inner Interval Join:流任务中,只有两条流 Join 到(满⾜ Join on 中的条件:两条流的数据在时间区间 + 满⾜其他等值条件)才输出,输出 +[L, R]
  • Left Interval Join:流任务中,左流数据到达之后,如果没有 Join 到右流的数据,就会等待(放在 State 中等),如果右流之后数据到达,发现能和刚刚那条左流数据 Join 到,则会输出 +[L,R] 。事件时间中随着 Watermark 的推进(也⽀持处理时间)。如果发现发现左流 State 中的数据过期了,就把左流中过期的数据从 State 中删除,然后输出 +[L, null] ,如果右流 State 中的数据过期了,就直接从 State 中删除。
  • Right Interval Join:和 Left Interval Join 执⾏逻辑⼀样,只不过左表和右表的执⾏逻辑完全相反。
  • Full Interval Join:流任务中,左流或者右流的数据到达之后,如果没有 Join 到另外⼀条流的数据,就会等待(左流放在左流对应的 State 中等,右流放在右流对应的 State 中等),如果之后另⼀条流数据到达之后,发现能和刚刚那条数据 Join 到,则会输出 +[L, R] 。事件时间中随着 Watermark 的推进(也⽀持处理时间),发现 State 中的数据过期了,就将这些数据从 State 中删除并且输出(左流过期输出+[L, null] ,右流过期输出 -[null, R] )

**Inner Interval Join 和 Outer Interval Join 的区别在于:**随着时间推移的过程中,如果有数据过期了之后,会根据是否是 Outer 将没有 Join 到的数据也给输出。

c) 注意

实时 Interval Join 可以不是 等值 join ,等值 join 和 ⾮等值 join 区别在于,等值 join 数据 shuffle 策略是 Hash,会按照 Join on 中的等值条件作为 id 发往对应的下游;⾮等值 join 数据 shuffle 策略是 Global,所有数据发往⼀个并发,将满⾜条件的数据关联输出。

3.Temporal Join
a) 概述

同离线中的 拉链快照表 ,Flink SQL 中对应的表叫做 Versioned Table ,使⽤⼀个明细表去 join 这个 Versioned Table 的 join 操作叫做 Temporal Join。

Temporal Join 中,Versioned Table 是对同⼀条 key(在 DDL 中以 primary key 标记同⼀个 key)的历史版本(根据时间划分版本)做维护,当有明细表 Join 这个表时,可以根据明细表中的时间版本选择 Versioned Table 对应时间区间内的快照数据进⾏ join。

b) Verisoned Table

Verisoned Table 中存储的数据通常来源于 CDC 或者会发⽣更新的数据,Flink SQL 会为 Versioned Table 维护 Primary Key 下的所有历史时间版本的数据。

c) 注意

事件时间的 Temporal Join ⼀定要给左右两张表都设置 Watermark。

事件时间的 Temporal Join ⼀定要把 Versioned Table 的主键包含在 Join on 的条件中。

4.Lookup Join(维表 Join)
a) 概述

Lookup Join 是维表 Join,实时数仓场景中,实时获取外部缓存。

b) 注意

同⼀条数据关联到的维度数据可能不同;

会发⽣实时的新建及更新的维表应该建⽴起数据延迟的监控,防⽌流表数据先于维表数据到达,关联不到维表数据;

5.Time-Windowed Join

利用窗口给两个输入表设定一个 Join 的时间界限,超出时间范围的数据则对 JOIN 不可见并可以被清理掉;

时间可以是指计算发生的系统时间(即 Processing Time),也可以是指从数据本身的时间字段提取的 Event Time;

如果是 Processing Time,Flink 根据系统时间自动划分 Join 的时间窗口并定时清理数据;如果是 Event Time,Flink 分配 Event Time 窗口并依据 Watermark 来清理数据。

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

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

相关文章

源头厂家定制直线度测量仪 在线与离线检测均可

直线度的检测不再局限于直尺法、重力法等人工检测方式,随着自动化的发展,直线度检测也更需要自动化方便快捷的检测仪器。为此,研发了在线直线度测量仪与离线直线度测量仪,根据不同的需要,选择合适的设备即可。 数据计…

轻量检测模型PP-PicoDet解析

Paper:PP-PicoDet: A Better Real-Time Object Detector on Mobile Devices official implementation:https://github.com/PaddlePaddle/PaddleDetection/tree/release/2.7/configs/picodet Backbone 作者通过实验发现,ShuffleNetV2在移动…

NeRF-RPN: A general framework for object detection in NeRFs 全文翻译

摘要 Abstract 本文提出了第一个重要的物体检测框架 NeRF-RPN,它直接在 NeRF 上运行。给定一个预先训练好的 NeRF 模型,NeRF-RPN 的目标是检测场景中所有物体的边界框。通过利用包含多尺度三维神经体积特征的新颖体素表示法,我们证明…

ubuntu环境安装配置nginx流程

今天分享ubuntu环境安装配置nginx流程 一、下载安装 1、检查是否已经安装 nginx -v 结果 2、安装 apt install nginx-core 过程 查看版本:nginx -v 安装路径:whereis nginx nginx文件安装完成之后的文件位置: /usr/sbin/nginx&#xf…

Axure鲜花商城网站原型图,网上花店订花O2O本地生活电商平台

作品概况 页面数量:共 30 页 兼容软件:仅支持Axure RP 9/10,非程序软件无源代码 应用领域:鲜花网、花店网站、本地生活电商 作品特色 本作品为「鲜花购物商城」网站模板,高保真高交互,属于O2O本地生活电…

OpenVINS学习5——VioManager.cpp/h学习与注释

前言 之前又看到说VioManager.cpp/h是OpenVINS中的核心程序,这次就看看这里面都写了啥,整体架构什么样,有哪些函数功能。具体介绍: VioManager类 整体分析 VioManager类包含 MSCKF 工作所需的状态和其他算法。我们将测量结果输…

python的课后练习总结3之条件语句

1,简单点,只有IF IF 后面加入条件然后冒号: 条件成立执行的代码1 条件成立执行的代码2 条件是否成立都执行的代码 身高 float(input(请输入你的身高(米):)) if 身高 > 1.3:print(f您的身高是{身高}米,请您买票) print(祝您旅途愉快) 2,IF 加个else if 条件:…

Spring AOP的环境搭建、切入点表达式、通知注解

Spring AOP的实现 Spring AOP环境搭建AOP坐标依赖引入添加xml配置实现三层架构 定义切入点Pointcut("匹配规则")切入点表达式1. 执行所有的公共方法2.执行任意的set方法3.设置指定包下的任意类的任意方法 (指定包: com.svt.service)4.设置指定包及于包下的任意类的任…

用 Python 抓取 bilibili 弹幕并分析!

01 实现思路 首先,利用哔哩哔哩的弹幕接口,把数据保存到本地。接着,对数据进行分词。最后,做了评论的可视化。 02 弹幕数据 平常我们在看视频时,弹幕是出现在视频上的。实际上在网页中,弹幕是被隐藏在源代码…

【熔断限流组件resilience4j和hystrix】

文章目录 🔊博主介绍🥤本文内容起因resilience4j落地实现pom.xml依赖application.yml配置接口使用 hystrix 落地实现pom.xml依赖启动类上添加注解接口上使用 📢文章总结📥博主目标 🔊博主介绍 🌟我是廖志伟…

【期末复习向】数据可视化技术

一、重点复习 题型:填空题(15道,2分一个)与简答题(3道题目,10分一个)与绘图题(选画2个类型的图) 1.什么是数据可视化 在计算机视觉领域,数据可视化是对数据的…

Linux 进程(八) 进程的退出码

main 函数的返回值叫做进程的退出码。当进程成功退出的时候,我们一般用0来表示。进程失败的时候一般用非零来表示。我们使用不同的数字来表示进程退出时不同的失败原因。 我们查看系统的有多少退出码以及其含义时需要用到strerror() 他的头文件和用法如下。 通过一…

CSS 放大旋转动画

<template><div class"container" mouseenter"startAnimation" mouseleave"stopAnimation"><!-- 旋方块 --><div class"box" :class"{ rotate-scale-up: isAnimating }"><!-- 元素内容 -->&l…

从零开始搭建企业级前端项目模板(vue3+vite+ts)

文章目录 主要内容一、vite脚手架工具初始化项目二、项目代码加入eslint校验和自动格式化2.1安装对应依赖插件2.2 配置script脚本&#xff0c;项目安装eslint配置2.3 安装完成后&#xff0c;后面启动项目还缺少一些依赖&#xff0c;提前按需安装好 三&#xff0c;修改eslintrc.…

3D目标检测(教程+代码)

随着计算机视觉技术的不断发展&#xff0c;3D目标检测成为了一个备受关注的研究领域。与传统的2D目标检测相比&#xff0c;3D目标检测可以在三维空间中对物体进行定位和识别&#xff0c;具有更高的准确性和适用性。本文将介绍3D目标检测的相关概念、方法和代码实现。 一、3D目…

2023年12月青少年软件编程Python等级考试(三级)真题试卷

2023年12月青少年软件编程Python等级考试&#xff08;三级&#xff09;真题试卷 题目总数&#xff1a;38 总分数&#xff1a;100 选择题 第 1 题 单选题 一个非零的二进制正整数&#xff0c;在其末尾添加两个“0”&#xff0c;则该新数将是原数的&#xff1f;&#x…

nuxt3 env文件、全局变量处理

有两种方向 通过配置nuxt.config.ts Nuxt提供的钩子函数&#xff0c;实现全局变量的获取 runtimeconfig env文件往runtimeconfig放入内容 useAppConfig 通过env文件配置来获取服务端全局变量&#xff0c;客户端通过vite.define实现 nuxt.config.ts Nuxt钩子 1. runtim…

Win32 TEXT()宏学习

之前学习了_T()宏&#xff1b; _T()是MFC的&#xff1b; TEXT()是win32的&#xff1b; _T("")定义于tchar.h&#xff1b; TEXT宏是windows程序设计中经常遇到的宏&#xff0c;定义在 <winnt.h>中&#xff1b; 如果使用UNICODE字符集&#xff0c;则TEXT&…

kubernetes(三)

文章目录 1. k8s弹性伸缩1.1 安装heapster监控1.2 弹性伸缩使用和验证 2. 持久化存储2.1 emptyDir 1. k8s弹性伸缩 k8s弹性伸缩&#xff0c;需要附加插件heapster 1.1 安装heapster监控 使用heapster(低版本)可以监控pod压力大不大 使用hpa调节pod数量&#xff0c;自动扩容或…

chatgpt3.5和chatgpt4的区别

ChatGPT4是基于GPT-3模型的一个实例&#xff0c;但ChatGPT4已经进行了进一步的改进和优化。GPT-3&#xff08;第三代生成式预训练模型&#xff09;是OpenAl开发的一个大型语言模型&#xff0c;它在很多自然语言处理任务中表现出色。 ChatGPT4继承了GPT-3的基本架构和能力&…