目錄
Apache Flink 流應用程序通常被設計爲無限期或長時間運行。與所有長時間運行的服務一樣,需要更新應用程序以適應不斷變化的需求。應用程序所針對的數據模式也是如此;它們隨着應用程序的發展而發展。
這個頁面提供瞭如何演進狀態類型的數據模式的概述。當前的限制因不同類型和狀態結構( ValueState、ListState 等)而異。
請注意,只有在使用由Flink自己的類型序列化框架生成的狀態序列化器時,此頁面的信息才相關。也就是說,在聲明狀態時,所提供的狀態描述符沒有配置爲使用特定的類型序列化器或類型信息,在這種情況下,Flink推斷關於狀態類型的信息:
ListStateDescriptor<MyPojoType> descriptor =
new ListStateDescriptor<>(
"state-name",
MyPojoType.class);
checkpointedState = getRuntimeContext().getListState(descriptor);
本質上,狀態模式是否可以演化取決於用於讀取/寫入持久狀態字節的序列化器。簡單地說,註冊狀態的模式只有在它的序列化程序正確地支持它的情況下才能得到發展。這是由 Flink 類型序列化框架生成的序列化器透明地處理的(當前支持範圍如下所示)。
如果您打算爲您的狀態類型實現自定義類型序列化器,並且希望瞭解如何實現序列化器來支持狀態模式演化,請參閱:自定義狀態序列化。那裏的文檔還包括關於狀態序列化器和 Flink 的狀態後端之間相互作用的必要內部細節,以支持狀態模式的演化。
進化狀態模式
要演進給定狀態類型的模式,您將採取以下步驟:
- 取你的Flink流作業的一個保存點。
- 更新應用程序中的狀態類型(例如,修改Avro類型模式)。
- 從保存點恢復作業。當第一次訪問狀態時,Flink將評估狀態模式是否已經更改,並在必要時遷移狀態模式。
遷移狀態以適應更改模式的過程是自動發生的,並且獨立於每個狀態。該過程由Flink在內部執行,首先檢查狀態的新序列化器是否具有與前一個序列化器不同的序列化模式;如果是,則使用先前的序列化器將狀態讀取到對象,然後使用新的序列化器再次將其寫入字節。
關於遷移過程的詳細信息超出了本文檔的範圍,請參考:Flink流處理(Stream API)- State & Fault Tolerance(狀態和容錯)之 Custom Serialization for Managed (管理狀態的自定義序列化)。
支持模式演化的數據類型
目前,模式演化只支持 POJO 和 Avro 類型。因此,如果您關心狀態的模式演化,那麼目前建議始終對狀態數據類型使用 Pojo 或 Avro。
POJO types
Flink 支持基於以下規則集的 POJO 類型的演進模式:
- 可以刪除字段。刪除後,刪除字段的前一個值將在以後的檢查點和保存點中刪除。
- 可以添加新字段。新字段將初始化爲其類型的默認值,如 Java 所定義的那樣。
- 聲明的字段類型不能更改。
- POJO 類型的類名不能更改,包括類的命名空間。
請注意,POJO類型狀態的模式只能在從以前的保存點恢復到比1.8.0更新的Flink版本時進行演化。使用大於1.8.0的Flink版本恢復時,模式不能更改。
Avro types
Flink 完全支持 Avro 類型狀態的模式演進,只要 Avro 的模式解析規則認爲模式更改是兼容的。
一個限制是,Avro生成的用作狀態類型的類在作業恢復時不能被重新定位或具有不同的名稱空間。
不支持鍵的模式演化。
示例:RocksDB狀態後端依賴於二進制對象標識,而不是hashCode方法實現。對keys對象結構的任何更改都可能導致不確定性行爲。
Kryo不能用於模式演化。
使用 Kryo 時,框架不可能驗證是否進行了任何不兼容的更改。