天天看點

【重新發現PostgreSQL之美】- 12 serverless & SaaS行業 & 多租戶 & 資源隔離 & 搗蛋鬼,你揍開

背景

場景:

  • 遊戲、SaaS行業. serverless 場景: 在一個企業内部, 業務線非常多,
  • 在同一個執行個體中有多個業務共同使用時,
  • 分析師、DBA或者營運人員有偶爾使用資料庫的需求.

挑戰:

  • 為每個業務配置設定一個資料庫執行個體存在的問題: 資源浪費(每個執行個體在記憶體、空間方面的浪費)、彈性較差(建立資源慢、擴容縮容慢).
  • 多個業務共享一個執行個體存在的問題: 資源争搶、幹擾、抖動、安全風險增加,
  • DBA或分析師人為的大查詢可能将資源耗光, 影響線上業務

PG 方案:

  • 按來源IP、USER、DBNAME、application_name等資訊來區分使用者和業務
  • 結合cgroup隔離業務的cpu、io、網絡等資源使用率, 防止幹擾

例子

cgroup 配置舉例

限制組cgroupA的任務最多可以使用8核資源

限制組cgroupB的任務最多可以使用16核資源

加載CPU子系統,建立子資源分區

mount -t cgroup -o cpu cpu /cgroup/cpu      
cd /cgroup/cpu      
mkdir cgroupA      
mkdir cgroupB      

配置資源配比(以100為基數,核數乘以100即得到cpu.shares)

echo 800 > cpu.shares      
echo 1000000 > cpu.cfs_period_us      
echo 8000000 > cpu.cfs_quota_us      
cd ../cgroupB      
echo 1600 > cpu.shares      
echo 1000000 > cpu.cfs_period_us      
echo 16000000 > cpu.cfs_quota_us      

将PID放入某個cgroup組

建立一個shell将PID放入某個cgroup組

腳本内容略

配置允許PG程序的啟動賬号sudo執行該指令

202011/20201107_03.md  《Linux : 使用sudoedit 配置- 允許普通使用者a以另一個使用者b或組g執行某些特定指令》

在資料庫中建立plpythonu, 調用shell, 将目前會話PID放入對應cgroup

create or replace function exec_cmd2(cmd text) returns setof text as $$      
import os      
v = os.popen('/home/digoal/cpu_cgroup.sh ' + cmd)      
return v      
$$ language plpythonu;      

以下例子, 簡單粗暴的邏輯,

  • postgres 使用者登陸後, 會話對應的backend PID 會塞入cgroupA
  • digoal 使用者登陸後, 會話對應的backend PID 會塞入cgroupB

實際使用中可以配置一個映射表,從映射表裡面擷取規則.

declare      
pid int := pg_backend_pid();      
begin      
case current_user      
when 'postgres' then perform exec_cmd2(format('%s %s',pid, 'cgroupA'));      
when 'digoal' then perform exec_cmd2(format('%s %s',pid, 'cgroupB'));      
else raise notice 'not mapping users cgroup';      
end case;      
end;      
$$ language plpgsql strict;      

配置login hook, 建立會話時, 自動執行以上函數

session_preload_libraries = 'session_exec'      
session_exec.login_name = 'exec_cmd'      

postgres 使用者登陸後, 會話對應的backend PID 會塞入cgroupA

digoal 使用者登陸後, 會話對應的backend PID 會塞入cgroupB

更複雜的邏輯

限制邏輯還可以更複雜一點, 例如, 根據:

  • 來源IP
  • 登陸的使用者
  • 登陸的資料庫
  • application_name(使用者在連接配接URL裡面可以設定, 用來區分不同的業務)
  • 登陸的時間
  • 目前執行個體級資源使用率
  • 目前各個cgroup的資源使用率
  • 目前映射的cgroup的資源使用率

實施動作:

  • 将目前會話的PID放入某個cgoup組進行限制
  • 擴大或縮小某個cgroup的限制上限. 例如淩晨放大BI業務的限制, 白天縮小BI業務的限制.

其他cgoup可以限制的名額:

  • io, 讀寫吞吐, 網絡流量, 記憶體等

參考

https://github.com/okbob/session_exec
202007/20200727_02.md  《PostgreSQL登入(建立會話)hook - login "trigger"插件》
201710/20171023_01.md  《在PostgreSQL中使用plpythonu 調用系統指令》
201606/20160613_01.md  《Linux cgroup - cpu與cpuset子系統講解》
201606/20160611_01.md  《Linux cgroup資源隔離各個擊破之- io隔離》