天天看點

實操指南 | Resource Queue如何實作對AnalyticDB PostgreSQL的資源管理?一 背景二 Resource Queue簡介三 Resource Queue使用四 Resource Queue狀态監控五 Resource Queue實作六 總結

一 背景

AnalyticDB PostgreSQL版(簡稱ADB PG)是阿裡雲資料庫團隊基于PostgreSQL核心(簡稱PG)打造的一款雲原生資料倉庫産品。在資料實時互動式分析、HTAP、ETL、BI報表生成等業務場景,ADB PG都有着獨特的技術優勢,在金融、物流、泛網際網路等行業都有廣泛的應用,是傳統數倉上雲、去O去T、替換自建Greenplum的标杆雲上資料倉庫産品。

資料倉庫産品是資料分析系統的重要元件之一,各類線上業務對資料倉庫産品的穩定性、可用性具有很高的要求。缺乏有效的資源管理機制會導緻資料庫産品的穩定性下降,發生例如連接配接數打滿OS限制、記憶體不足、程序卡死等問題,進而影響産品的可用性。

實操指南 | Resource Queue如何實作對AnalyticDB PostgreSQL的資源管理?一 背景二 Resource Queue簡介三 Resource Queue使用四 Resource Queue狀态監控五 Resource Queue實作六 總結

Resource Queue(資源隊列)是ADB PG的一種資源管理方式,能夠對資料庫的CPU、記憶體等資源進行限制,對多租戶資源限制、保障資料庫穩定運作具有一定的作用。顧名思義,Resource Queue以隊列形式對運作在資料庫叢集上的SQL進行資源管理。對于每個使用者,他的所有連接配接隻能歸屬于一個隊列。而對于每個隊列能夠管理多個使用者的連接配接。沒有顯示指定資源隊列的使用者,會歸屬于預設資源隊列管理。通過限制每個隊列的資源總量,我們可以達到限制某類業務或者某個使用者使用的資源總量的目的。

我們以ADB PG某線上交易平台類客戶A為例,介紹Resource Queue的使用。客戶A基于ADB PG建構資料倉庫,日常運作三類業務:以交易資料入庫為代表的實時類業務;用于支撐決策分析的報表類業務;以及用于實時大屏展示的可視化類業務。我們根據三類業務的不同特點,按如下政策配置資源隊列。

實操指南 | Resource Queue如何實作對AnalyticDB PostgreSQL的資源管理?一 背景二 Resource Queue簡介三 Resource Queue使用四 Resource Queue狀态監控五 Resource Queue實作六 總結

客戶A的實時類業務的典型代表是,交易資料經Kafka->Flink->ADB PG鍊路實時寫入ADB PG。這類業務的典型特點是,峰值并發比較大,單個SQL資源消耗小。在進行資源隊列限制前,業務高峰期經常發生突然提高的并發查詢打滿資料庫連接配接,造成高可用探活查詢執行失敗,引發執行個體不可用。對于這類業務我們将其關聯到一個高CPU權重、大并發限制(安全門檻值内)、單個SQL記憶體份額低的隊列。既保證資料的快速入庫,又防止流量洪峰造成系統不穩定。

客戶A的另一類典型業務是報表類、ETL類業務,這類業務會在實時類業務的低峰期進行排程,生成報表以提供決策支援。這類業務涉及的資料量較大,消耗記憶體量和産生的臨時檔案量大。對于這類業務,我們将其關聯到低CPU權重、低并發限制,但是記憶體份額高的隊列,在滿足業務需要的同時,控制記憶體使用上限;

除此之外,客戶還基于ADB PG資料倉庫支援資料的實時可視化展示,這類可視化方案往往具有非常穩定的并發,但是對查詢的延時具有一定的要求。對于這類業務,我們将其資源隊列設定為高CPU權重,低并發限制,以及寬泛的優化器查詢計劃消耗份額,最大程度為其生成良好的查詢計劃,以保證業務穩定。

接下來,本文會具體介紹Resource Queue的使用方式、狀态監控,以及它的實作機制。

二 Resource Queue簡介

Resource Queue支援通過SQL配置,支援進行四種類型的資源限制:并發限制、CPU限制、記憶體限制和查詢計劃限制。使用者可以通過SQL在資料庫内定義多個資源隊列,并設定每個資源隊列的資源限制。在一個資料庫中,每個資源隊列可以關聯一個或多個資料庫使用者,而每個資料庫使用者隻能歸屬于單個資源隊列。

另外,并不是所有送出到資源隊列的SQL都會受到隊列限制的限制,資料庫隻會限制SELECT、SELECT INTO、CREATE TABLE AS SELECT、DECLARE CURSOR、INSERT、UPDATE 和DELETE這些類型SQL的資源利用。另外,在執行EXPLAIN ANALYZE指令期跑的SQL也會被資源隊列排除。

資源隊列支援的資源限制配置如下:

配置名 配置說明
MEMORY_LIMIT 隊列中所有查詢所使用的記憶體總量。
ACTIVE_STATEMENTS 隊列中允許同時運作的查詢數。超出該設定值的查詢需要排隊等待執行。
PRIORITY 隊列的CPU使用優先級,可以設定為以下級别:LOW、MEDIUM、HIGH 和MAX。預設值為MEDIUM,優先級越高的隊列會被配置設定越高的CPU份額。
MAX_COST 查詢計劃消耗限制。

通過SQL語句定義一個新的資源隊列:

CREATE RESOURCE QUEUE etl WITH (ACTIVE_STATEMENTS=3, 
MEMORY_LIMIT='1GB', PRIORITY=LOW, MAX_COST=-1.0);      

ACTIVE_STATEMENTS:

隊列中允許同時運作的查詢數,即隊列中允許并發查詢的最大并發值。資料庫允許超出ACTIVE_STATEMENTS數目、但是少于資料庫最大連接配接數MAX_CONNECTIONS數目的連結連接配接到資料庫,但是這部分SQL連接配接并不會立刻開始運作,而是排隊等待。

MAX_COST:

查詢計劃Cost限制。資料庫優化器會為每個查詢計算Cost,如果該Cost總量超過了資源隊列所設定的的MAX_COST的值,該查詢就會被拒絕。ADB PG的預設配置為0,即不受限制。

Memory Limit:

ADB PG可以通過設定statement_mem來決定每條SQL在每個Segment上使用的記憶體上限。Memory Limit既沒有預設值,也可以不指定。在MEMORY_LIMIT參數沒有被配置時,一個資源隊列中的一條SQL所允許的記憶體大小,由statement_mem參數決定:

  • 如果一個資源隊列沒有設定MEMORY_LIMIT的話,每個資源所配置設定到的記憶體大小就是statement_mem的伺服器配置參數,一個資源隊列的可用記憶體大小是根據statement_mem和ACTIVE_STATEMENTS的計算結果。
  • 當資源隊列有設定MEMORY_LIMIT時,單個SQL所使用的記憶體量會由隊列中的平均配置設定值(MEMORY_LIMIT/ACTIVE_STATEMENTS)和statement_mem中的最大值決定,具體計算方式可以參考後面實作章節。

資源隊列中可以并行執行的查詢數會受到該隊列的可用記憶體限制。舉個例子:對于隊列etl,設定STATEMENTS=3, MEMORY_LIMIT=2.1G;那麼在沒有設定statement_mem的情況下,每個查詢預設使用記憶體700MB。

SQL1進入隊列,使用記憶體700MB,此時隊列剩餘記憶體1.4G;

SQL2進入隊列,設定statement_mem為1.0GB,此時隊列剩餘記憶體為0.4GB;

此時,隊列剩餘記憶體無法滿足SQL3的記憶體使用需求(預設700GB),那麼雖然隊列中并行查詢數沒有達到隊列限制,SQL3依然無法執行,需要排隊等待。

PRIORITY:

資料庫運作的SQL會按照其所在資源隊列的優先權設定來共享可用的CPU資源。當一個來自高優先權隊列的語句進入到活動運作語句分組中時,它可以得到可用CPU中較高的份額,同時也會降低具有較低優先權設定隊列中已經在運作的語句得到的份額。

查詢的相對尺寸或複雜度不影響CPU的配置設定。如果一個簡單的低代價的查詢與一個大型的複雜查詢同時運作,并且它們的優先權設定相同,它們将被配置設定同等份額的可用CPU資源。當一個新的查詢變成活動時,CPU份額将會被重新計算,但是優先權相等的查詢仍将得到等量的CPU。

例如,管理者建立三個資源隊列:streaming、etl、prod,并相應地配置為以下優先權:

  • streaming — 低優先權
  • etl— 高優先權
  • prod — 最大優先權

當資料庫中隻有etl隊列中有查詢1和2同時運作時,它們有相等份額的CPU,因為它們的優先權設定相等:

實操指南 | Resource Queue如何實作對AnalyticDB PostgreSQL的資源管理?一 背景二 Resource Queue簡介三 Resource Queue使用四 Resource Queue狀态監控五 Resource Queue實作六 總結

上圖中顯示的百分數都是近似值。高、低和中優先權隊列的CPU使用并不總是準确地用這些比例計算出來。

實操指南 | Resource Queue如何實作對AnalyticDB PostgreSQL的資源管理?一 背景二 Resource Queue簡介三 Resource Queue使用四 Resource Queue狀态監控五 Resource Queue實作六 總結

當一個streaming隊列中的查詢開始運作時,在etl隊列中兩個查詢依然保持相等的CPU份額,而低優先級的query3則會以較低CPU份額運作。

實操指南 | Resource Queue如何實作對AnalyticDB PostgreSQL的資源管理?一 背景二 Resource Queue簡介三 Resource Queue使用四 Resource Queue狀态監控五 Resource Queue實作六 總結

而當最高優先級隊列prod中有查詢進入隊列之後,其CPU使用會被調整以說明其最大優先權設定。它可能是一個非常簡單的查詢,但直到它完成前,它都将要求最大份額的CPU。而其他查詢的優先級則會被調整為較低的CPU份額。

三 Resource Queue使用

3.1 建立資源隊列

ADB PG允許使用者使用SQL建立資源隊列,并指定各類資源限制。使用CREATE RESOURCE QUEUE指令來建立新的資源隊列。

建立帶有并發限制的隊列

帶有ACTIVE_STATEMENTS設定的資源隊列會限制指派給該隊列的角色所執行的并發查詢數量。

CREATE RESOURCE QUEUE etl WITH (ACTIVE_STATEMENTS=3);      

這意味着對于所有被配置設定到etl資源隊列的角色,在任意給定時刻隻能有三個活動查詢被運作在這個系統上。如果這個隊列已經有三個查詢在運作并且一個角色在該隊列中送出第四個查詢,則第四個查詢隻有等到一個槽被釋放出來後才能運作。

建立帶有記憶體限制的隊列

帶有MEMORY_LIMIT設定的資源隊列控制所有通過該隊列送出的查詢的總記憶體。在與ACTIVE_STATEMENTS聯合使用時,每個查詢被配置設定的預設記憶體量為:MEMORY_LIMIT /ACTIVE_STATEMENTS。

例如,要建立一個活動查詢限制為10且總記憶體限制為2000MB的資源隊列(每個查詢将在執行時被配置設定200MB的Segment主機記憶體):

CREATE RESOURCE QUEUE etl WITH (ACTIVE_STATEMENTS=10, 
MEMORY_LIMIT='2000MB');      

另外gp_vmem_protect_limit參數會限制一個Segment上配置設定的記憶體總大小。該參數的優先級更高,如果這個參數超标,查詢可能會被取消。

設定優先級

為了控制一個資源隊列對可用CPU資源的消耗,使用者可以指派一個合适的優先級。

ALTER RESOURCE QUEUE etl WITH (PRIORITY=LOW);
ALTER RESOURCE QUEUE etl WITH (PRIORITY=MAX);      

3.2 指派角色(使用者)到資源隊列

一旦建立了一個資源隊列,使用者必須把角色(使用者)指派到它們合适的資源隊列。如果沒有顯式地把角色指派給資源隊列,它們将進入預設資源隊列pg_default。

使用ALTER ROLE或者CREATE ROLE指令來指派角色到資源隊列。例如:

ALTER ROLE name RESOURCE QUEUE queue_name;
CREATE ROLE name WITH LOGIN RESOURCE QUEUE queue_name;      

從資源隊列移除角色

所有使用者都必須被指派到資源隊列。如果沒有被顯式指派到一個特定隊列,使用者将會進入到預設的資源隊列pg_default。如果使用者想要從一個資源隊列移除一個角色并且把它們放在預設隊列中,可以将該角色的隊列指派改成none。例如:

ALTER ROLE role_name RESOURCE QUEUE none;      

3.3 修改資源隊列

在資源隊列被建立後,使用者可以使用ALTER RESOURCE QUEUE指令更改隊列限制,或使用DROP RESOURCE QUEUE指令移除一個資源隊列。

修改資源隊列配置

ALTER RESOURCE QUEUE指令更改資源隊列的限制。要更改一個資源隊列的限制,可以為該隊列指定想要的新值。例如:

ALTER RESOURCE QUEUE etl WITH (ACTIVE_STATEMENTS=5);
ALTER RESOURCE QUEUE etl WITH (PRIORITY=MAX);      

删除資源隊列

DROP RESOURCE QUEUE指令可以删除資源隊列。要删除一個資源隊列,該隊列不能有指派給它的角色,也不能有任何語句在其中等待。

DROP RESOURCE QUEUE etl;      

四 Resource Queue狀态監控

4.1 檢視隊列中的語句和資源隊列狀态

gp_toolkit.gp_resqueue_status視圖允許使用者檢視一個負載管理資源隊列的狀态和活動。對于一個特定資源隊列,它展示有多少查詢在等待運作以及系統中目前有多少查詢是活動的。要檢視系統中建立的資源隊列、它們的限制屬性和目前狀态:

SELECT * FROM gp_toolkit.gp_resqueue_status;      
實操指南 | Resource Queue如何實作對AnalyticDB PostgreSQL的資源管理?一 背景二 Resource Queue簡介三 Resource Queue使用四 Resource Queue狀态監控五 Resource Queue實作六 總結

4.2 檢視資源隊列統計資訊

如果想要持續跟蹤資源隊列的統計資訊和性能,使用者可以使用pg_stat_resqueues系統視圖來檢視在資源隊列使用上收集的統計資訊。

SELECT * FROM pg_stat_resqueues;      

4.3 檢視指派到資源隊列的角色

要檢視指派給資源隊列的角色,執行下列在pg_roles和gp_toolkit.gp_resqueue_status系統目錄表上的查詢:

SELECT rolname, rsqname FROM pg_roles, gp_toolkit.gp_resqueue_status 
WHERE pg_roles.rolresqueue=gp_toolkit.gp_resqueue_status.queueid;      

4.4 檢視資源隊列的等待查詢

使用者可以看到所有資源隊列的所有目前活躍的以及在等待的查詢:

SELECT * FROM gp_toolkit.gp_locks_on_resqueue WHERE 
lorwaiting='true';      

如果這個查詢不傳回結果,那就意味着目前沒有語句在資源隊列中等待。

4.5 檢視活動語句的優先權

檢視目前正在被執行的語句并且提供優先權、會話ID和其他資訊:

SELECT * FROM gp_toolkit.gp_resq_priority_statement;      

4.6 重置活動語句的優先權

使用者可以使用函數gp_adjust_priority(session_id,statement_count,priority)調整目前正在被執行的語句的優先權。使用這個函數,使用者可以提升或者降低任意查詢的優先權。例如:

SELECT gp_adjust_priority(12, 10000, 'LOW');      

在這個函數的參數中,session_id代表會話id, statement_count代表要調整的SQL在session中的序号,priority是待調整的優先級。可以通過gp_resq_priority_statement視圖查詢現有語句的上述資訊。

select * from gp_toolkit.gp_resq_priority_statement;      

五 Resource Queue實作

ADB PG資料庫是MPP架構,整體分為一個或多個Master,以及多個segment,資料在多個segment之間可以随機、哈希、複制分布。在ADB PG中,Resource Queue的資源限制級别是語句級别,即在整條SQL執行的任何時刻,不管是否處于事務中,均會受到資源隊列的限制。

實操指南 | Resource Queue如何實作對AnalyticDB PostgreSQL的資源管理?一 背景二 Resource Queue簡介三 Resource Queue使用四 Resource Queue狀态監控五 Resource Queue實作六 總結

如上文所述,Resource Group支援對并發、CPU和記憶體等進行限制,本節會詳細介紹對這些資源進行限制的實作細節。

5.1 并發限制

ADBPG資料庫是多程序模型,分布式資料庫的每個節點會啟動多個子程序,各個子程序通過共享記憶體、共享信号量、共享消息隊列的方式實作程序間通信。

Resource Queue基于分布式鎖實作。在ADBPG中所有的SQL連接配接首先會到達Master節點,在經過解析、優化,到達執行器層面時,會首先嘗試擷取ResQueueLock類型的排他鎖。

在單個ADB PG節點中,同一時間隻能有一個程序擷取到ResQueueLock類型的排他鎖,而每個程序隻會包含單個線程。

實操指南 | Resource Queue如何實作對AnalyticDB PostgreSQL的資源管理?一 背景二 Resource Queue簡介三 Resource Queue使用四 Resource Queue狀态監控五 Resource Queue實作六 總結

在獲得ResQueueLock類型的排他鎖之後,執行SQL的背景程序會讀取及更新共享記憶體中的值,特别是隊列中并發執行語句的計數值。若資源充足,則會在更新完共享記憶體中對應資源隊列中的資源使用量之後,釋放ResQueueLock,開始SQL的實際執行;

若資源不足,比如目前隊列中正在運作的SQL數量已經達到了所設定的并發上限值,對應的背景程序則會sleep排隊等待其他query執行完畢後釋放資源。

5.2 記憶體限制

對于記憶體的限制的實作方式與對并發限制的實作方式大體是一緻的,隻是對于判斷資源隊列中是否有資源來運作送出的SQL的方式有一些差別。

實操指南 | Resource Queue如何實作對AnalyticDB PostgreSQL的資源管理?一 背景二 Resource Queue簡介三 Resource Queue使用四 Resource Queue狀态監控五 Resource Queue實作六 總結

對于某個Resource Queue中的SQL,能夠使用的記憶體上限計算如下:

1)如果沒有設定resource queue的memory_limit值,那麼直接取資料庫的statement_mem值;

2)如果設定了resource queue的memory limit值,則根據所設定的resource queue的memory_limit值,計算資源組能夠使用的記憶體總量;用總量除以resource queue設定的并發數,得到單條SQL所能利用的上限值。再将這個上限值與statement_mem取一個最大值,作為SQL最終使用的記憶體上限值。

5.3 CPU限制

Resource Queue的CPU限制是一個很有意思的實作。ADB PG專門為Resource Queue CPU限制的功能拉起了一個專門的程序:sweeper程序來監控各個背景程序的CPU使用,以及調節各個背景程序的CPU份額。

這個程序是一個與資料庫高度獨立的程序,它沒有加載一些緩存、資源類的東西,也無法開啟事務或者查系統表,它的活動就是不停的讀寫共享記憶體,計算各個程序的CPU使用,更改CPU配置設定份額。各個實際執行SQL的背景程序(backend)會根據所計算的CPU份額去休眠一定的時間,進而調節各個SQL實際的CPU使用率。

實操指南 | Resource Queue如何實作對AnalyticDB PostgreSQL的資源管理?一 背景二 Resource Queue簡介三 Resource Queue使用四 Resource Queue狀态監控五 Resource Queue實作六 總結

這個程序的主體流程如上,他的流程非常簡單,就是不斷地sweep和sleep。

各個實際執行SQL的backend程序在啟動時,會在共享記憶體中注冊一些狀态,并在執行過程中執行系統調用getrusage等,更新CPU使用狀态;sweeper程序會根據這些共享記憶體狀态,以及所設定的資源隊列CPU利用值,在共享記憶體中更新對應backend程序的CPU份額(targetCPU)。而在backend運作過程中,則會調用BackoffBackend,根據CPU份額來進行一段時間的休眠,進而調節整體的CPU使用率。

在運作過程中,分布式資料庫的每個計算節點都會有一個sweeper程序來調節每個節點的CPU調用,使資源隊列的CPU配置全局有效。

六 總結

資源管理對于資料庫叢集的多租戶管理、資源細粒度配置設定具有很重要的價值。Resource Queue能夠對分布式資料庫進行整體的資源管理和控制,在多租戶隔離、保障資料庫整體平穩運作具有一定的價值。

除了Resource Queue的資源管理方式外,ADB PG還支援 Resource Group 的資源管理方式,能夠進行更精細的資源控制。Resource Group現已在專有雲環境提供使用,後續會逐漸在公有雲提供能力。後續我們會介紹Resource Group的基本使用和最佳實踐。