感谢英文原文作者: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. 模式#1:用户登录并立即注销而无需浏览电子商务网站上的其他页面。
  2. 模式#2:用户将商品添加到购物车并在不完成购买的情况下注销。

这些模式有助于企业更好地分析用户行为,检测恶意行为并改善网站体验。

例如,如果项目被添加到购物车而没有后续购买,网站团队可以采取适当的措施来更好地了解用户未完成购买的原因并启动特定程序以改善网站转换(如提供折扣代码,限时免费送货优惠等)

在右侧,该图显示了操作员的三个并行任务,即摄取模式和用户操作流,评估操作流上的模式,并在下游发出模式匹配。

为简单起见,我们示例中的运算符仅评估具有两个后续操作的单个模式。当从模式流接收到新模式时,替换当前活动模式。

原则上,还可以实现运算符以同时评估更复杂的模式或多个模式,这些模式可以单独添加或移除。

我们将描述模式匹配应用程序如何处理用户操作和模式流。



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



接下来,第一个用户操作按用户ID分区并发送到操作员任务。分区可确保同一用户的所有操作都由同一任务处理。上图显示了操作员任务消耗第一个模式和前三个操作事件后应用程序的状态。

当任务收到新的用户操作时,它会通过查看用户的最新和先前操作来评估当前活动的模式。

对于每个用户,操作员将先前的操作存储在键控状态。由于上图中的任务到目前为止仅为每个用户收到了一个操作(我们刚刚启动了应用程序),因此不需要评估该模式。

最后,用户键控状态中的先前操作被更新为最新动作,以便能够在同一用户的下一个动作到达时查找它。

在处理前三个动作之后,下一个事件(用户1001的注销动作)被运送到处理用户1001的事件的任务。

当任务接收到动作时,它从广播状态中查找当前模式并且用户1001的先前操作。由于模式匹配两个动作,因此任务发出模式匹配事件。

最后,任务通过使用最新操作覆盖上一个事件来更新其键控状态。

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



一旦用新模式更新广播状态,匹配逻辑就像之前一样继续,即,用户动作事件由密钥分区并由负责任务评估。

如何使用广播状态实现应用程序?

到目前为止,我们在概念上讨论了该应用程序并解释了它如何使用广播状态来评估事件流上的动态模式。

接下来,我们将展示如何使用Flink的DataStream API和广播状态功能实现示例应用程序。

让我们从应用程序的输入数据开始。我们有两个数据流,操作和模式。

在这一点上,我们并不关心流来自何处。这些流可以从Apache Kafka或Kinesis或任何其他系统中摄取。并与各两个字段的POJO:

DataStream<Action> actions = ???
DataStream<Pattern> patterns = ???

ActionPattern

  • ActionLong userIdString action
  • Pattern:,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()为广播流的每个记录调用。在我们的 函数中,我们只是使用键将接收到的记录放入广播状态(记住,我们只存储一个模式)。PatternEvaluator Patternnull MapState
  • processElement()为键控流的每个记录调用。它提供对广播状态的只读访问,以防止修改导致跨函数的并行实例的不同广播状态。 从广播状态检索当前模式的方法和从键控状态检索用户的先前动作。如果两者都存在,则检查先前和当前操作是否与模式匹配,并且如果是这种情况则发出模式匹配记录。最后,它将键控状态更新为当前用户操作。processElement()PatternEvaluator
  • onTimer()在先前注册的计时器触发时调用。定时器可以在任何处理方法中注册,并用于执行计算或将来清理状态。我们在示例中没有实现此方法以保持代码简洁。但是,当用户在一段时间内未处于活动状态时,它可用于删除用户的最后一个操作,以避免由于非活动用户而导致状态增长。

您可能已经注意到了处理方法的上下文对象。上下文对象提供对其他功能的访问,例如KeyedBroadcastProcessFunction

  • 广播状态(读写或只读,取决于方法),
  • A,可以访问记录的时间戳,当前的水印,以及可以注册计时器,TimerService
  • 当前密钥(仅适用于 ),和processElement()
  • 一种将函数应用于每个注册密钥的键控状态的方法(仅适用于)processBroadcastElement()

在具有就像任何其他ProcessFunction完全进入状态弗林克和时间特性,因此可以用来实现复杂的应用程序逻辑。广播状态被设计为适应不同场景和用例的多功能特性。虽然我们只讨论了一个相当简单且受限制的应用程序,但您可以通过多种方式使用广播状态来实现应用程序的要求。KeyedBroadcastProcessFunction

结论

在这篇博文中,我们向您介绍了一个示例应用程序,以解释Apache Flink的广播状态以及它如何用于评估事件流上的动态模式。我们还讨论了API并展示了我们的示例应用程序的源代码。

我们邀请您查看Apache Flink网站上的文档,并通过Apache Flink 邮件列表提供反馈或建议以进一步改进。

Apache Flink中的广播状态实用指南的更多相关文章

  1. 如何在 Apache Flink 中使用 Python API?

    本文根据 Apache Flink 系列直播课程整理而成,由 Apache Flink PMC,阿里巴巴高级技术专家 孙金城 分享.重点为大家介绍 Flink Python API 的现状及未来规划, ...

  2. Flink 从0到1学习 —— Flink 中如何管理配置?

    前言 如果你了解 Apache Flink 的话,那么你应该熟悉该如何像 Flink 发送数据或者如何从 Flink 获取数据.但是在某些情况下,我们需要将配置数据发送到 Flink 集群并从中接收一 ...

  3. 《Android Studio实用指南》7.1 AndroidStudio代码检查工具概述

    本文节选自<Android Studio实用指南> 作者: 毕小朋 目前本书已上传到百度阅读, 在百度中搜索[Anroid Studio实用指南]便可以找到本书. Android Stud ...

  4. State Processor API:如何读取,写入和修改 Flink 应用程序的状态

    过去无论您是在生产中使用,还是调研Apache Flink,估计您总是会问这样一个问题:我该如何访问和更新Flink保存点(savepoint)中保存的state?不用再询问了,Apache Flin ...

  5. Apache Flink 漫谈系列 - JOIN 算子

    聊什么 在<Apache Flink 漫谈系列 - SQL概览>中我们介绍了JOIN算子的语义和基本的使用方式,介绍过程中大家发现Apache Flink在语法语义上是遵循ANSI-SQL ...

  6. 《Android Studio实用指南》4.27 使用演示模式

    本文节选自<Android Studio实用指南> 第4章第27节 作者: 毕小朋 目前本书已上传到百度阅读, 在百度中搜索[Anroid Studio实用指南]便可以找到本书. 什么是演 ...

  7. Apache beam中的便携式有状态大数据处理

    Apache beam中的便携式有状态大数据处理 目标: 什么是 apache beam? 状态 计时器 例子&小demo 一.什么是 apache beam? 上面两个图片一个是正面切图,一 ...

  8. Apache Flink vs Apache Spark——感觉二者是互相抄袭啊 看谁的好就抄过来 Flink支持在runtime中的有环数据流,这样表示机器学习算法更有效而且更有效率

    Apache Flink是什么 Flink是一款新的大数据处理引擎,目标是统一不同来源的数据处理.这个目标看起来和Spark和类似.没错,Flink也在尝试解决 Spark在解决的问题.这两套系统都在 ...

  9. kali中的APT软件包处理工具(apt-get)、Debian软件包管理器(dpkg)、源代码压缩和Nessus安装实用指南

    写在前面的话 能看懂此博客的朋友,深信你有一定的Kali基础了. 使用APT软件包处理工具(apt-get).Debian软件包管理器(dpkg)来维护.升级和安装自定义及第三方应用程序 APT软件包 ...

随机推荐

  1. asp.net core系列 39 Web 应用Razor 介绍与详细示例

    一. Razor介绍 在使用ASP.NET Core Web开发时, ASP.NET Core MVC 提供了一个新特性Razor. 这样开发Web包括了MVC框架和Razor框架.对于Razor来说 ...

  2. Asp.Net SignalR 集线器不使用代理的实现

    不使用生成代理JS的实现 可能有同学会觉得使用集线器很麻烦,要么引入虚拟目录,要么在生成期间生成js文件,再引入js文件进行开发.难道就没有比较清爽的方式吗?这个当然是有的,先不要(。・∀・)ノ゙嗨皮 ...

  3. linux权限之su和sudo的差别

    我们都知道非常多的文件都仅仅有root有权限来改动,那么在我们平时的开发过程中都建议使用一般账号来登录进行开发.还记得前面说到的ssh吗.我们也是将同意root登录设置成no.到必要的时候再切换到ro ...

  4. SB!SB!SB!

    Topic Link http://ctf5.shiyanbar.com/stega/ste.png SB!SB!SB! 其实很简单,可别真的变成 SB! 1)根据链接提示,直接用stegsolve ...

  5. Thread之九:stop

    搞过Java线程的人都知道,stop这个方法是臭名昭著了,早就被弃用了,但是现在任然有很多钟情与他的人,永远都放不下他,因为从他的字面意思上我们可以知道他貌似可以停止一个线程,这个需求是每个搞线程开发 ...

  6. 基本 SQL 之增删改查(二)

    上一篇文章中,我们介绍了 SQL 中最基本的 DML 语法,包括 insert 的插入数据.update 的更新数据.delete 的删除数据以及基本的查询语法,但大多比较简单不能解决我们日常项目中复 ...

  7. 流式大数据计算实践(7)----Hive安装

    一.前言 1.这一文学习使用Hive 二.Hive介绍与安装 Hive介绍:Hive是基于Hadoop的一个数据仓库工具,可以通过HQL语句(类似SQL)来操作HDFS上面的数据,其原理就是将用户写的 ...

  8. DSAPI多功能组件编程应用-网络相关(下)

    [DSAPI.DLL下载地址] 在本篇,我将重点介绍DSAPI.DLL中Socket编程的使用.众所周知,Socket用起来不难,但是写起来麻烦.我对Socket进行了封装,进行了高度简化.下面我将通 ...

  9. C#___.net经典题

    1 请你说说   .NET  中类和结构的区别? 答:结构和类具有大体的语法,但是结构受到的限制比类要多.结构不能申明有默认的构造函数,为结构的副本是又编译器创建 和销毁的,所以不需要默认的构造函数和 ...

  10. [PHP] defunct僵尸进程

    1.如果子进程先于父进程退出, 同时父进程又没有调用wait/waitpid,则该子进程将成为僵尸进程 2.如果fork完就不管了可以使用 忽略子进程信号, 防止僵尸进程 pcntl_signal(S ...