Flink的State類型
基本類型劃分:
在Flink中,按照基本類型,對State做了以下兩類的劃分:
Keyed State,和Key有關的狀態類型,它只能被基於KeyedStream之上的操作,方法所使用。我們可以從邏輯上理解這種狀態是一個並行度操作實例和一種Key的對應, <parallel-operator-instance, key>。
Operator State(或者non-keyed state),它是和Key無關的一種狀態類型。相應地我們從邏輯上去理解這個概念,它相當於一個並行度實例,對應一份狀態數據。因爲這裏沒有涉及Key的概念,所以在並行度(擴/縮容)發生變化的時候,這裏會有狀態數據的重分佈的處理。
組織形式劃分:
但是在這裏還有一種按照組織形式的劃分,也可以理解爲按照runtime層面的劃分,又可以分爲一下兩類:
Managed State,這類State的內部結構完全由Flink runtime內部來控制,包括如何將它們編碼寫入到checkpoint中等等。
Raw State,這類State就比較顯得靈活一些,它們被保留在操作運行實例內部的數據結構中。從Flink系統角度來觀察,在checkpoint時,它只知道的是這些狀態數據是以連續字節的形式被寫入checkpoint中。等待進行狀態恢復時,又從字節數據反序列化爲狀態對象。
Managed State可以在所有的data stream相關方法中被使用,官方也是推薦優先使用這類State,因爲它能被Flink runtime內部做自動重分佈而且能被更好地進行內存管理。
爲什麼需要State?作用是什麼?
1 保存中間結果,實現某些功能
2 方便保存到檢查點中,便於從檢查點恢復
Keyed State 與 Operator State 區別
一個算子的並行度是多少,就有多少個子任務。如果不同的key比較多,該算子的並行度低,那麼一個子任務會處理多個key流。
Keyed State 與key相關,Operator State 與key無關。
實現Operator State,需要手動實現CheckpointedFunction或ListCheckpointed 接口
Managed Keyed State包含:
ValueState<T>
ListState<T>
ReducingState<T>
AggregatingState<IN, OUT>
FoldingState<T, ACC>
MapState<UK, UV>
Managed Operator State包含:
ListState
UnionListState
BroadcastState
Managed State 與 Raw State區別
Flink有兩種基本類型的狀態:託管狀態(Managed State)和原生狀態(Raw State)。從名稱中也能讀出兩者的區別:Managed State是由Flink管理的,Flink幫忙存儲、恢復和優化,Raw State是開發者自己管理的,需要自己序列化。
兩者的具體區別有:
- 從狀態管理的方式上來說,Managed State由Flink Runtime託管,狀態是自動存儲、自動恢復的,Flink在存儲管理和持久化上做了一些優化。當我們橫向伸縮,或者說我們修改Flink應用的並行度時,狀態也能自動重新分佈到多個並行實例上。Raw State是用戶自定義的狀態。
- 從狀態的數據結構上來說,Managed State支持了一系列常見的數據結構,如ValueState、ListState、MapState等。Raw State只支持字節,任何上層數據結構需要序列化爲字節數組。使用時,需要用戶自己序列化,以非常底層的字節數組形式存儲,Flink並不知道存儲的是什麼樣的數據結構。
- 從具體使用場景來說,絕大多數的算子都可以通過繼承Rich函數類或其他提供好的接口類,在裏面使用Managed State。Raw State是在已有算子和Managed State不夠用時,用戶自定義算子時使用。
Keyed State 用法:
Operator State用法:
Flink Operator State 實例 實現ListCheckpointed
Flink Operator State 實例 實現CheckpointedFunction
CheckpointedFunction 可對多種類型的狀態進行保存、恢復、初始化;當並行度變化時,支持按照Even-split Redistribution重分佈策略(默認)和Union redistribution重分佈策略;
ListCheckpointed 只能對List類型的狀態進行保存、恢復;當並行度變化時,只支持按照Even-split Redistribution重分佈策略。
Even-split redistribution:每個算子返回一個狀態數據的list集合。 當從 checkpoint 中恢復狀態數據或者進行重新分配的時候,List 類型的狀態數據將被均勻切割成和並行示例數量一致的子鏈表(每個子鏈表的元素個數一致),每個算子獲得一個子鏈表,子鏈表可能爲空,也可能包含一個或多個數據。例如,當一個並行度爲1 算子,擁有一個 ListState,其中包含數據 e1、e2,當算子的並行改成 2 的時候,發生重新分配,ListState 被切分成兩個子鏈,算子的並行實例1 獲得包含 e1 的ListState, 並行實例2 獲得包含 e2 的ListState。
Union redistribution:每個算子返回一個狀態數據的 List 集合,包含所有的狀態數據。當發生重新分配或者從 checkpoint 中恢復狀態數據的時候,每個算子都將獲取到全部的狀態數據。
參考:
https://cloud.tencent.com/developer/article/1584935
https://blog.csdn.net/Androidlushangderen/article/details/86485850
https://summerbuger.github.io/2019/01/26/%E6%8A%80%E6%9C%AF/flink/flink%E4%B9%8Bstate/