Presto記憶體管理包括了單機和叢集粒度的記憶體,有如下參數設定:
- query.max-memory-per-node:單個Query在單個Worker上允許的最大 user memory
- query.max-total-memory-per-node:單個Query在單個Worker上允許的最大 user memory + system memory
- query.max-memory:單個Query在整個叢集上允許的最大 user memory
- query.max-total-memory:單個Query在整個叢集上允許占用的最大 user memory + system memory
乍看之下,感覺還是很簡單的,其實這裡面有個大坑!
在填坑之前,有必要給大家鋪墊一些Presto的基礎知識:
1、Presto的2種記憶體
- 一種是user memory,用于 input/output/exchange buffers 等
- 另一種是system memory,用于 hash join、agg等
2、Presto的記憶體池
Presto在版本0.201之前有3種記憶體POOL,分别是 GENERAL_POOL、RESERVED_POOL 及 SYSTEM_POOL。但是0.201之後,預設 SYSTEM_POOL 是不開啟的,由以下參數控制,預設值為false
deprecated.legacy-system-pool-enabled
簡單來說,0.201之後,GENERAL_POOL 扮演了之前 GENERAL_POOL 及 SYSTEM_POOL 的作用,提供 user memory 和 system memory。
另外,RESERVED_POOL 作用就是當 GENERAL_POOL 滿的時候,将最占用記憶體的SQL配置設定到這塊記憶體上來,但是實際使用時,這塊記憶體很少會被使用,原因是:
- 一般使用Presto的業務是用來SQL提速的,不會使用 spill to disk 功能
- 第二,為了服務的穩定性,會限制最大記憶體和Kill記憶體政策,是以會出現查詢沒有被配置設定到 RESERVED_POOL 之前,SQL将會被系統Kill掉
- 第三,大查詢一般會用 Spark/Hive 替代
是以,對于絕大部分Presto使用者,禁止掉 RESERVED_POOL 是正确的選擇。
3、新增加的heap-headroom-per-node參數
memory.heap-headroom-per-node
這個記憶體主要是第三方庫的記憶體配置設定,無法被統計跟蹤,預設值是 Xmx*0.3。
是以,一般情況下,Presto記憶體配置設定隻需要考慮 GENERAL_POOL 及 heap-headroom-per-node。
4、如何設定 GENERAL_POOL?(天坑)
大多數同學容易将 query.max-total-memory-per-node 這個參數當作是 GENERAL_POOL,這是不對的。其實 query.max-total-memory-per-node 這個參數是設定 RESERVED_POOL 的,即:
RESERVED_POOL = query.max-total-memory-per-node
GENERAL_POOL 不是通過參數直接設定的,需要計算一下:
GENERAL_POOL = Xmx - RESERVED_POOL - memory.heap-headroom-per-node
如果禁用掉 RESERVED_POOL:
GENERAL_POOL = Xmx - memory.heap-headroom-per-node
舉個栗子,假如 -Xmx80g,Worker數大于8台:
query.max-memory=120GB # 預設為20GB,query.max-memory-per-node * 8 * 0.8 ,傾斜按照0.8算即可
query.max-memory-per-node=20GB # 預設值0.1*Xmx,一般線上按照0.25*Xmx算,這個最好結合自己并發,如果并發大,大查詢多,值最好小一點,穩定性考慮
query.max-total-memory-per-node=32GB # 預設值0.3*Xmx,一般設定為0.4*Xmx
experimental.reserved-pool-enabled=false # 不使用RESERVED_POOL
memory.heap-headroom-per-node=16GB # 預設0.3*Xmx,一般使用的是0.2*Xmx
query.low-memory-killer.policy=total-reservation-on-blocked-nodes # Kill政策,幹掉Blocked的最大查詢,GENERAL_POOL滿了,防止OOM
按照上面的配置,在不使用 RESERVED_POOL 的情況下,GENERAL_POOL = 80GB - 16GB = 64GB。
騷年,你學廢了嗎?