Apache Flink中的广播状态实用指南
感谢英文原文作者:https://data-artisans.com/blog/a-practical-guide-to-broadcast-state-in-apache-flink
不过,原文最近好像不能访问了。应该是https://www.da-platform.com/网站移除了blog板块了。
从版本1.5.0开始,Apache FlinkⓇ具有一种新的状态,称为广播状态。
在这篇文章中,我们解释了广播状态是什么,并展示了如何将其应用于评估事件流上的动态模式的应用程序的示例。我们将引导您完成处理步骤和源代码,以实现此应用程序。
什么是广播状态?
广播状态可用于以特定方式组合和联合处理两个事件流。第一个流的事件被广播到运营商的所有并行实例,这些实例将它们维持为状态。
不广播另一个流的事件,而是将其发送到同一运营商的各个实例,并与广播流的事件一起处理。
新的广播状态非常适合需要加入低吞吐量和高吞吐量流或需要动态更新其处理逻辑的应用程序。
我们将使用后一个用例的具体示例来解释广播状态,并在本文的其余部分更详细地展示其API。
广播状态下的动态模式评估
想象一下,一个电子商务网站将所有用户的交互捕获为用户操作流。运营该网站的公司有兴趣分析交互以增加收入,改善用户体验,以及检测和防止恶意行为。
该网站实现了一个流应用程序,用于检测用户事件流上的模式。
但是,公司希望每次模式更改时都避免修改和重新部署应用程序。相反,应用程序在从模式流接收新模式时摄取第二个模式流并更新其活动模式。
在下文中,我们将逐步讨论此应用程序,并展示它如何利用Apache Flink中的广播状态功能。

我们的示例应用程序摄取了两个数据流。
第一个流在网站上提供用户操作,并在上图的左上方显示。用户交互事件包括操作的类型(用户登录,用户注销,添加到购物车或完成付款)和用户的ID,其由颜色编码。
图示中的用户动作事件流包含用户1001的注销动作,其后是用户1003的支付完成事件,以及用户1002的“添加到购物车”动作。
第二流提供应用将执行的动作模式。评估。模式由两个连续的动作组成。在上图中,模式流包含以下两个:
- 模式#1:用户登录并立即注销而无需浏览电子商务网站上的其他页面。
- 模式#2:用户将商品添加到购物车并在不完成购买的情况下注销。
这些模式有助于企业更好地分析用户行为,检测恶意行为并改善网站体验。
例如,如果项目被添加到购物车而没有后续购买,网站团队可以采取适当的措施来更好地了解用户未完成购买的原因并启动特定程序以改善网站转换(如提供折扣代码,限时免费送货优惠等)
在右侧,该图显示了操作员的三个并行任务,即摄取模式和用户操作流,评估操作流上的模式,并在下游发出模式匹配。
为简单起见,我们示例中的运算符仅评估具有两个后续操作的单个模式。当从模式流接收到新模式时,替换当前活动模式。
原则上,还可以实现运算符以同时评估更复杂的模式或多个模式,这些模式可以单独添加或移除。
我们将描述模式匹配应用程序如何处理用户操作和模式流。


首先,将模式发送给操作员。该模式被广播到运营商的所有三个并行任务。任务将模式存储在其广播状态中。由于广播状态只应使用广播数据进行更新,因此所有任务的状态始终预期相同。


接下来,第一个用户操作按用户ID分区并发送到操作员任务。分区可确保同一用户的所有操作都由同一任务处理。上图显示了操作员任务消耗第一个模式和前三个操作事件后应用程序的状态。
当任务收到新的用户操作时,它会通过查看用户的最新和先前操作来评估当前活动的模式。
对于每个用户,操作员将先前的操作存储在键控状态。由于上图中的任务到目前为止仅为每个用户收到了一个操作(我们刚刚启动了应用程序),因此不需要评估该模式。
最后,用户键控状态中的先前操作被更新为最新动作,以便能够在同一用户的下一个动作到达时查找它。

在处理前三个动作之后,下一个事件(用户1001的注销动作)被运送到处理用户1001的事件的任务。
当任务接收到动作时,它从广播状态中查找当前模式并且用户1001的先前操作。由于模式匹配两个动作,因此任务发出模式匹配事件。
最后,任务通过使用最新操作覆盖上一个事件来更新其键控状态。

当新模式到达模式流时,它被广播到所有任务,并且每个任务通过用新模式替换当前模式来更新其广播状态。


一旦用新模式更新广播状态,匹配逻辑就像之前一样继续,即,用户动作事件由密钥分区并由负责任务评估。
如何使用广播状态实现应用程序?
到目前为止,我们在概念上讨论了该应用程序并解释了它如何使用广播状态来评估事件流上的动态模式。
接下来,我们将展示如何使用Flink的DataStream API和广播状态功能实现示例应用程序。
让我们从应用程序的输入数据开始。我们有两个数据流,操作和模式。
在这一点上,我们并不关心流来自何处。这些流可以从Apache Kafka或Kinesis或任何其他系统中摄取。并与各两个字段的POJO:
DataStream<Action> actions = ???
DataStream<Pattern> patterns = ???
ActionPattern
Action:Long userId,String actionPattern:,String firstActionString secondAction
作为第一步,我们在属性上键入操作流。接下来,我们准备广播状态。广播状态始终表示为 Flink提供的最通用的状态原语。
由于我们的应用程序一次只评估和存储一个,我们将广播状态配置为具有键类型和值类型。该总是存储在与关键。
使用 广播状态,我们在流上应用转换并接收a 。在我们获得了密钥 流和广播流之后,我们都流式传输并应用了一个userId
KeyedStream<Action, Long> actionsByUser = actions
.keyBy((KeySelector<Action, Long>) action -> action.userId); MapState
MapStateDescriptor<Void, Pattern> bcStateDescriptor =
new MapStateDescriptor<>(
"patterns", Types.VOID, Types.POJO(Pattern.class)); PatternMapStateVoidPatternPatternMapStatenull
BroadcastStream<Pattern> bcedPatterns = patterns.broadcast(bcStateDescriptor); MapStateDescriptorbroadcast()patternsBroadcastStream bcedPatterns
DataStream<Tuple2<Long, Pattern>> matches = actionsByUser
.connect(bcedPatterns)
.process(new PatternEvaluator());
PatternEvaluator是一个实现接口的自定义函数。
它应用我们之前讨论过的模式匹配逻辑,并发出包含用户ID和匹配模式的记录。该 接口提供了三种处理记录和发出结果的方法。
public static class PatternEvaluator
extends KeyedBroadcastProcessFunction<Long, Action, Pattern, Tuple2<Long, Pattern>> { // handle for keyed state (per user)
ValueState<String> prevActionState; @Override
public void open(Configuration conf) {
// initialize keyed state
prevActionState = getRuntimeContext().getState(
new ValueStateDescriptor<>("lastAction", Types.STRING));</code
}
/**
* Called for each user action.
* Evaluates the current pattern against the previous and
* current action of the user.
*/
@Override
public void processElement(
Action action,
ReadOnlyContext ctx,
Collector<Tuple2<Long, Pattern>> out) throws Exception {
// get current pattern from broadcast state
Pattern pattern = ctx
.getBroadcastState(
new MapStateDescriptor<>("patterns", Types.VOID, Types.POJO(Pattern.class)))
// access MapState with null as VOID default value
.get(null);
// get previous action of current user from keyed state
String prevAction = prevActionState.value();
if (pattern != null && prevAction != null) {
// user had an action before, check if pattern matches
if (pattern.firstAction.equals(prevAction) &&
pattern.secondAction.equals(action.action)) {
// MATCH
out.collect(new Tuple2<>(ctx.getCurrentKey(), pattern));
}
}
// update keyed state and remember action for next pattern evaluation
prevActionState.update(action.action);
}
/**
* Called for each new pattern.
* Overwrites the current pattern with the new pattern.
*/
@Override
public void processBroadcastElement(
Pattern pattern,
Context ctx,
Collector<Tuple2<Long, Pattern>> out) throws Exception {
// store the new pattern by updating the broadcast state
BroadcastState<Void, Pattern> bcState =
ctx.getBroadcastState(new MapStateDescriptor<>("patterns", Types.VOID, Types.POJO(Pattern.class)));
// storing in MapState with null as VOID default value
bcState.put(null, pattern);
}
}
KeyedBroadcastProcessFunction
processBroadcastElement()为广播流的每个记录调用。在我们的 函数中,我们只是使用键将接收到的记录放入广播状态(记住,我们只存储一个模式)。PatternEvaluatorPatternnullMapStateprocessElement()为键控流的每个记录调用。它提供对广播状态的只读访问,以防止修改导致跨函数的并行实例的不同广播状态。 从广播状态检索当前模式的方法和从键控状态检索用户的先前动作。如果两者都存在,则检查先前和当前操作是否与模式匹配,并且如果是这种情况则发出模式匹配记录。最后,它将键控状态更新为当前用户操作。processElement()PatternEvaluatoronTimer()在先前注册的计时器触发时调用。定时器可以在任何处理方法中注册,并用于执行计算或将来清理状态。我们在示例中没有实现此方法以保持代码简洁。但是,当用户在一段时间内未处于活动状态时,它可用于删除用户的最后一个操作,以避免由于非活动用户而导致状态增长。
您可能已经注意到了处理方法的上下文对象。上下文对象提供对其他功能的访问,例如KeyedBroadcastProcessFunction
- 广播状态(读写或只读,取决于方法),
- A,可以访问记录的时间戳,当前的水印,以及可以注册计时器,
TimerService - 当前密钥(仅适用于 ),和
processElement() - 一种将函数应用于每个注册密钥的键控状态的方法(仅适用于)
processBroadcastElement()
在具有就像任何其他ProcessFunction完全进入状态弗林克和时间特性,因此可以用来实现复杂的应用程序逻辑。广播状态被设计为适应不同场景和用例的多功能特性。虽然我们只讨论了一个相当简单且受限制的应用程序,但您可以通过多种方式使用广播状态来实现应用程序的要求。KeyedBroadcastProcessFunction
结论
在这篇博文中,我们向您介绍了一个示例应用程序,以解释Apache Flink的广播状态以及它如何用于评估事件流上的动态模式。我们还讨论了API并展示了我们的示例应用程序的源代码。
我们邀请您查看Apache Flink网站上的文档,并通过Apache Flink 邮件列表提供反馈或建议以进一步改进。
Apache Flink中的广播状态实用指南的更多相关文章
- 如何在 Apache Flink 中使用 Python API?
本文根据 Apache Flink 系列直播课程整理而成,由 Apache Flink PMC,阿里巴巴高级技术专家 孙金城 分享.重点为大家介绍 Flink Python API 的现状及未来规划, ...
- Flink 从0到1学习 —— Flink 中如何管理配置?
前言 如果你了解 Apache Flink 的话,那么你应该熟悉该如何像 Flink 发送数据或者如何从 Flink 获取数据.但是在某些情况下,我们需要将配置数据发送到 Flink 集群并从中接收一 ...
- 《Android Studio实用指南》7.1 AndroidStudio代码检查工具概述
本文节选自<Android Studio实用指南> 作者: 毕小朋 目前本书已上传到百度阅读, 在百度中搜索[Anroid Studio实用指南]便可以找到本书. Android Stud ...
- State Processor API:如何读取,写入和修改 Flink 应用程序的状态
过去无论您是在生产中使用,还是调研Apache Flink,估计您总是会问这样一个问题:我该如何访问和更新Flink保存点(savepoint)中保存的state?不用再询问了,Apache Flin ...
- Apache Flink 漫谈系列 - JOIN 算子
聊什么 在<Apache Flink 漫谈系列 - SQL概览>中我们介绍了JOIN算子的语义和基本的使用方式,介绍过程中大家发现Apache Flink在语法语义上是遵循ANSI-SQL ...
- 《Android Studio实用指南》4.27 使用演示模式
本文节选自<Android Studio实用指南> 第4章第27节 作者: 毕小朋 目前本书已上传到百度阅读, 在百度中搜索[Anroid Studio实用指南]便可以找到本书. 什么是演 ...
- Apache beam中的便携式有状态大数据处理
Apache beam中的便携式有状态大数据处理 目标: 什么是 apache beam? 状态 计时器 例子&小demo 一.什么是 apache beam? 上面两个图片一个是正面切图,一 ...
- Apache Flink vs Apache Spark——感觉二者是互相抄袭啊 看谁的好就抄过来 Flink支持在runtime中的有环数据流,这样表示机器学习算法更有效而且更有效率
Apache Flink是什么 Flink是一款新的大数据处理引擎,目标是统一不同来源的数据处理.这个目标看起来和Spark和类似.没错,Flink也在尝试解决 Spark在解决的问题.这两套系统都在 ...
- kali中的APT软件包处理工具(apt-get)、Debian软件包管理器(dpkg)、源代码压缩和Nessus安装实用指南
写在前面的话 能看懂此博客的朋友,深信你有一定的Kali基础了. 使用APT软件包处理工具(apt-get).Debian软件包管理器(dpkg)来维护.升级和安装自定义及第三方应用程序 APT软件包 ...
随机推荐
- AngularJS7那些不得不说的事故
题外话 最近简直要忙死,所以停更了很久,你们会不会以为我人间蒸发了? 正文之前,请允许我先跑个题,就是关于忙的问题. 做了Freelance,每天过的比上班还累,这完全不是我想要的生活啊? ...
- 知识小罐头03(idea+maven+部署war包到tomcat 上)
自学的的小伙伴第一就要用maven!自学的的小伙伴第一就要用maven!自学的的小伙伴第一就要用maven! 重要的事说三遍!maven本质上,其实就是一种目录的格式,没有什么特别的地方!而且,你可以 ...
- 浅谈RNN、LSTM + Kreas实现及应用
本文主要针对RNN与LSTM的结构及其原理进行详细的介绍,了解什么是RNN,RNN的1对N.N对1的结构,什么是LSTM,以及LSTM中的三门(input.ouput.forget),后续将利用深度学 ...
- Smobiler 4.4 更新预告 Part 1(Smobiler能让你在Visual Studio上开发APP)
在4.4版本中,大家对产品优化的一些建议和意见进行了相应的优化和修复,同时,还新增了一些令人激动的功能和插件. 下面先为大家介绍4.4版本中Smobiler的优化和修复: 优化 1, PageView ...
- 第13章 切换到混合流并添加API访问 - Identity Server 4 中文文档(v1.0.0)
在之前的快速入门中,我们探讨了API访问和用户身份验证.现在我们想把这两个部分放在一起. OpenID Connect和OAuth 2.0组合的优点在于,您可以使用单个协议和使用令牌服务进行单次交换来 ...
- C#程序员知识体系
[https://blog.csdn.net/zj735539703/article/details/50409476] 基础部分 C# 基础语法 OOP的概念,面向对象的理解 继承 封装 多态 AS ...
- Java开发笔记(二十八)布尔包装类型
前面介绍了数值包装类型,因为不管是整数还是小数,它们的运算操作都是类似的,所以只要学会了Integer的用法,其它数值包装类型即可一并掌握.但是对于布尔类型boolean来说,该类型定义的是“true ...
- 实现PHP内部的通知机制,如当一个类的属性发生变化时,另外一个类就可以收到通知
设计模式:观察者模式 当一个对象的状态发生改变时,依赖他的对象会全部收到通知,并自动更新. 使用场景 一个事件发生后,要执行一连串更新操作.传统的编程方式,就是在事件的代码之后直接加入处理逻辑,当更新 ...
- iOS----------禁止输入汉字
说明: ^.*[\u4e00-\u9fa5].*$ 是否包含中文^[\u4E00-\u9FA5]+$ 是否全中文 - (BOOL)textField:(UITextField *)textField ...
- 访问vsts私有nuget
访问vsts私有nuget Intro 有时候我们可能要自己搭建一个 nuget,如果不对外公开,即包浏览也是需要权限的,那我们应该怎么做才可以支持在哪里都可以正常的还原包呢? 我是在 VSTS(Vi ...