本文主要运行到Flink以下内容

  • 检查点机制(CheckPoint)

  • 状态管理器(StateBackend)

  • 状态周期(StateTtlConfig)

关系

首先要将state和checkpoint概念区分开,可以理解为checkpoint是要把state数据持久化存储起来,checkpoint默认情况下会存储在JoManager的内存中。checkpoint表示一个Flink job在一个特定时刻的一份全局状态快照,方便在任务失败的情况下数据的恢复。在启动 CheckPoint 机制时,状态会随着 CheckPoint 而持久化,以防止数据丢失、保障恢复时的一致性。状态内部的存储格式、状态在 CheckPoint 时如何持久化以及持久化在哪里均取决于选择的StateBackend。存储多长时间或者说是周期,取决于StateTtlConfig

1 检查点机制(CheckPoint)

Checkpoint 使 Flink 的状态具有良好的容错性,通过 checkpoint 机制,Flink 可以对作业的状态和计算位置进行恢复。

Checkpoint 在默认的情况下仅用于恢复失败的作业,并不保留,当程序取消时 checkpoint 就会被删除。当然,你可以通过配置来保留 checkpoint,这些被保留的 checkpoint 在作业失败或取消时不会被清除。这样,你就可以使用该 checkpoint 来恢复失败的作业。

参数设置与解释

val env: StreamExecutionEnvironment =
      StreamExecutionEnvironment.getExecutionEnvironment //只指定两个checkpoint的时间间隔,单位是毫秒
//指定checkpoint时间间隔,并指定checkpoint的模式,是exactly-once(刚好一次)
//还是AT_LEAST_ONCE(至少一次)。
//大多数情况下是exactly-once(默认就是这个模式),少数情况下,如果要求超低延迟的处理情况,才会设置AT_LEAST_ONCE
env.enableCheckpointing(1000,CheckpointingMode.EXACTLY_ONCE)  // 两种方式
// env.enableCheckpointing(1000)
// env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE) /* 设置checkpoint上一个的结束点到下一个开始点之间的最短时间。
checkpoint触发时,需要一定时间去完成整个checkpoint的过程,
1、这里的时间间隔,指的是上一个checkpoint完成的时间点,到下一个checkpoint开始的时间点的间隔,如果过短,会导致频繁checkpoint,影响性能。假设这个间隔为T
2、而上面设置的checkpoint时间间隔,指的是前一个checkpoint的开始时间到下一个checkpoint的开始时间。所以是始终大于1中的时间间隔的。假设这个间隔为 N 如果T小于这里设置的值,那么无论N设置多少,下一个checkpoint的开始时间必须是5000ms之后。如果T大于这里设置的值,那么正常按照N设置的间隔来触发下一个checkpoint,这里设置的间隔无关了。
*/
env.getCheckpointConfig().setMinPauseBetweenCheckpoints(5000) // 设置checkpoint完成的超时时间
env.getCheckpointConfig().setCheckpointTimeout(60000) // 设置checkpoint的最大并行度
env.getCheckpointConfig().setMaxConcurrentCheckpoints(1) /*  开启checkpoints的外部持久化,但是在job失败的时候不会自动清理,需要自己手工清理state
DELETE_ON_CANCELLATION:在job canceled的时候会自动删除外部的状态数据,但是如果是FAILED的状态则会保留;
RETAIN_ON_CANCELLATION:在job canceled的时候会保留状态数据*/
env.getCheckpointConfig().enableExternalizedCheckpoints(ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION) // 当有更近的保存点时,优先采用savepoint来恢复成检查点
env.getCheckpointConfig().setPreferCheckpointForRecovery(true)

目录结构

/user-defined-checkpoint-dir
    /{job-id}
        |
        + --shared/
        + --taskowned/
        + --chk-1/
        + --chk-2/
        + --chk-3/
        ...

SHARED目录保存了可能被多个 checkpoint 引用的文件

TASKOWNED保存了不会被 JobManager 删除的文件

EXCLUSIVE则保存那些仅被单个 checkpoint 引用的文件

2 状态管理器(StateBackend)

可用的 State Backends

  • MemoryStateBackend

  • FsStateBackend

  • RocksDBStateBackend

MemoryStateBackend

在 MemoryStateBackend 内部,数据以 Java 对象的形式存储在堆中。Key/value 形式的状态和窗口算子持有存储着状态值、触发器的 hash table。

在 CheckPoint 时,State Backend 对状态进行快照,并将快照信息作为 CheckPoint 应答消息的一部分发送给 JobManager(master),同时 JobManager 也将快照信息存储在堆内存中。

MemoryStateBackend 能配置异步快照。强烈建议使用异步快照来防止数据流阻塞,注意,异步快照默认是开启的。用户可以在实例化 MemoryStateBackend 的时候,将相应布尔类型的构造参数设置为 false 来关闭异步快照(仅在 debug 的时候使用),例如:

 new MemoryStateBackend(MAX_MEM_STATE_SIZE, false)

FsStateBackend

FsStateBackend 将正在运行中的状态数据保存在 TaskManager 的内存中。CheckPoint 时,将状态快照写入到配置的文件系统目录中。少量的元数据信息存储到 JobManager 的内存中(高可用模式下,将其写入到 CheckPoint 的元数据文件中)。

FsStateBackend 默认使用异步快照来防止 CheckPoint 写状态时对数据处理造成阻塞。用户可以在实例化 FsStateBackend 的时候,将相应布尔类型的构造参数设置为 false 来关闭异步快照,例如:

 new FsStateBackend(path, false)

RocksDBStateBackend

RocksDBStateBackend 将正在运行中的状态数据保存在 RocksDB 数据库中,RocksDB 数据库默认将数据存储在 TaskManager 的数据目录。CheckPoint 时,整个 RocksDB 数据库被 checkpoint 到配置的文件系统目录中。少量的元数据信息存储到 JobManager 的内存中(高可用模式下,将其存储到 CheckPoint 的元数据文件中)。RocksDBStateBackend 只支持异步快照。

设置 State Backend

后面的案例也以RocksDBStateBackend为例

 val backend:StateBackend = new RocksDBStateBackend("hdfs://djcluster/Test/")
 
 env.setStateBackend(backend)

3 状态周期(StateTtlConfig)

状态引入了TTL(time-to-live,生存时间)机制,支持Keyed State 的自动过期,有效解决了状态数据在无干预情况下无限增长导致 OOM 的问题。对于任何类型 Keyed State 都可以设定状态生命周期(TTL),以确保能够在规定时间内即时清理状态数据。

val config: StateTtlConfig = StateTtlConfig
              .newBuilder(Time.minutes(1))
              .setUpdateType(StateTtlConfig.UpdateType.OnReadAndWrite)
              .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)
              .build()
              
 val mapState = new MapStateDescriptor[String,Any]("aa",classOf[String],classOf[Any])
 
 mapState.enableTimeToLive(config)

参数说明:

  • UpdateType:表示状态时间戳的更新的时机

参数 说明
Disabled 不更新时间戳
OnCreateAndWrite 当状态创建或每次写入时都会更新时间戳
OnReadAndWrite 除了在状态创建和写入时更新时间戳外,读取也会更新状态的时间戳
  • StateVisibility:表示对已过期但还未被清理掉的状态如何处理

参数 说明
ReturnExpiredIfNotCleanedUp 即使这个状态的时间戳表明它已经过期了,但是只要还未被真正清理掉,就会被返回给调用方
NeverReturnExpired 那么一旦这个状态过期了,那么永远不会被返回给调用方,只会返回空状态,避免了过期状态带来的干扰

上面是理论论述,下面是代码实现与测试

4.理论实现与测试

描述

通过 nc -lk 8765 在机器上输入逗号隔开的字符串,比如:event,1,1 要保证中间的值和下次输入的值一样,这样keyBy分流到一个分区中,方便测试看到效果。状态值保存到Hdfs上。

def main(args: Array[String]): Unit = {
    val env: StreamExecutionEnvironment =
      StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)
    val backend:StateBackend = new RocksDBStateBackend("hdfs://cluster/Test/")
    env.setStateBackend(backend)
    env.enableCheckpointing(5000)
    env.getCheckpointConfig.setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE)
    env.getCheckpointConfig.enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION)
    val dataDS: scala.DataStream[String] = env.socketTextStream("localhost", 8765)
    dataDS.map(item => {
      val str = item.split(",")
      (str(0),str(1),str(2))
    }
    )
      .keyBy(_._2)
      .process(
        new KeyedProcessFunction[String,(String, String, String), String] {
          var leastValueState: MapState[String, Any] = _
          override def open(parameters: Configuration): Unit = {
            println("open")
            val config: StateTtlConfig = StateTtlConfig
              .newBuilder(Time.minutes(15))
              .setUpdateType(StateTtlConfig.UpdateType.OnReadAndWrite)
              .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)
              .build()
            val aa = new MapStateDescriptor[String,Any]("aa",classOf[String],classOf[Any])
            aa.enableTimeToLive(config)
            leastValueState = getRuntimeContext.getMapState(aa)
          }
          override def processElement(i: (String, String, String),
                                      ctx: KeyedProcessFunction[String, (String, String, String), String]#Context,
                                      out: Collector[String]): Unit = {
            println(leastValueState.get("3"))             i._1 match {
              case "order" => leastValueState.put("order", 12)
              case "event" => out.collect("打印event")
              case _ => out.collect("什么都没有")
            }
            out.collect(leastValueState.get("3")+":")
          }
        }       )
      .uid("bbbbbbb")
      .print()
    env.execute()
  }

打包上传集群测试

执行命令

./bin/flink run -m yarn-cluster 
-yqu spark -c com.wang.StateBackend /usr/local/jars/flink.jar  
-yn 7 -ys 2 -p 14 -ytm 2048m -yjm 2048m

这个不管是你自己亲自kill掉application 或者是某些原因flink任务挂掉,这个时候你就可以这样恢复数据

找到RocksDBStateBackend设置的地址 hdfs://cluster/Test/

找到挂掉任务的checkpoint地址(可以通过Flink历史服务器去找,如果任务少,也可以直接去hdfs上找)

重新启动任务

这边遇到的一个坑就是命令参数位置不对,怎么设置都没有用,也不起效,下次一定记得。刚测试的时候 -s 写在后面的某一个位置,怎么测试都不起效,一直以为代码有问题,查询了好多资料,都是这样写的,没有问题,前前后后折腾好久。最后把 -s 参数调到最前面就神奇的好了......

./bin/flink run -m yarn-cluster 
-s hdfs://cluster/Test/e45509db99014fd47971c6eaf3701f4b/chk-41/_metadata 
-yqu spark -c com.wang.StateBackend /usr/local/jars/flink.jar 
-yn 7 -ys 2 -p 14 -ytm 2048m -yjm 2048m

这个时候已经恢复到之前挂掉的数据了

Flink的状态与容错的更多相关文章

  1. 9、flink的状态与容错

    1.理解State(状态) 1.1.State 对象的状态 Flink中的状态:一般指一个具体的task/operator某时刻在内存中的状态(例如某属性的值) 注意:State和Checkpoint ...

  2. 第09讲:Flink 状态与容错

    Flink系列文章 第01讲:Flink 的应用场景和架构模型 第02讲:Flink 入门程序 WordCount 和 SQL 实现 第03讲:Flink 的编程模型与其他框架比较 第04讲:Flin ...

  3. 关于 Flink 状态与容错机制

    Flink 作为新一代基于事件流的.真正意义上的流批一体的大数据处理引擎,正在逐渐得到广大开发者们的青睐.就从我自身的视角看,最近也是在数据团队把一些原本由 Flume.SparkStreaming. ...

  4. Flink之状态之checkpointing

    1.前言 在Flink中,函数和操作符都可以是有状态的.在处理每个消息或者元素时,有状态的函数都会储存信息,使得状态成为精密操作中关键的组成部分. 为了使状态能够容错,Flink会checkpoint ...

  5. Flink Streaming状态处理(Working with State)

    参考来源: https://www.jianshu.com/p/6ed0ef5e2b74 https://blog.csdn.net/Fenggms/article/details/102855159 ...

  6. Flink中的状态与容错

    1.概述 Flink支持有状态计算,根据支持得不同状态类型,分别有Keyed State和Operator State.针对状态数据得持久化,Flink提供了Checkpoint机制处理:针对状态数据 ...

  7. 「Flink」Flink的状态管理与容错

    在Flink中的每个函数和运算符都是有状态的.在处理过程中可以用状态来存储数据,这样可以利用状态来构建复杂操作.为了让状态容错,Flink需要设置checkpoint状态.Flink程序是通过chec ...

  8. Flink的状态编程和容错机制(四)

    一.状态编程 Flink 内置的很多算子,数据源 source,数据存储 sink 都是有状态的,流中的数据都是 buffer records,会保存一定的元素或者元数据.例如 : ProcessWi ...

  9. flink 有状态udf 引起血案一

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/rlnLo2pNEfx9c/article/details/83422587 场景 近期在做一个画像的 ...

随机推荐

  1. RabbitMq基本概念理解

    RabbitMQ的基本概念 RabbitMQ github项目地址 RabbitMQ 2007年发布,是一个在AMQP(高级消息队列协议)基础上完成的,可复用的企业消息系统,是当前最主流的 消息中间件 ...

  2. Matplotlib处理csv文件

    csv模块包含在python标准库中,可用于分析CSV文件中的数据行,让我们能够快速提取感兴趣的值.首先绘制一个简单的折线图: 1 #!usr/bin/env python 2 #*-*Coding= ...

  3. pycharm的快捷键的使用

    作为未来的程序猿,快捷键对我们来说很重要,因为它方便且快捷,今天就给大家介绍pycharm中常用的快捷键 1.编辑: Ctrl + Space------------------基本的代码完成(类.方 ...

  4. 函数进阶· 第3篇《常用内置函数filter()、map()、zip(),怎么用的呢?》

    坚持原创输出,点击蓝字关注我吧 作者:清菡 博客:oschina.云+社区.知乎等各大平台都有. 由于微信公众号推送改为了信息流的形式,防止走丢,请给加个星标 ,你就可以第一时间接收到本公众号的推送! ...

  5. 为什么游戏公司的server不愿意微服务化?

    背景介绍 笔者最近去面试了家游戏公司(有上市).我问他,公司有没有做微服务架构的打算及考量?他很惊讶的,我没听说过微服务耶,你可以解释一下吗? 我大概说了,方便测试,方便维护,方便升级,服务之间松耦合 ...

  6. java中根据后端返回的数据加载table列表

    <%//引入 js @ page language="java" pageEncoding="UTF-8"%> <!DOCTYPE HTML& ...

  7. 【分布式锁】Redis实现可重入的分布式锁

    一.前言 之前写的一篇文章<细说分布式锁>介绍了分布式锁的三种实现方式,但是Redis实现分布式锁关于Lua脚本实现.自定义分布式锁注解以及需要注意的问题都没描述.本文就是详细说明如何利用 ...

  8. 论文阅读 Characterization of Multiple 3D LiDARs for Localization and Mapping using Normal Distributions Transform

    Abstract 在这个文章里, 我们细致的比较了10种不同的3D LiDAR传感器, 用了一般的 Normal Distributions Transform (NDT) 算法. 我们按以下几个任务 ...

  9. Modbus 协议图文详解

    1.概论 Modbus是一种串行通信协议,由于其协议简单易用,且没有版权要求,目前已经成为工业领域通信协议的实时标准.ModBus协议是又施耐德电气的前身Modicon公司在1979年提出的.Modb ...

  10. STP、PVST、MST协议

    • STP:生成树协议        ○ 阻止环形链路的广播风暴    • PVST:VLAN生成树        ○ 是STP的进阶版不仅能阻止广播风暴,还可以做到基于VLAN进行流量均衡.     ...