- Flink內核原理與實現
- 馮飛 崔鵬云 陳冠華編著
- 1403字
- 2021-04-14 11:30:43
6.2 內存模型
Flink 1.10以前的版本中內存模型存在一些缺陷,導致優化資源充分利用率比較困難,例如:
● 流和批處理內存占用的配置模型不同,配置參數多、關系亂。
● 流處理中的RocksDBStateBackend需要依賴用戶進行復雜的配置。
為了讓內存配置對于用戶更加清晰、直觀,Flink 1.10版本對TaskExecutor的內存模型和配置邏輯進行了較大的改動(FLIP-49)。這些改動使得Flink能夠更好地適配所有部署環境(如Kubernetes、Yarn、Mesos),讓用戶能夠更加嚴格地控制其內存開銷。
6.2.1 內存布局
TaskManager是Flink中執行計算的核心組件,是用來運行用戶代碼的Java進程。其中大量使用了堆外內存。
Flink TaskManager的簡化和詳細內存結構如圖6-2所示。

圖6-2 Flink TaskManager簡化和詳細內存模型
從大的方面來說,TaskManager進程的內存模型分為JVM本身所使用的內存和Flink使用的內存,Flink使用了堆上內存和堆外內存。
1. Flink使用的內存
(1)JVM堆上內存
1)框架堆上內存Framework Heap Memory。Flink框架本身所使用的內存,即TaskManager本身所占用的堆上內存,不記入Slot的資源中。
配置參數:taskmanager.memory.framework.heap.size = 128MB,默認128MB。
2)Task堆上內存Task Heap Memory。Task執行用戶代碼時所使用的堆上內存。
配置參數:taskmanager.memory.task.heap.size。
(2)JVM堆外內存
1)框架堆外內存Framework Off-Heap Memory。Flink框架本身所使用的內存,即TaskManager本身所占用的堆外內存,不記入Slot資源。
配置參數:taskmanager.memory.framework.off-heap.size = 128MB,默認128MB。
2)Task堆外內存Task Off-Heap Memory。Task執行用戶代碼時所使用的堆外內存。
配置參數:taskmanager.memory.task.off-heap.size = 0,默認為0。
3)網絡緩沖內存Network Memory。網絡數據交換所使用的堆外內存大小,如網絡數據交換緩沖區(Network Buffer,后文會介紹)。
配置參數:taskmanager.memory.network.[64/1024/0.1])(min/max/fraction),默認min=64MB, max=1gb, fraction=0.1。
4)堆外托管內存Managed Memory。Flink管理的堆外內存。
配置參數:taskmanager.memory.managed.[size|fraction]),默認fraction=0.4。
2. JVM本身使用的內存
JVM本身直接使用了操作系統的內存。
(1)JVM元空間
JVM元空間所使用的內存。
配置參數:taskmanager.memory.jvm-metaspace =96m,默認96MB。
(2)JVM執行開銷
JVM在執行時自身所需要的內容,包括線程堆棧、IO、編譯緩存等所使用的內存。
配置參數:taskmanager.memory.jvm-overhead = [min/max/fraction])。默認min=192MB,max=1GB, fraction=0.1。
3. 總體內存
(1)Flink使用內存
綜上而言,Flink使用的內存包括Flink使用的堆上、堆外內存。使用參數taskmanager. memory.flink.size進行控制。
(2)進程使用內存
整個進程所使用的內存,包括Flink使用的內存和JVM使用的內存。使用參數taskmanager.memory.process.size進行控制。
JVM內存控制參數如下所示。
1)JVM堆上內存,使用-Xmx和-Xms參數進行控制。
2)JVM直接內存,使用參數-XX:MaxDirectMemorySize進行控制。對于托管內存,使用Unsafe.allocateMemory()申請,不受該參數控制。
3)JVM Metaspace使用-XX:MaxMetaspaceSize進行控制。
6.2.2 內存計算
目前的實現中,在JVM啟動之前就需要確定各個內存區塊的大小。一旦JVM啟動了,在TaskManager進程內部就不再重新計算。Flink中有兩個地方進行內存大小計算:
● 在Standalone部署模式下,內存的計算在啟動腳本中實現。
● 在容器環境下(Yarn、K8s、Mesos),計算在ResourceManager中進行。
在啟動腳本與容器環境下的內存大小計算都調用了Fink的Java代碼時間,保證了所有部署模式下的統一,計算好的參數使用-D參數交給Java進程。
計算時,需要配置如下3個參數組合中的至少1個。
(1)Task的堆上內存和托管內存
如果手動配置了網絡緩沖區內存大小,則使用該參數。如果沒有明確配置,則使用分配系數fraction×總體Flink使用內存計算網絡緩沖區內存大小。
(2)總體Flink使用內存
如果配置了該選項,而沒有配置(1),則從總體Flink內存中劃分網絡緩沖區內存和托管內存,剩余的內存作為Task堆上內存。
如果手動設置了網絡緩沖內存,則使用其值,否則使用默認的分配系數fraction×總體Flink內存。
如果手動設置了托管內存,則使用其值,否則使用默認的分配系數fraction×總體Flink內存。
(3)總體進程使用內存
如果只配置了總體進程使用內存,則從總體進程中扣除JVM元空間和JVM執行開銷內存,剩余的內存作為總體Flink使用內存。