1. 程式人生 > 實用技巧 >Flink例項(三十):狀態管理(一)概述

Flink例項(三十):狀態管理(一)概述

參考連結;

https://www.cnblogs.com/qiu-hua/p/13432337.html

https://www.cnblogs.com/shengyang17/p/12549199.html

1. 狀態管理

Flink中的狀態

  • A. 運算元狀態(Operatior State)
  • B. 鍵控狀態(Keyed State)
  • 狀態後端(State Backends) --用作狀態管理

流式處理(A. 可以是無狀態(基於某個獨立的事件計算出來後直接輸出了,來一個處理一個不涉及到其他東西,如map、flatmap、filter;超過一定溫度就報警 - 側輸出流;)、

B. 可以是有轉態的(求和、wordcount計算))

  • 狀態是針對一個任務而言的,由一個任務維護,並且用來計算某個結果的所有資料,都屬於這個任務的轉態;
  • 可以認為狀態就是一個本地變數,可以被任務的業務邏輯直接訪問;
  • Flink會進行狀態管理(狀態做序列化以二進位制的形式全部儲存起來),包括狀態一致性、故障處理以及高效儲存和訪問,以便開發人員可以專注於應用程式的邏輯。

在Flink中,狀態始終與特定運算元相關聯;為了執行時的Flink瞭解運算元的狀態,運算元需要預先註冊其狀態

有兩種狀態:

  運算元狀態(Operator State),運算元狀態的作用範圍限定為運算元任務,一個任務一個狀態;

  鍵控(分割槽)狀態(Keyed State)

,根據輸入資料流中定義的鍵(Key)來維護和訪問(基於KeyBy--KeyedStream上有任務出現的狀態,定義的不同的key來維護這個狀態;不同的key也是獨立訪問的,一個key只能訪問它自己的狀態,不同key之間也不能互相訪問);

A. 運算元狀態:

運算元狀態的作用範圍限定為運算元任務,由同一並行子任務所處理的所有資料都可以訪問到相同的狀態;

狀態對於同一個任務而言是共享的(每一個並行的子任務共享一個狀態);

運算元狀態不能由相同或不同運算元的另一個任務訪問(相同運算元的不同任務之間也不能訪問);

運算元狀態資料結構:

列表狀態(List state),將狀態表示為一組資料的列表;(會根據並行度的調整把之前的狀態重新分組重新分配

聯合列表狀態(Union list state),也將狀態表示為資料的列表,它常規列表狀態的區別在於,在發生故障時,或者從儲存點(savepoint)啟動應用程式時如何恢復(把之前的每一個狀態廣播到對應的每個運算元中)。

廣播狀態(Broadcast state),如果一個運算元有多項任務,而它的每項任務狀態又都相同,那麼這種特殊情況最適合應用廣播狀態(把同一個狀態廣播給所有運算元子任務);

B. 鍵控狀態(Keyed State)-- 更常用

鍵控狀態是根據輸入資料流中定義的鍵(key)來維度和訪問狀態的;

Flink為每個key維護一個狀態例項,並將具有相同鍵的所有資料,都分割槽到同一個運算元任務中,這個任務會維護和處理這個key對應的狀態;

當任務處理一條資料時,它會自動將狀態的訪問範圍限定為當前資料的key;

鍵控狀態資料結構:

值狀態(Value state),將狀態表示為單個值;(直接.value獲取,Set操作是.update)

列表狀態(List state),將狀態表示為一組資料的列表(存多個狀態);(.get,.update,.add)

對映狀態(Map state),將狀態表示為一組Key-Value對;(.get,.put ,類似HashMap)

聚合狀態(Reducing state & Aggregating State),將狀態表示為一個用於聚合操作的列表;(.add不像之前新增到列表,它是直接聚合到之前的結果中)

    Reduce輸入輸出型別是不能變的,Aggregate可得到資料型別完全不一樣的結果;

鍵控狀態的使用:

宣告一個鍵控狀態:
lazy val lastTemp: ValueState[Double] = getRuntimeContext.getState(
  new ValueStateDescriptor[Double]("lastTemp", classOf[Double])
)
讀取狀態:
val prevTemp = lastTemp.value()
對狀態賦值:
lastTemp.update(value.temperature)

C. 狀態後端(State Backends) -- 狀態管理(儲存、訪問、維護和檢查點)

每傳入一條資料,有狀態的運算元任務都會讀取和更新狀態;

由於有效的狀態訪問對於處理資料的低效遲至關重要,因此每個並行任務都會在本地維度其狀態,以確保快速的狀態訪問;

狀態的儲存、訪問以及維度,由一個可插入的元件決定,這個元件就叫做狀態後端(State Backends)

狀態後端主要負責兩件事:本地的狀態管理,以及將檢查點(checkpoint)狀態寫入遠端儲存;

狀態後端的分類:

MemoryStateBackend: 一般用於開發和測試

  • 記憶體級的狀態後端,會將鍵控狀態作為記憶體中的物件進行管理,將它們儲存在TaskManager的JVM堆上,而將checkpoint儲存在JobManager的記憶體中;
  • 特點快速、低延遲,但不穩定;

FsStateBackend(檔案系統狀態後端):生產環境

  • 將checkpoint存到遠端的持久化檔案系統(FileSystem)上,而對於本地狀態,跟MemoryStateBackend一樣,也會存到TaskManager的JVM堆上。
  • 同時擁有記憶體級的本地訪問速度,和更好的容錯保證;(如果是超大規模的需要儲存還是無法解決,存到本地狀態就可能OOM)

RocksDBStateBackend:

  • 將所有狀態序列化後,存入本地的RocksDB(本地資料庫硬碟空間)中儲存,全部序列化儲存到本地。