Flink多流处理之Broadcast(广播变量)
写过Spark批处理的应该都知道,有一个广播变量broadcast
这样的一个算子,可以优化我们计算的过程,有效的提高效率;同样在Flink中也有broadcast
,简单来说和Spark中的类似,但是有所区别,首先Spark中的broadcast
是静态的数据,而Flink中的broadcast
是动态的,也就是源源不断的数据流.在Flink中会将广播的数据存到state
中.
在Flink中主流数据可以获取state
中的所有状态数据,使用过window
的应该都清楚,当两个streamData
中的数据到达窗口的时间刚好错过时就会发生关联不上的情况,如window
是2S
,sreamData1
到达窗口的时间刚好卡在这个2S
窗口的尾端,而streamData
到达窗口时,这个窗口已经结束了,这种情况就算这两条数据有相同id
也无法进行关联了.
但是broadcast
会将到达的数据都存储在state
中,这样主流到达的每一条数据都可以和state
中的广播流数据进行关联比较.
流程图内容可能不够准确,只是为了看起来方便理解.
- 数据源
# 主流数据 ➜ ~ nc -lk 1234 101,浏览商品,2023-08-02 102,浏览商品,2023-08-02 103,查看商品价格,2023-08-04 101,商品加入购物车,2023-08-03 101,从购物车删除商品,2023-08-03 102,下单,2023-08-02 102,申请延期发货,2023-08-03 103,点击商品详情页,2023-08-04 104,点击收藏,2023-08-05 104,下单,2023-08-05 104,付款,2023-08-06 105,浏览商品,2023-08-07 106,浏览商品,2023-08-07 106,加入购物车,2023-08-08 107,浏览商品,2023-08-10
# 广播流数据 ➜ ~ nc -lk 5678 101,小明 102,张丽 103,公孙飞天 104,王二虎 106,李四 108,赵屋面
- 代码
import org.apache.flink.api.common.state.BroadcastState; import org.apache.flink.api.common.state.MapStateDescriptor; import org.apache.flink.api.common.state.ReadOnlyBroadcastState; import org.apache.flink.api.common.typeinfo.TypeHint; import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.api.java.tuple.Tuple3; import org.apache.flink.streaming.api.datastream.*; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.api.functions.co.BroadcastProcessFunction; import org.apache.flink.util.Collector;/*** @Author: J* @Version: 1.0* @CreateTime: 2023/8/11* @Description: 多流操作-广播流**/ public class FlinkBroadcast {public static void main(String[] args) throws Exception {// 构建流环境StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();// 设置并行度env.setParallelism(3);// 数据集源1作为主流数据(用户行为日志[id,behavior,date])DataStreamSource<String> sourceStream1 = env.socketTextStream("localhost", 1234);// 将字符串切割处理SingleOutputStreamOperator<Tuple3<String, String, String>> mainSourceStream = sourceStream1.map(str -> Tuple3.of(str.split(",")[0], str.split(",")[1], str.split(",")[2])).returns(new TypeHint<Tuple3<String, String, String>>() {});// 数据源2作为广播流数据(用户信息(id,name))DataStreamSource<String> sourceStream2 = env.socketTextStream("localhost", 5678);// 将字符串切割处理SingleOutputStreamOperator<Tuple2<String, String>> mapStream2 = sourceStream2.map(str -> Tuple2.of(str.split(",")[0], str.split(",")[1])).returns(new TypeHint<Tuple2<String, String>>() {});// 将广播流数据源进行广播/***参数说明* 这里需要我们传入一个MapStateDescriptor,其实就是一个Map结构的数据<k,v>* <String, Tuple2<String, String>>,第一个String类型就是广播流和主流连接的字段,在这个代码中就是id,由实际业务决定* <String, Tuple2<String, String>>,第二个Tuple2<String, String>就是实际广播数据流的数据,由实际业务决定* "userInfo"就是给一个名字,这个自定义无强制要求**/// 先构建一个状态,后面也会使用MapStateDescriptor<String, Tuple2<String, String>> userInfoState = new MapStateDescriptor<>("userInfo", TypeInformation.of(String.class), TypeInformation.of(new TypeHint<Tuple2<String, String>>() {}));BroadcastStream<Tuple2<String, String>> userInfoBroadStream = mapStream2.broadcast(userInfoState);// 将主流数据和广播流数据使用connect连接/*** 我们将数据转变成广播流之后,在Flink中也不知哪个数据流需要使用这个广播流(userInfoBroadStream),* 这个时候就需要我们自己将主流数据和该广播流数据进行连接**/BroadcastConnectedStream<Tuple3<String, String, String>, Tuple2<String, String>> connectedStream = mainSourceStream.connect(userInfoBroadStream);/*** 在process()中有两类函数供我们选择,KeyedBroadcastProcessFunction和BroadcastProcessFunction,* 这里要注意当"connectedStream"是KeyedStream时选择KeyedBroadcastProcessFunction* 当"connectedStream"不是KeyedStream时选择BroadcastProcessFunction就可以.* 使用keyBy算子返回的就是KeyedStream**/SingleOutputStreamOperator<String> resultStream = connectedStream.process(new BroadcastProcessFunction<Tuple3<String, String, String>, Tuple2<String, String>, String>() {// 这个方法写主流数据处理逻辑@Overridepublic void processElement(Tuple3<String, String, String> value, BroadcastProcessFunction<Tuple3<String, String, String>, Tuple2<String, String>, String>.ReadOnlyContext ctx, Collector<String> out) throws Exception {/*** 要注意,这里我们最好从ReadOnlyContext来获取广播状态数据,因为获取只读的状态数据可以保证数据的安全性,* 如果是通过成员变量的方式获取可修改的状态数据,就会存在数据不安全的问题,如在代码逻辑中出现了对状态数据* 修改的代码,那么共享此状态的并行算子可能看到的状态数据不一致,就会导致数据错误或者代码报错.* 而使用ReadOnlyContext就可以保证processElement这个方法中我们只对状态数据进行读取.**/ReadOnlyBroadcastState<String, Tuple2<String, String>> broadcastState = ctx.getBroadcastState(userInfoState);if (broadcastState != null) {// 通过主流中的ID作为key获取广播变量中的用户信息Tuple2<String, String> userInfo = broadcastState.get(value.f0);// 输出数据的形式(id,behavior,date,name)if (userInfo == null) {out.collect(value.f0 + "," + value.f1 + "," + value.f2 + "," + "NULL");} else {out.collect(value.f0 + "," + value.f1 + "," + value.f2 + "," + userInfo.f1);}} else {out.collect(value.f0 + "," + value.f1 + "," + value.f2 + "," + "NULL");}}// 这个方法写广播流数据处理逻辑@Overridepublic void processBroadcastElement(Tuple2<String, String> value, BroadcastProcessFunction<Tuple3<String, String, String>, Tuple2<String, String>, String>.Context ctx, Collector<String> out) throws Exception {// 使用Context获取状态BroadcastState<String, Tuple2<String, String>> broadcastState = ctx.getBroadcastState(userInfoState);// 将数据存入到状态中broadcastState.put(value.f0, value);}});// 打印结果resultStream.print();env.execute("Flink broadcast");} }
- 结果
代码内容就不进行详细解释了,注释基本都写清楚了,如有疑问可评论提问,共同探讨.3> 101,浏览商品,2023-08-02,小明 3> 101,商品加入购物车,2023-08-03,小明 3> 102,申请延期发货,2023-08-03,张丽 3> 104,下单,2023-08-05,王二虎 3> 106,浏览商品,2023-08-07,李四 1> 102,浏览商品,2023-08-02,张丽 1> 101,从购物车删除商品,2023-08-03,小明 1> 103,点击商品详情页,2023-08-04,公孙飞天 1> 104,付款,2023-08-06,王二虎 1> 106,加入购物车,2023-08-08,李四 2> 103,查看商品价格,2023-08-04,公孙飞天 2> 102,下单,2023-08-02,张丽 2> 104,点击收藏,2023-08-05,王二虎 2> 105,浏览商品,2023-08-07,NULL 2> 107,浏览商品,2023-08-10,NULL
相关文章:

Flink多流处理之Broadcast(广播变量)
写过Spark批处理的应该都知道,有一个广播变量broadcast这样的一个算子,可以优化我们计算的过程,有效的提高效率;同样在Flink中也有broadcast,简单来说和Spark中的类似,但是有所区别,首先Spark中的broadcast是静态的数据,而Flink中的broadcast是动态的,也就是源源不断的数据流.在…...

LVS/DR+Keepalived负载均衡实战(一)
引言 负载均衡这个概念对于一个IT老鸟来说再也熟悉不过了,当听到此概念的第一反应是想到举世闻名的nginx,但殊不知还有一个大名鼎鼎的负载均衡方案可能被忽略了,因为对于一般系统来说,很多应用场合中采用nginx基本已经满足需求&a…...
测试DWPose的onnx +Unity barracuda
环境: Unity Barracuda 3.0.1 从github直接拉取的barracuda仓库才能装到这个版本Barracuda以后不再升级了,会迁移到Unity AI大计划里的Sentis 我想申请的来着但好像已经不开放了 Unity 2021.3.20模型:dw-ll_ucoco_384.onnx 报了一些错&…...

轻装上阵,不调用jar包,用C#写SM4加密算法【卸载IKVM 】
前言 记得之前写了一个文章,是关于java和c#加密不一致导致需要使用ikvm的方式来进行数据加密,主要是ikvm把打包后的jar包打成dll包,然后Nuget引入ikvm,从而实现算法的统一,这几天闲来无事,网上找了一下加密…...

redis学习笔记(一)
文章目录 一、引言二、redis介绍2.1、定义2.2、Redis的数据类型及主要特性2.3、Redis的应用场景有哪些? 三、redis环境安装3.1、下载和安装 一、引言 在Web应用发展的初期,那时关系型数据库受到了较为广泛的关注和应用,原因是因为那时候Web站…...
最优化问题 - 拉格朗日对偶
primal 原问题 dual 对偶问题 目标函数 约束条件 可行域D 对偶专题 “拉格朗日对偶问题”如何直观理解?“KKT条件” “Slater条件” “凸优化”打包理解——bilibili 王木头 拉格朗日乘子法与对偶问题...

关于ISO27701隐私信息安全管理体系介绍
01 什么是ISO27701 ISO27701是对ISO27001信息安全管理和ISO27002安全控制的隐私扩展,全称《安全技术—扩展ISO27001和ISO27002的隐私信息管理—要求与指南》,是ISO标准委员会以ISO 27001为基准,以ISO27552为蓝本,建立发布的隐私…...

C语言案例 分数列求和-11
题目:有一分数列:2 / 1,3 / 2,5 / 3,8 / 5,13 / 8,21 / 13 …求出这个数列的前20项之和。 程序分析 这是一个典型的分数列数学逻辑题,考究这类题目是需要从已知的条件中找到它们的分布规律 我们把前6荐的分子与分母分别排列出来,…...

Git 入门
一、版本控制 1.1 什么是版本控制 版本控制(Revision control)是一种在开发的过程中用于管理我们对文件、目录或工程等内容的修改历史,方便查看更改历史记录,备份以便恢复以前的版本的软件工程技术。简单说就是用于管理多人协同开…...
PAT 1010 Radix
个人学习记录,代码难免不尽人意 Given a pair of positive integers, for example, 6 and 110, can this equation 6 110 be true? The answer is yes, if 6 is a decimal number and 110 is a binary number. Now for any pair of positive integers N 1and N 2…...

ruoyi-cloud微服务新建子模块
目录 相关文章1、复制system模块2、在modules下的 pom.xml文件中添加子模块 test3、进入 test模块修改 pom.xml4、修改对应的包名、目录名和启动应用程序为test5、修改bootstrap.yml文件中的端口号和应用名称6、nacos中克隆 system-dev.yml的配置,修改名称为 test-d…...
Dijkstra(求最短路)
时间复杂是 O(n2m) ,n 表示点数,m 表示边数 模板(朴素法一般m等于n^2的时候使用) #include<bits/stdc.h> #include<algorithm> using namespace std; const int N510; int g[N][N]; //为稠密阵所以用邻接矩阵存储 int dist[N]; //用…...
React 脚手架
1.React 定义 React 脚手架(React boilerplate)是一种预先设置好的、可以快速启动 React 项目的工具。脚手架已经包含了 React、Webpack、Babel、ESLint、Jest 等一些常用的工具和库,并已经配置好了这些工具的参数,可以直接使用和…...

CTFSHOW php命令执行
目录 web29 过滤flag web30 过滤system php web31 过滤 cat|sort|shell|\. 这里有一个新姿势 可以学习一下 web32 过滤 ; . web33 web34 web35 web36 web37 data伪协议 web38 短开表达式 web39 web40 __FILE__命令的扩展 web41 web42 重定向…...
侧滑置顶,取消置顶
第一步:布局 <?xml version"1.0" encoding"utf-8"?> <com.ddmh.magic.camera.ui.widget.SwipeMenuLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.android.com/apk/res-auto"…...

Pycharm解决启动时候索引慢的问题
设置里去掉update里面的两个勾 shared indexes中,把自动下载索引改成不下载使用本地索引...
Http请求响应时间一般划分标准
HTTP请求的响应时间被认为是长或短通常取决于具体应用场景和性能需求。一般来说,以下是一些常见的对HTTP请求响应时间进行划分的标准: 即时响应:通常在毫秒级别的响应时间被认为是即时响应。这适用于对实时性要求较高的应用,如实时…...

生成测试报告,在Unittest框架中就是简单
测试套件(Test Suite)是测试用例、测试套件或两者的集合,用于组装一组要运行的测试(多个测试用例集合在一起)。 (1)创建一个测试套件: import unittest suite unittest.TestSuite…...
生成式人工智能的潜在有害影响与未来之路(一)
这是本文的第1版,反映了截至2023年5月15日,Generative AI的已记载的和预期的危害。由于Generative AI的发展、使用和危害的快速变化,我们承认这是一篇内在的动态论文,未来会发生变化。 在本文中,我们使用一种标准格式…...
lightdb23.3 表名与包名不能重复
LightDB 表名与包名不能重复 从 LightDB 23.3 版本开始表名和包名不能重复,与 oracle 一致。原先已已支持包名和schema名不能重复。 背景 在之前版本在同一schema 下可以创建相同名字的表和包。这会导致在存储过程中使用%type指定变量类型时,如果存在…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...

地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...

Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...