Apache Flink 是一個即時數據流處理引擎。大多數流處理應用程序都是“有狀態”的。這意味著狀態被存儲並用於進一步處理。在 Apache Flink 中,狀態是通過配置的狀態後端來管理的。Flink 支持兩種生產中的狀態後端。一種是 HashMapStateBackend
,另一種是 EmbeddedRocksDBStateBackend
。
為了防止數據丟失並實現容錯性,Flink 可以將狀態的快照持久化到可靠的存儲中。Flink 可以配置為將整個狀態快照到可靠位置或自上次快照以來的增量快照。前者稱為完整檢查點,後者稱為增量檢查點。
在本文中,我們將比較帶有完整檢查點的 HashMapStateBackend
和帶有增量檢查點的 EmbeddedRocksDBStateBackend
。本文假設讀者對Apache Flink具有工作知識或理論知識。
Flink 狀態後端概述
要理解 Flink 狀態後端,重要的是要了解在途狀態和狀態快照之間的區別。
在途狀態被稱為 Flink 的工作狀態,並存儲在本地。根據狀態後端配置,它可能位於堆內存或堆外存儲器中,並可能溢出到本地磁盤。
另一方面,狀態快照(檢查點或保存點)存儲在持久的遠程位置。這些快照用於在作業失敗時重建 Flink 作業狀態。
如果作業失敗,正在進行的狀態可能會丟失。如果作業中啟用了檢查點,則這不會影響作業恢復。當配置檢查點時,狀態將從持久存儲中檢索以進行恢復。
在生產環境中選擇哪種狀態後端取決於應用對吞吐量、延遲和可擴展性的需求。
Apache Flink 在生產環境中支持兩種狀態後端。
1. HashMapStateBackend
這是 Flink 中用於管理流處理期間的 Keyed State 和 Operator State 的輕量級狀態後端。狀態存儲在使用 HashMap 數據結構的 Java Heap 中。由於它存儲在內存中,這裡的主要限制是最大狀態大小受限於 Java Heap 大小。寫入狀態或從狀態讀取時不涉及序列化。因此,這適用於低延遲、高吞吐量和狀態不是很大的應用程序。
2. EmbeddedRocksDBStateBackend
此狀態後端將在內存中的RocksDB數據庫中存儲在飛數據。默認情況下,RocksDB將數據存儲在任務管理器的本地磁盤中。數據被序列化並存儲在非堆內存中,並溢出到與任務管理器相連的本地磁盤。序列化格式取決於應用程序中配置的類型序列化器。
使用此狀態後端,可以存儲的狀態量僅受限於與任務管理器相連的磁盤空間。如果應用程序具有龐大的狀態且無法包含在堆內存中,這是正確的狀態後端。由於涉及序列化,與HashMapStateBackend
相比,應用程序的延遲會更高,吞吐量會更低。
快照狀態概述
快照代表Flink作業的全局狀態。這包括每個數據源的指針以及在處理到這些指針來自數據源的所有Flink有狀態運算符之後的狀態。Apache Flink中的檢查點是通過定期將狀態保存到耐用的遠程存儲來實現容錯的機制。
在作業失敗的情況下,Flink會從耐用的遠程存儲中檢索存儲的狀態,並從中斷點處開始處理流式數據。Flink使用異步屏障快照。這是Chandy-Lamport算法的一種變體。
Flink支持兩種類型的檢查點。
1. 完整檢查點
完整的檢查點是指將整個 Flink 作業的狀態捕獲並存儲在持久的遠程存儲中。在作業故障的情況下,作業會從之前存儲的狀態中恢復。存儲空間需求和執行檢查點所需的時間完全取決於應用程序狀態。完整的檢查點與 HashMapStateBackend
和 RocksDBStateBackend
一起使用。
2. 增量檢查點
增量檢查點是一種優化的方法。 Flink 不再對整個狀態進行快照,而是僅保存自上次檢查點以來對狀態進行的“增量”。這減少了網絡開銷,從而縮短了檢查點的時間。在這種情況下,檢查點是完全異步進行的。
只有 RocksDBStateBackend
支持增量檢查點。 Flink 利用 RocksDB 的內部機制來實現這一點。儘管檢查點所需的時間比完整檢查點少,但在作業故障的情況下,恢復時間取決於許多因素。如果網絡成為瓶頸,恢復時間可能會高於從完整檢查點恢復。
分析
管道詳情:Apache Beam 管道運行在具有固定窗口為 10 分鐘的 Flink 引擎上,並且配置了每 3 分鐘運行一次檢查點。配置的序列化類型是 AVRO。
- 集群類型:”m5dn.4xlarge”
- 最終檢查點存儲:S3
- 唯一鍵數量:2K
Input rate 10k/s (~ 7.8 MB/s) | |||||||||
---|---|---|---|---|---|---|---|---|---|
輸入 | 號碼: TM |
並行性 | 堆分配 每個TM |
堆使用 每個TM |
Pod內存使用 每個TM |
CPU使用率 每個TM |
檢查點 大小 |
檢查點 持續時間 |
Flink管理 內存 |
HashMap狀態 使用完整檢查點 |
1 | 1 | 10GB | 8.5GB | 11.1GB | 1.2 | 4GB | 50秒 | 0 |
RocksDB狀態 使用增量檢查點與AVRO |
1 | 1 | 3GB | 1.82GB | 4.63GB | 1.5 | 207MB | 3秒 | 3GB |
Input rate 20k/s (~15.6 MB/s) | |||||||||
---|---|---|---|---|---|---|---|---|---|
輸入 | 號碼: TM |
並行性 | 堆分配 每個TM |
堆使用 每個TM |
Pod使用 每個TM |
CPU使用率 每個TM |
檢查點 大小 |
檢查點 持續時間 |
Flink管理 內存 |
HashMap狀態 使用完整檢查點 |
2 | 2 | 10GB | 8.69GB | 11.2GB | 1.3 | 8.39GB | 50秒 | 0 |
RocksDBState 帶有增量 使用AVRO的檢查點 |
2 | 2 | 3GB | 1.87GB | 4.71GB | 1.4 | 404MB | 3秒 | 3GB |
input rate 30k/s (~23.5 MB/s) | |||||||||
---|---|---|---|---|---|---|---|---|---|
類型 | TM數: 平行度 |
堆分配 | 每個TM | 堆使用 每個TM |
Pod使用 每個TM |
CPU使用率 每個TM |
檢查點 大小 |
檢查點 持續時間 |
Flink管理 記憶體 |
HashMapState 帶有完整檢查點 |
3 | 3 | 10GB | 9.74GB | 11.2GB | 1.2 | 11.8GB | 65秒 | 0 |
RocksDBState 帶有增量 AVRO檢查點 |
3 | 3 | 3GB | 1.72GB | 3.75GB | 1.4 | 576MB | 5秒 | 3GB |
如您可以從上述實驗中看到,增量檢查點的持續時間減少。這對應用程式的性能非常有幫助。
摘要
以下是實驗的摘要。
HashMapStateBackend帶有完整檢查點 | 帶有增量檢查點的RocksDBStateBackend | |
應用程式延遲 | 低延遲,因為數據以Java對象形式存儲在堆中。讀寫不涉及任何序列化。 | 由於每次讀寫應用都涉及序列化,因此延遲將更高。 |
可擴展性 | 對於具有大狀態的作業來說可擴展性較差 | 對於具有大狀態和變化緩慢的作業來說非常可擴展 |
容錯性 | 容錯性很高 | 容錯性很高 |
檢查點持續時間 | 檢查點持續時間很長,因為每次都要對整個數據集進行快照。 | 檢查點持續時間較短,因為僅保存自上次檢查點以來的增量。 |
恢復複雜性 | 恢復很容易,因為只需加載一個快照。 | 恢復復雜,因為RocksDB必須從多個檢查點構建狀態,很大程度上取決於網絡速度。 |
存儲需求 | HashMapStateBackend和RocksDBStatebackend都支持。 | 僅由RocksDBStatebackend支持。 |
狀態快照 | 每次檢查點都保存整個狀態。 | 僅保存自上次成功檢查點以來的增量。 |
堆大小 | 由於狀態在檢查點之前存儲在堆中,因此堆需求很高,並且預計會有更多的GC週期。 | 狀態被存儲在堆外並可能存儲在本地磁盤上,因此佔用較少的堆空間並減少了GC週期。 |
狀態後端大小 | 限制於為JVM分配的最大堆大小。 | RocksDB狀態後端大小不受JVM堆限制,僅受可用磁盤空間限制。 |
性能影響 | 對處理性能有較大影響,因為它是完整快照。 | 對處理性能的影響較小,因為僅對快照的增量進行了快照。 |
CPU | CPU使用僅用於處理和GC。不涉及狀態後端序列化。 | 與完整檢查點相比,對相同輸入數據速率的CPU使用率較高。
通過應用適當的序列化機制可以優化CPU利用率。我們實驗了Avro,與Kryo相比取得了更好的結果。 |
最佳使用案例 | 適用於較小的狀態後端大小和經常變更的狀態。 | 適用於較大的狀態後端和緩慢更新狀態。 |
Source:
https://dzone.com/articles/apache-flink-full-checkpoint-vs-incremental-checkpoint