使用 Broadcast State 的 4 个注意事项

本文将描述什么是广播状态模式(Broadcast State Pattern),广播状态与其他的 Operator State 有什么区别,最后,我们在 Flink 中使用该功能时需要考虑的一些重要的注意事项。

广播状态(Broadcast State)作为Apache Flink 1.5.0 中引入的新特性,它可用于以特定方式组合和联合处理两个事件流,其中第一个流中的的数据被广播到某个算子的所有并行实例中,该算子将它们保存为状态。另一个流的事件不广播,而是发送给同一个算子的单个实例,并与广播流的事件一起处理。对于需要连接低吞吐量和高吞吐量流或需要动态更新处理逻辑的应用来说,新的broadcast state非常适合。

广播状态模式是什么 ?

广播状态模式指的一种流应用程序,其中低吞吐量的事件流(例如,包含一组规则)被广播到某个 operator 的所有并发实例中,然后针对来自另一条原始数据流中的数据(例如金融或信用卡交易)进行计算。 广播状态模式的一些典型应用案例如下:

  • 动态规则:例如,有一个规则:当连续登陆3次失败时发出警报。我们将这个规则广播到计算连续登陆次数算子的所有并发实例中。
  • 维度补充:例如,将商品的详细信息作业广播状态进行广播,对包含商品id的交易数据流进行维度补充。

为了实现上述应用,关键组件是广播状态,我们将在下文详细描述。

广播状态如何理解 ?

广播状态是 Flink 支持的第三种类型的 operator state。广播状态使得 Flink 用户能够以容错、一致、可扩展的将来自广播的低吞吐的事件流数据作为状态存储下来。来自另一条数据流的数据通过流经同一operator 的各个并发实例,并与广播状态中的数据一起处理。

广播状态与其他 operator state 之间有三个主要区别。如下所示:

  • Map 的格式
  • 包含一条起到广播用途的输入流
  • operator 可以有多个不同名字的广播状态

使用注意事项

Apache Flink 官方文档为我们提供了如何使用广播状态相关API的详细指南,以及如何将它应用在我们的具体需求当中。在使用广播状态时有如下下4个注意事项:

  • 使用广播状态,operator task 之间不会相互通信
    这也是为什么(Keyed)-BroadcastProcessFunction上只有广播的一边可以修改广播状态的内容。用户必须保证所有 operator 并发实例上对广播状态的修改行为都是一致的。或者说,如果不同的并发实例拥有不同的广播状态内容,将导致不一致的结果。
  • 广播状态中事件的顺序在各个并发实例中可能不尽相同
    虽然广播流的元素保证了将所有元素(最终)都发给下游所有的并发实例,但是元素的到达的顺序可能在并发实例之间并不相同。因此,对广播状态的修改不能依赖于输入数据的顺序。
  • 在 checkpoint 时,所有的 task 都会 checkpoint 下他们的广播状态,即使各个 task 在广播状态中存储的数据是完全相同的。这么设计的目的是避免在恢复期间所有task都从单个文件读取而造成热点。然而,随着并发度的增加,总体checkpoint 的大小也会随之增加,checkpoint此时快照了多份完全相同的广播状态。这里要考虑到task的并发度p, 如果以相同或者更小的并行度恢复时,各个task会读取相对应的检查点状态。当恢复前后并行度加大,那么恢复前的task会读取相对应的检查点状态,恢复后新增的task会以循环方式(round-robin)来依次读取检查点状态。
  • RocksDB 状态后端目前还不支持广播状态, 广播状态目前在运行时保存在内存中。因为当前,RocksDB 状态后端还不适用于 operator state。Flink 用户应该相应地为相应的应用配置足够的内存,避免出现OOM。

往期精选▼

Flink中Checkpoint和Savepoint 的 3 个不同点

Flink实现固定时长或消息条数的触发器 

使用 Broadcast State 的 4 个注意事项

3种Flink State Backend | 你该用哪个?

100%会被问到的两道Flink面试题,你会了么?

 

大数据一站式学习

 

 

 

假设我们要实现一个跨进程的计算器应用,当用户在应用中输入两个数字和操作符后,计算结果需要显示在另一个进程中的UI界面上。我们可以使用BroadcastReceiver来实现这个功能。 首先,在发送广播的进程中,我们需要创建一个BroadcastReceiver来接收计算结果,并将结果发送到另一个进程中。代码如下: ``` public class CalculatorResultReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { double result = intent.getDoubleExtra("result", 0.0); Intent broadcastIntent = new Intent("com.example.calculator.CALCULATOR_RESULT"); broadcastIntent.putExtra("result", result); context.sendBroadcast(broadcastIntent); } } ``` 在这个Receiver中,我们从Intent中获取计算结果,并将结果封装到一个新的Intent中,然后发送给另一个进程。 接下来,在接收广播的进程中,我们需要创建一个BroadcastReceiver来接收计算结果并更新UI界面。代码如下: ``` public class CalculatorResultReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { double result = intent.getDoubleExtra("result", 0.0); TextView resultTextView = (TextView) findViewById(R.id.result_text_view); resultTextView.setText(String.valueOf(result)); } } ``` 在这个Receiver中,我们从Intent中获取计算结果,并使用findViewById方法获取UI界面中的TextView控件,然后更新UI界面上的结果。 最后,在发送广播的地方,我们需要创建一个Intent,并将计算结果封装到Intent中,然后发送广播。代码如下: ``` Intent intent = new Intent("com.example.calculator.CALCULATOR_RESULT"); intent.putExtra("result", result); sendBroadcast(intent); ``` 在这个Intent中,我们指定了广播的Action为"com.example.calculator.CALCULATOR_RESULT",这个Action需要和接收广播的地方注册的Action相同。然后我们将计算结果封装到Intent中,并发送广播。 这样,我们就完成了一个跨进程使用BroadcastReceiver的例子。当用户在应用中进行计算后,计算结果会自动显示在另一个进程的UI界面上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值