本文介紹了PolarDB PostgreSQL版的Resource Manager資源限制機制。
背景介紹
PolarDB PostgreSQL版的內存可以分為以下三部分:
共享內存。
進程間動態共享內存。
進程私有內存。
進程間動態共享內存和進程私有內存是動態分配的,其使用量隨著集群承載的業務運行情況而不斷變化。過多使用動態內存,可能會導致內存使用量超過操作系統限制,觸發內核內存限制機制,造成進程異常退出,節點重啟,引發集群不可用的問題。
進程私有內存(Memory Context)管理的內存可以分為兩部分:
工作計算區域內存:業務運行所需的內存,此部分內存會影響業務的正常運行。
Cache內存:數據庫會把部分內部元數據存放在進程內,此部分內存只會影響數據庫性能。
為了解決以上問題,PolarDB PostgreSQL版增加了Resource Manager資源限制機制,能夠在集群運行期間,周期性檢測資源使用情況。對于超過資源限制閾值的進程,強制進行資源限制,降低集群不可用的風險。
Resource Manager主要的限制資源有:
內存。
CPU。
I/O。
當前Resource Manager僅支持對內存資源進行限制。
內存限制原理
內存限制依賴Cgroup,如果不存在Cgroup,則無法有效進行資源限制。Resource Manager作為PolarDB PostgreSQL版一個后臺輔助進程,通過周期性讀取Cgroup的內存使用數據作為內存限制的依據。當發現存在進程超過內存限制閾值后,會讀取內核的用戶進程內存記賬,按照內存大小排序,依次對內存使用量超過閾值的進程發送中斷進程信號(SIGTERM)或取消操作信號(SIGINT)。
內存限制方式
Resource Manager(簡稱RM)守護進程會隨著集群啟動而建立,同時對主節點、只讀節點以及Standby節點起作用。可以通過修改參數改變Resource Manager的行為。當前RM限制內存的方式為,在集群內存使用超過RM參數設定的內存閾值后,會對使用內存較多的進程發送SIGTERM信號,終止進程以釋放內存。具體參數說明如下:
參數 | 描述 |
enable_resource_manager | 是否啟用Resource Manager,取值范圍如下:
|
stat_interval | 資源使用量周期檢測的間隔,單位為毫秒,取值范圍為10~10000,默認值為500。 |
total_mem_limit_rate | 限制集群內存使用的百分比,當集群內存使用超過該百分比后,開始強制對內存資源進行限制,默認值為95。 |
total_mem_limit_remain_size | 集群內存預留值,當集群空閑內存小于預留值后,開始強制對內存資源進行限制,單位為KB,取值范圍為131072~ |
mem_release_policy | 內存資源限制的策略,取值范圍如下:
|
內存限制效果
當用戶會話進程接收到SIGTERM信號后,會終止當前進程,并將終止信息寫入到日志中。日志內容如下:
2022-11-28 14:07:56.929 UTC [18179] LOG: [polar_resource_manager] terminate process 13461 release memory 65434123 bytes
2022-11-28 14:08:17.143 UTC [35472] FATAL: terminating connection due to out of memory
2022-11-28 14:08:17.143 UTC [35472] BACKTRACE:
postgres: primary: postgres postgres [local] idle(ProcessInterrupts+0x34c) [0xae5fda]
postgres: primary: postgres postgres [local] idle(ProcessClientReadInterrupt+0x3a) [0xae1ad6]
postgres: primary: postgres postgres [local] idle(secure_read+0x209) [0x8c9070]
postgres: primary: postgres postgres [local] idle() [0x8d4565]
postgres: primary: postgres postgres [local] idle(pq_getbyte+0x30) [0x8d4613]
postgres: primary: postgres postgres [local] idle() [0xae1861]
postgres: primary: postgres postgres [local] idle() [0xae1a83]
postgres: primary: postgres postgres [local] idle(PostgresMain+0x8df) [0xae7949]
postgres: primary: postgres postgres [local] idle() [0x9f4c4c]
postgres: primary: postgres postgres [local] idle() [0x9f440c]
postgres: primary: postgres postgres [local] idle() [0x9ef963]
postgres: primary: postgres postgres [local] idle(PostmasterMain+0x1321) [0x9ef18a]
postgres: primary: postgres postgres [local] idle() [0x8dc1f6]
/lib64/libc.so.6(__libc_start_main+0xf5) [0x7f888afff445]
postgres: primary: postgres postgres [local] idle() [0x49d209]