GaussDB細粒度資源管控技術透視

本文分享自華爲雲社區《【GaussTech速遞】技術解讀之細粒度資源管控》,作者:GaussDB 數據庫。

背景

對數據庫集羣內資源管控與資源隔離一直是企業客戶長久以來的訴求。華爲雲GaussDB作爲一款企業級分佈式數據庫,一直致力於滿足企業對大型數據庫集羣的管理需要。

數據庫可以管理的資源有計算資源與存儲資源,計算資源包括CPU、內存、IO與網絡,存儲資源包括數據存儲空間、日誌存儲空間與臨時文件等。

從用戶角度來看,資源管控通過設定閾值或者優先級限定程序對資源的使用,保證承諾服務等級協議的同時,又滿足不同用戶間資源隔離,達成多個租戶共享數據庫資源的目的。

從系統的角度來看,引入資源監控與控制的手段,可以實現資源在可控情況下被合理利用的目的,避免資源耗盡,防止系統停止響應、崩潰等情況的發生。作業優先級,可以保證作業平穩運行,避免某個作業佔用資源過高時影響其他作業,並在資源富裕時,實現資源利用的最大化。除此以外,還能滿足外部的期望,保證系統資源使用最大化。通過對作業控制,可以保證作業是平穩的,避免作業執行過程中出現不可控的行爲。

爲了解決上述目標,華爲雲GaussDB數據庫提供了一種對數據庫集羣內資源進行細粒度管控的方案——細粒度資源管控。該方案在不同的管控粒度(如用戶級、會話級與語句級)和不同的管控維度(CPU、內存與IO)都提供了對應的管控能力。用戶可以根據自己業務需求採取合適的管控維度與管控粒度來達成資源管控與資源隔離的目標,滿足不同場景的資源控制的需要。

技術架構

我們先來看下細粒度資源管控的技術架構和運行原理:

幻燈片1.PNG

從上圖中可以看到,GaussDB提供資源池模塊來完成CPU、內存與IO的管控邏輯。用戶可以創建一個資源池並指定其可以使用的CPU、內存與IO的份額,並把資源池與用戶綁定。之後該用戶發起的作業在數據庫內核優化解析、執行引擎以及存儲引擎模塊運行的過程中都會受到實時資源管控,確保其CPU、內存與IO都在對應資源池的範圍內。
 
假設A公司部署了一套GaussDB實例,其同時存在三個不同的應用來訪問該實例,如OLTP業務、報表業務、其他低優先級業務。A公司希望對三個業務做資源的合理管控,在保證資源使用最大化的情況下,系統平穩運行。我們可以使用系統管理員執行如下命令來爲三個業務的用戶設置,其資源份額比例爲50:30:10,剩餘的10%爲系統預留。
 
這裏僅做簡單的使用示例,每一個參數的具體含義會在後面的章節進行詳細說明。
 
create resource pool respool_tp with(control_group="cgroup_tp", max_dynamic_memory="5GB", max_shared_memory="5GB", io_limits=50, io_priority="High");
alter role tp_user RESOURCE POOL 'respool_tp';

create resource pool respool_report with(control_group="cgroup_report", max_dynamic_memory="3GB", max_shared_memory="3GB", io_limits=30, io_priority="Medium");
alter role report_user RESOURCE POOL 'respool_report';

create resource pool respool_other with(control_group="cgroup_other", max_dynamic_memory="1GB", max_shared_memory="1GB", io_limits=10, io_priority="Low");
alter role other_user RESOURCE POOL 'respool_other';
如上操作後,OLTP業務、報表業務與其他低優先級業務分別使用tp_user、report_user與other_user連入GaussDB執行作業時,這三個業務則會受到對應的資源池respool_tp、respool_report與respool_other的管控,在資源發生爭搶的時候保證三個業務分別可以使用GaussDB集羣50%、30%以及10%的資源。

關鍵能力

在瞭解了細粒度資源管控的整體架構和使用方法之後,我們再來看看它具備哪些關鍵能力,這些能力可以爲客戶帶來什麼樣的業務價值。

CPU管控

GaussDB的CPU管控是以資源池粒度來做用戶資源管控的,每一個資源池綁定一個控制組,通過控制組(Control Group,CGroup)來實現CPU的管控。CGroup是Linux內核提供的一種限制、記錄、隔離進程組所使用的物理資源(如CPU、Memory、IO等)的機制。
 
考慮到數據庫系統、用戶、作業不同維度的隔離性和可配置性,GaussDB使用控制組的層級特性構造符合數據庫場景的模型(見下圖),其滿足客戶SLA的關鍵特性,並支持三個維度的層次隔離和控制:數據庫程序與非數據庫程序隔離、數據庫常駐後備線程與執行作業線程隔離以及數據庫多用戶之間的隔離。

幻燈片2.PNG

GaussDB控制組可以設置CPU的百分比以及核數的上限,其中根節點負責管控GaussDB進程可用的CPU份額;Backend控制組負責管控數據庫常駐後臺線程的CPU份額(Vacuum、DefaultBackend);Class控制組負責管控用戶的作業線程的CPU份額(UserClass1,UserClass2,...UserClassN);Class控制組內還可以創建Workload控制組(TopWD,RemainWD...)進行更細粒度的管控。
 
接上面的示例,我們用GaussDB提供的CGroup工具來爲A公司的OLTP業務、報表業務以及其他低優先級業務分別創建控制組,CPU分配比例爲50%、30%與10%。
 
gs_cgroup -c -S cgroup_tp -s 50;
gs_cgroup -c -S cgroup_report -s 30;
gs_cgroup -c -S cgroup_other -s 10;
執行如上命令就代表我們成功創建了3個控制組,之後可以在創建資源池時指定該控制組名稱。綁定資源池的用戶所發起的作業就會收到控制組對應CPU份額的管控。
 
CGroup管控CPU有兩個問題需要注意:
 
一是,如果線程的CPU需要受CGroup管控,那麼需要執行CGroup的系統API來爲線程綁定對應的CGroup,該操作較爲耗時;
二是,CGroup的CPU管控效果,在線程數與CPU成比例的情況下,管控效果最佳。
 
基於這些問題GaussDB提出了線程組的概念,每一個資源池對應一個線程組,線程組裏的線程都綁定了該資源池所對應的CGroup。同時,GaussDB會將每一個線程組的線程數量調整到與對應CGroup的CPU份額一致。具體可見下圖:
幻燈片3.PNG
每一個用戶發起的作業都會被分發到對應的線程組裏的線程來執行,由於線程已經綁定了對應的Cgroup節點,所以操作系統會在線程調度時完成CPU管控。
 
GaussDB提供兩層用戶機制,綁定Class控制組的資源池稱之爲組資源池,對應的用戶爲組用戶,綁定Workload控制組的資源池稱之爲業務資源池,對應的用戶爲業務用戶。組用戶一般對應一個部門,而業務用戶對應這個部門的不同的業務。業務資源池的各個資源維度的資源份額會不會超過所屬組資源池的份額,從而達到兩級資源管控的目標。
 
CPU管控也提供名稱爲session_respool的GUC來限制單個會話的CPU不超過對應資源池的CPU上限。

內存管控

GaussDB提供動態內存與共享緩存的管控,創建資源池時可以指定max_dynamic_memory與max_shared_memory來分別完成動態內存與共享緩存的閾值設置。
 
動態內存管控並沒有更改其原有的內存資源分配機制,僅在分配內存之前增加一個邏輯判斷層,對多分配出的內存進行記賬,通過檢查該記賬值是否達到允許使用的內存上限來完成內存的管控。當動態內存超過上限時,作業申請內存會失敗。作業退出時,該作業已申請的內存會進行釋放來保證其他作業可以正常執行。同理,當作業使用的共享緩存超過資源池的管控上限時,再次申請共享緩存,需要先釋放自己已經佔用的共享緩存,比如BufferPool,作業申請頁面時,會對自己已經佔用的頁面進行淘汰,淘汰之後空餘出來的頁面供自己繼續使用。
 
GaussDB除了用戶粒度的內存管控外,也提供session_max_dynamic_memory與query_max_mem兩個GUC參數來完成會話級與語句級動態內存的管控,當一個會話或者語句所使用的動態內存達到GUC的閾值時,作業申請內存失敗。

IO管控

GaussDB的磁盤讀寫IO都由後臺線程完成,該線程無法區分頁面屬主,只是按照時間順序依次落盤,無法針對不同用戶管控不同的IO使用。基於此,考慮IO管控功能採用邏輯IO統計方式,對用戶或者會話的讀寫IO進行管控限制,在工作線程和共享緩存之間增加了邏輯IO計數,對於行存表來說每6000(可通過io_control_unit GUC進行修改)行算做一次IO,當一秒產生的讀寫IO請求數超過資源池設置的閾值時,則將該IO請求加入到後臺線程的一個等待隊列裏,後臺線程將對等待隊列裏的這些IO請求進行監控,當其等待時間符合條件時,將這些IO請求從等待隊列中喚醒。
 
GaussDB支持兩種模式的IO資源管控,上線數值模式是通過設置固定的觸發IO次數的數值,進行IO資源控制;優先級模式是指在當前磁盤長時間使用率達到95%以上,所有作業都無法達到上線數值模式時,用戶可通過該模式進行IO控制,控制該作業原本觸發IO的優先級比例,優先級包含三擋:High、Medium與Low。
 

4.PNG

接上面的示例,我們爲A公司的OLTP業務、報表業務以及其他低優先級業務分別創建資源池,IO權重分別設置的爲High、Medium與Low。那麼,OLTP業務能使用50%的IO請求向BufferPool中讀取或寫入數據,少量的IO請求會進入等待隊列等待;報表業務能使用20%的IO請求向BufferPool中讀取或寫入數據,較多的IO請求會進入等待隊列等待;其他低優先級業務能使用10%的IO請求向BufferPool中讀取或寫入數據,較多的IO請求會進入等待隊列等待;後臺監控線程會週期性的遍歷IO等待隊列,喚醒等待時間符合要求的IO請求從BufferPool讀取或寫入數據。
 
GaussDB除了支持用戶粒度的IO管控外,也支持通過設置會話級GUC參數io_limits與io_priority,來完成指定會話上允許作業的IO管控。

連接數與併發管控

GaussDB提供基於資源池的連接數管控與併發管控,創建資源池時可以指定max_connections與max_concurrency來分別完成連接數與併發數的設置,可以使用如下SQL,爲前面示例A公司的三個業務對應的資源池完成連接數與併發數管控:
 
alter resource pool respool_tp with(max_connections=-1, max_concurrency = -1);
alter resource pool respool_report with(max_connections=200, max_concurrency = 100);
alter resource pool respool_other with(max_connections=100, max_concurrency = 50);
如上SQL執行成功後,實時生效。A公司OLTP業務的連接數與併發數不受限制,只有集羣有資源它都可以使用到;報表業務的最大連接數爲200,其他低優先級業務的最大連接數爲100,當這兩個業務建立的連接數超過該值時,GaussDB內核會自動攔截,報當前連接數不足,鏈接失敗;報表業務的最大併發數爲100,其他低優先級業務的最大併發數爲50,當這兩個業務同時發起的作業數超過該值時,超出的作業將會進入等待隊列,直到已有的作業完成之後GaussDB纔會將其喚醒繼續執行作業。

存儲空間管控

存儲空間管控,用於限定不同用戶可以使用的空間配額,防止單用戶存儲空間使用過大導致整個數據庫業務受阻。GaussDB通過在創建用戶時指定存儲空間的大小來實現對存儲資源的管控。
 
存儲空間資源分爲三種類型:永久表空間(Perm Space)、臨時表空間(Temp Space)與算子下盤空間(Spill Space)。
 
可以使用如下SQL,爲前面示例A公司的三個業務對應的用戶完成磁盤空間額管控。
 
alter user tp_user PERM SPACE '200G' TEMP SPACE '20G' SPILL SPACE '20G';
alter user report_user PERM SPACE '100G' TEMP SPACE '10G' SPILL SPACE '10G';
alter user other_user PERM SPACE '100G' TEMP SPACE '10G' SPILL SPACE '10G';
 
存儲空間管理支持對組用戶和業務用戶的存儲空間管理。當業務用戶對應的組用戶存在空間限制時,業務用戶的空間也受到該組用戶的空間限制。指定存儲空間的大小後,該用戶在DN上所有的寫操作會增加用戶已用空間,刪除操作減少用戶已用空間,CN會週期性的從DN獲取一次已用空間總和,並對用戶已用空間進行判斷,超過最大值後cancel掉寫作業(insert/create table as/copy),後面寫作業報錯退出。

特性演示

特性演示這裏我們就簡單的爲大家演示一下CPU的管控效果,因爲對業務影響最大的就是CPU。
 
創建兩個資源池分別設置20%與60%的CPU,然後使用兩個綁定了該資源池的用戶開始跑業務。觀測CPU的實際使用情況。

1. 創建控制組:

gs_cgroup -c -S class1 -s 20;
gs_cgroup -c -S class2 -s 60;

2. 創建資源池:

CREATE RESOURCE POOL xuuer_pool with(control_group = "class1");
CREATE RESOURCE POOL xyuser1_pool with(control_group = "class2");

3. 創建用戶綁定資源池:

create role user1 RESOURCE POOL 'xuuer_pool';
create role user2 RESOURCE POOL 'xyuser1_pool';
4. 通過Top觀察系統CPU狀態,同時細粒度資源管控提供gs_wlm_respool_cpu_info函數來觀察各個資源池的CPU實時情況。

幻燈片5.PNG

如上圖,可知初期系統CPU是空閒狀態,資源池的CPU監控視圖也顯示CPU使用爲0。讓user1開始跑業務,觀測可知系統CPU有一定業務佔用,查詢資源池的CPU監控視圖顯示,user1可以使用80%的CPU。此時,讓user2也開始跑業務,觀測可知系統CPU進入繁忙狀態,查詢資源池的CPU資源監控的系統函數可知user1的CPU使用率開始下降,user2的CPU使用率開始上升。

整理兩個用戶的CPU使用率並繪製曲線圖如下圖,可看出user1與user2的CPU使用率最終會平衡到3比1的狀態,符合資源池對應的CGroup控制組裏設置的20%與60%的比例,達到了CPU管控的效果。

幻燈片6.PNG

總結

細粒度資源管控特性目前支持集中式與分佈式。分佈式下的計算資源管控是各個節點獨立管控自己節點的資源,存儲資源管控是以集羣維度來整體管控的。

細粒度資源管控作爲多租戶的資源隔離的底座,實現資源的精準劃分與控制,並解決高負載場景下資源不足而導致集羣不可服務的問題。該特性適用於數據隔離不敏感,但對不同業務有資源隔離需求的場景,如果客戶對資源隔離和數據隔離都有需求的話,可以關注一下我們後面即將分享的多租數據庫特性哦!

 

點擊關注,第一時間瞭解華爲雲新鮮技術~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章