背景
Flink作業設置內存參數後發現不是自己預期的資源分配方式,比如分配了4G內存結果只用了2G,其餘2G都是閒置的,導致Flink作業內存上限不夠用,內存超用時TaskManager容器會被Yarn集羣殺死。另外並行度與slot槽數在Flink on Yarn集羣模式下如何設置才能資源利用最大化,在本文給出優化建議
Flink TM內存分配機制
內存分配區域說明
組成部分 |
描述 |
框架堆內存 Framework Heap Memory |
用於 Flink 框架的 JVM 堆內存(進階配置)。 |
任務堆內存 Task Heap Memory |
用於 Flink 應用的算子及用戶代碼的 JVM 堆內存。 |
託管內存 Managed memory |
由 Flink 管理的用於排序、哈希表、緩存中間結果及 RocksDB State Backend 的本地內存。 |
框架堆外內存 Framework Off-heap Memory |
用於 Flink 框架的堆外內存(直接內存或本地內存)(進階配置)。 |
任務堆外內存 Task Off-heap Memory |
用於 Flink 應用的算子及用戶代碼的堆外內存(直接內存或本地內存)。 |
網絡內存 Network Memory |
用於任務之間數據傳輸的直接內存(例如網絡傳輸緩衝)。該內存部分爲基於 Flink 總內存的受限的等比內存部分。這塊內存被用於分配網絡緩衝 |
JVM Metaspace |
Flink JVM 進程的 Metaspace。 |
JVM overhead |
用於其他 JVM 開銷的本地內存,例如棧空間、垃圾回收空間等。該內存部分爲基於進程總內存的受限的等比內存部分。 |
內存分配案例
設置(進程總內存)
taskmanager.memory.process.size:4196m
設置託管內存分配比例
taskmanager.memory.managed.fraction:0.4 (默認)
taskmanager.memory.managed.fraction:0.2
自動分配區域 |
分配內存值0.4 |
分配內存值0.2 |
備註 |
Framework Heap Memory |
128MB |
128MB |
|
Task Heap Memory |
1.47G |
2.16G |
任務算子可用內存空間 (影響任務效率) |
Managed memory |
1.38G |
704MB |
狀態緩存可用內存空間 (影響checkpoint效率) |
Framework Off-heap Memory |
128MB |
128MB |
|
Task Off-heap Memory |
0b |
0B |
|
Network Memory |
352MB |
352MB |
閒置內存空間 |
JVM Metaspace |
256MB |
256MB |
使用少量內存空間 |
JVM overhead |
420MB |
420MB |
閒置內存空間 |
申請、容器內存合計 |
4196MB |
4196MB |
|
設置(Flink總內存)
taskmanager.memory.flink.size:4G
自動分配區域 |
分配內存值0.4 |
分配內存值0.2 |
備註 |
Framework Heap Memory |
128MB |
128MB |
|
Task Heap Memory |
1.80G |
2.62G |
任務算子可用內存空間 (影響任務效率) |
Managed memory |
1.64G |
839MB |
狀態緩存可用內存空間 (影響checkpoint效率) |
Framework Off-heap Memory |
128MB |
128MB |
|
Task Off-heap Memory |
0b |
0B |
|
Network Memory |
420MB |
420MB |
閒置內存空間 |
申請內存合計 |
4196MB |
4196MB |
|
JVM Metaspace |
256MB |
256MB |
使用少量內存空間 |
JVM overhead |
495MB |
495MB |
閒置內存空間 |
容器內存合計 |
4947MB |
4947MB |
metaspace、overhead單獨分配內存,不計入到申請內存中,容器內存會比預期申請的內存要大 |
案例分析
1、在相同的託管內存分配比例情況下,跟taskmanager.memory.process.size比較,設置taskmanager.memory.flink.size能申請分配更多的任務算子可用內存空間,因爲JVM Metaspace、JVM overhead這兩塊區域空間不計入內存分配池子,額外算一部分內存(根據這兩個參數的比例因子)
2、不管設置process.size還是flink.size,Network Memory、JVM overhead這兩塊空間都是閒置的內存空間,基本不會使用到,所以作業並行度和slot槽數設置越多(yarn集羣下1並行度對應一個TaskManager容器),閒置內存空間會越多
實踐總結
1、儘量設置taskmanager.memory.flink.size參數,能得到更多任務可用內存和託管內存
2、taskmanager.memory.managed.fraction託管內存分配比例這個參數只有在使用rocksdb狀態存儲情況下需要考慮設置成0.1~0.2值,使用hashmap可以設置更低,因爲從實踐來看基本不會用到這部分內存空間,目的就是儘可能的提高Task Heap Memory這塊區域的內存可用空間,實踐經驗這塊區域內存可用空間越大,Flink作業的吞吐量越大,作業的穩定性越高
3、TaskManager容器一般設置個3~4個就夠了,更多的是提高任務可用內存空間的上限,在總內存相同情況下容器越多效率不一定高,容器多帶來的網絡IO消耗也更多
4、對於 YARN,如果 yarn.nodemanager.pmem-check-enabled設爲true(公司集羣已關閉) , 則會在運行時定期檢查容器內的進程是否超用內存。如果進程總內存用量超出配額,容器平臺通常會直接發送最嚴格的 SIGKILL 信號(相當於 )來中止 TaskManager,此時不會有任何延期退出的機會,可能會造成作業崩潰重啓、外部系統資源無法釋放等嚴重後果,所以沒關閉這個檢測前,提高容器算子任務可用內存上限很重要