Flink 狀態管理

有狀態計算是指在程序計算過程中,在Flink程序內部存儲計算產生的中間結果,並提供給後續Function或者算子計算結果使用。

狀態數據可以維繫在本地存儲中(Flink的堆內存或者堆外存),也可以藉助第三方的存儲,例如Flink已經實現的RocksDB,或者自定義其他存儲。

state 可以理解爲Flink上下文中可以access的一個內存數據庫(相比於無狀態計算,需要實現同樣功能需要藉助外部數據庫,如Redis),通過存取更新狀態,從而實現有狀態地算子運算。

案例:

  • 用戶想實現CEP(複雜事件處理),獲取符合某一特定事件規則的事件,狀態計算就可以將接入的事件進行存儲,然後等待符合規則的事件觸發;
  • 用戶想按照分鐘、小時、天進行聚合計算,求取當前的最大值、均值等聚合指標,這就需要利用狀態來維護當前計算過程中產生的結果,例如事件的總數、總和以及最大,最小值等

在Flink中需要通過創建StateDescriptor來獲取相應State的操作類。StateDescriptor主要定義了狀態的名稱、狀態中數據的類型參數信息以及狀態自定義函數。每種Managed Keyed State有相應的StateDescriptor,例如ValueStateDescriptor、ListStateDescriptor、ReducingState-Descriptor、FoldingStateDescriptor、MapStateDescriptor等

其中獲取狀態的方式是在RichFunction的Open方法中,以ValueState爲例:

private var leastValueState: ValueState[Long] = _
    override def open(parameters: Configuration): Unit = {
      //創建ValueStateDescriptor,定義狀態名稱爲leastValue,並指定數據類型
      val leastValueStateDescriptor = new ValueStateDescriptor[Long]("leastValue", classOf[Long])
      //通過getRuntimeContext.getState獲取State
      leastValueState = getRuntimeContext.getState(leastValueStateDescriptor)
    }

根據是否按key分區,分爲Keyed State 和 Operator State

意思是:

(1)keyed state 和 Key以及具體的Operator 綁定。

(2)Operator State 只和Operator算子有關。

根據是否託管Flink自動狀態管理,分爲Managed State 和 Raw State

Managed State 直接將狀態管理交給Flink,checkpoint時存儲的是bytes數據。

託管的好處是,Flink可以更好的支持狀態數據的重平衡以及更加完善的內存管理。

Managed Keyed State

狀態名 解釋 獲取值 更新值
ValueState[T] 與Key對應的單個值狀態 T .value() .update(T)
ListState[T] 與Key對應的列表的狀態 get(i) .add .addAll .update
ReducingState[T] 單個聚合值的狀態, 每次調用add方法添加值的時候,會調用reduceFunction,最後合併到一個單一的狀態值。 T get() add(T)
AggregatingState[IN,OUT] 與ReducingState唯一的區別是,輸入輸出類型可以不同。 OUT get() add(IN
MapState[UK,UV] 定義與Key對應的鍵值對的狀態 get(UK) .put .putAll .entries() .keys() .values()

Keyed State 生命週期

對於任何類型Keyed State都可以設定狀態的生命週期(TTL),以確保能夠在規定時間內及時地清理狀態數據。狀態生命週期功能可以通過StateTtlConfig配置,然後將StateTtlConfig配置傳入StateDescriptor中的enableTimeToLive方法中即可。

//創建StateTtlConfig
val stateTtlConfig = StateTtlConfig
  //指定TTL時長爲10s
  .newBuilder(Time.seconds(10))
  //指定TTL刷新時只對創建和寫入操作有效
  .setUpdateType(StateTtlConfig.UpdateType.OnCreateAndWrite)
  //指定狀態可見性爲永遠不反悔過期數據
  .setStateVisibility(StateTtlConfig.StateVisibility.NeverReturnExpired)
  .build
//創建ValueStateDescriptor
val valueStateDescriptor = new ValueStateDescriptor[String]("valueState", classOf[Long])
//指定創建好的stateTtlConfig
valueStateDescriptor.enableTimeToLive(stateTtlConfig)

Managed Operator State

應用場景,例如:

統計算子輸入數據量

維護Topics分區和Offsets偏移量

案例,統計算子輸入數據量:

class numberRecordsCount extends FlatMapFunction[(String, Long), (String, 
Long)] with ListCheckpointed[Long] {
  //定義算子中接入的numberRecords數量
  private var numberRecords: Long = 0L
  override def flatMap(t: (String, Long), collector: Collector[(String, Long)]): Unit = {
    //接入一條記錄則進行統計,並輸出
    numberRecords += 1
    collector.collect(t._1, numberRecords)
  }
  override def snapshotState(checkpointId: Long, ts: Long): util.List[Long] = {
    //Snapshot狀態的過程中將numberRecords寫入
    Collections.singletonList(numberRecords)
  }
  override def restoreState(list: util.List[Long]): Unit = {
    numberRecords = 0L
    for (count <- list) {
      //從狀態中恢復numberRecords數據
      numberRecords += count }}}
  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章