Flink源码分析(二): 广播状态流实现规格更新或字段参数变更

Flink源码专辑:
Flink源码分析(一): 重启策略机制RestartStrategy

前言:

版权说明:本专栏是作者在日常工作期间对技术的不断深入研究后的沉淀,辛苦码字总结而成。严禁转载,严禁作为商业用途转发。欢迎同行加入大数据技术群QQ:427560730

版本号:Flink1.10.0

在使用Flink流式计算时,代码功能实现重要的同时,后期的可维护性一样很重要。作者在开发过程中就遇见过这样一个场景:如果实时计算过程中,我源表突然增加一个字段怎么办,难道Flink程序要改代码重启吗,虽然Flink是有Savepoint机制,但是这样还是会造成延迟,而且后期维护不是很友好。

为了解决这样问题,小编发现了一个Flink的一个功能很强大: 广播状态流机制。

BroadCast State Stream:

广播流是数据以流的形式存在,所以我们需要把广播的数据发送到kafka中(配置文件,数据库表结构等)
Flink源码分析(二): 广播状态流实现规格更新或字段参数变更_第1张图片

  1. 定义广播状态描述:
    在流B上调用DataStream.broadcast()方法并传入MapStateDescriptor作为状态描述符,就可以将它转化为广播流BroadcastStream
val mapStateDescriptor = new MapStateDescriptor[String,String]("sqlConfig",
      BasicTypeInfo.STRING_TYPE_INFO,
      BasicTypeInfo.STRING_TYPE_INFO
    )
  1. BroadcastStream入参、出参:
    Flink源码分析(二): 广播状态流实现规格更新或字段参数变更_第2张图片
    从上图源码中可以看出broadcast()方法将执行环境StreamExecutionEnvironment、原始的DataStream和MapStateDescriptor一起包装成了BroadcastStream实例。

  2. 使用BroadcastStream:
    我们生成广播状态流B之后,可以和A数据流进行connect(),之后使用process()方法写自己的处理逻辑。

class testSink extends BroadcastProcessFunction[String,String,String]{
  
  
  override def processElement(in1: String, 
                              readOnlyContext: BroadcastProcessFunction[String, String, String]#ReadOnlyContext, 
                              collector: Collector[String]): Unit = {
    
  }

  override def processBroadcastElement(in2: String, 
                                       context: BroadcastProcessFunction[String, String, String]#Context, 
                                       collector: Collector[String]): Unit = {
    
  }
}

这里继承了BroadcastProcessFunction,里面传入三个参数,分别表示A数据流String格式,B数据流String格式,connect()后输出String格式

processElement()
BroadcastProcessFunction的重写方法之一,这里需要传入3个参数:A数据流,只读上下文状态,输出流。该方法用来处理数据流中的数据

processBroadcastElement():
BroadcastProcessFunction的重写方法之一,这里需要传入3个参数:B数据流,上下文状态,输出流。该方法用来处理广播数据流中的数据

重点总结

没有跨任务通信(There is no cross-task communication):
如前所述,这就是为什么只有(键的)broadcastprocessfunction的广播端可以修改广播状态的内容。此外,用户必须确保所有任务以相同的方式为每个传入元素修改broadcast状态的内容。
否则,不同的任务可能具有不同的内容,从而导致不一致的结果。

广播状态下的事件顺序可能会因任务的不同而不同(Order of events in Broadcast State may differ across tasks)
尽管广播流的元素可以保证所有元素(最终)都将进入所有下游任务,元素可能以不同的顺序到达每个任务。因此,每个传入元素的状态更新不能依赖于传入事件的顺序。

所有任务检查它们的广播状态(All tasks checkpoint their broadcast state)
尽管在检查点发生时,所有任务的广播状态中都有相同的元素(检查点屏障不会跨越元素),所有任务检查它们的广播状态,而且不止一个。这是一个设计决策,避免在恢复期间从同一个文件读取所有任务(从而避免热点),尽管这样做的代价是将检查点状态的大小增加p(=并行度)。Flink保证在恢复/重新扫描时不会有重复和丢失数据。在并行度相同或更小的恢复情况下,每个任务读取其检查点状态。在扩展时,每个任务读取自己的状态,其余任务(p_new-p_old)以循环方式读取以前任务的检查点。

没有RocksDB状态后端(No RocksDB state backend):
广播状态在运行时保存在内存中,应该相应地进行内存供应。这适用于所有的运算符状态。

你可能感兴趣的:(Flink)