
什么是 Pgpool-II?
Pgpool II 管理一個 PostgreSQL 服務器池,以實現單個 PostgreSQL 安裝無法實現的一些功能。這些功能包括:
高可用
Pgpool-II通過使用多個PostgreSQL服務器提供高可用性 (HA) 功能,以便它自動從服務器池中刪除損壞的服務器以繼續執行數據庫任務。這稱為自動故障轉移(automatic failover)。Pgpool-II還為Pgpool-II本身提供了一個HA功能,稱為Watchdog。此外,Pgpool-II采用復雜的仲裁算法來避免誤報錯誤和腦裂問題,使整個HA系統高度可靠。
負載均衡
Pgpool-II將讀取查詢分布在多個PostgreSQL服務器上以獲得更高的性能。此功能稱為負載平衡。 寫查詢被發送到主服務器(在流復制模式下)或所有服務器(在原生復制模式和快照隔離模式下)。在任何情況下,Pgpool-II都會自動區分讀查詢和寫查詢。
除了這些基本功能之外,Pgpool-II 還提供了一些有用的功能,例如:
連接池
Pgpool-II維護與PostgreSQL服務器的已建立連接,並在具有相同屬性(即用戶名、數據庫、協議版本和其他連接參數,如果有的話)的新連接進入時重用它們。它減少了連接開銷,並改進了 系統的整體吞吐量。
在線恢復
Pgpool-II可以通過執行一條命令進行數據庫節點的在線恢復。 當在線恢復與自動故障轉移一起使用時,通過故障轉移分離的節點可以自動附加為備用節點。 也可以同步和附加新的PostgreSQL服務器。
限制超出的連接
PostgreSQL的最大並發連接數是有限制的,當達到這個數量時,新的連接會被拒絕。 但是,提高此最大連接數會增加資源消耗並對整體系統性能產生負面影響。Pgpool-II對最大連接數也有限制,但是額外的連接會排隊而不是立即返回錯誤。 但是,您可以配置為在超出連接限制時返回錯誤(4.1 或更高版本)。
Watchdog
Watchdog可以協調多個Pgpool-II,創建一個健壯的集群系統,避免單點故障或腦裂。 為避免腦裂,您至少需要3個Pgpool-II節點。Watchdog可以針對其他pgpool-II節點執行生命檢查,以檢測Pgpool-II的故障。如果活動Pgpool-II宕機,備用Pgpool-II可以升級為活動,並接管Virtual IP。
內存中查詢緩存
- 在內存中查詢緩存允許保存一對
SELECT語句及其結果。如果有相同的SELECT進入,Pgpool-II從緩存中返回值。由於不涉及SQL解析和對PostgreSQL的訪問,因此使用內存緩存非常快。 另一方面,在某些情況下它可能比正常路徑慢,因為它增加了存儲緩存數據的一些開銷。
Pgpool-II 使用 PostgreSQL 的后端和前端協議,並在后端和前端之間中繼消息。 因此,數據庫應用程序(前端)認為 Pgpool-II 是實際的 PostgreSQL 服務器,而服務器(后端)將 Pgpool-II 視為其客戶端之一。因為 Pgpool-II 對服務器和客戶端都是透明的,所以現有的數據庫應用程序可以與 Pgpool-II 一起使用,幾乎不需要更改其源代碼。
Pgpool-II 適用於 Linux、FreeBSD 和大多數類 UNIX 架構。不支持 Windows。支持的 PostgreSQL 服務器版本為 7.4 或更高版本(某些功能可能不適用於舊版本的 PostgreSQL)。您還必須確保所有 PostgreSQL 服務器都使用相同的主要版本。除此之外,我們不建議將不同的 PostgreSQL 安裝與不同的構建選項混合使用:包括是否支持 SSL、是否使用 --disable-integer-datetimes、不同的塊大小。這些可能會影響 Pgpool-II 的部分功能。PostgreSQL 次要版本的差異通常不是問題。但是,我們不會測試所有出現的次要版本,我們建議使用完全相同的 PostgreSQL 次要版本。
Pgpool-II 簡史
Pgpool-II 的生命始於 Tatsuo Ishii 的個人項目。在項目中它只是一個簡單的連接池軟件。所以 Pgpool 這個名字來源於這個事實。第一個版本於 2003 年公開。
2004 年,Pgpool 1.0 發布,帶有原生復制功能(基於 SQL 語句的復制)。同年 2.0 發布了負載均衡,並支持第 3 版前端/后端協議。2005 年,添加了自動故障轉移和主從模式支持。
2006 年,Pgpool 更名為 Pgpool-II。第一個版本 1.0 取消了 Pgpool 中的許多限制,例如 Pgpool 中 PostgreSQL 服務器的數量最多為 2 個。 還添加了許多新功能,例如並行查詢模式和 PCP 命令(PCP 代表 "Pgpool Control Protocol")。Pgpool 和 Pgpool-II 之間最重要的變化可能是項目從個人項目更改為 Pgpool Development Group 擁有的團體項目。
約定
在命令概要中使用以下約定:括號([ 和 ])表示可選部分。(在 Tcl 命令的概要中,使用問號 (?) 代替,這在 Tcl 中很常見。)大括號({ 和 })和豎線(|)表示您必須選擇一種替代方法。點 (...) 表示前面的元素可以重復。
在提高清晰度的地方,SQL 命令前面有提示符 =>,shell 命令前面有提示符 $。 但是,通常不會顯示提示。
administrator 通常是負責安裝和運行服務器的人。用戶可以是正在使用或想要使用 Pgpool-II 系統的任何部分的任何人。這些術語不應被解釋得太狹隘;本文檔沒有關於系統管理程序的固定假設。
更多的信息
網站
Pgpool-II網站是提供有關Pgpool-II官方信息的中心位置:下載、文檔、常見問題解答、郵件列表存檔等。
郵件列表
- 郵件列表是回答您的問題、與其他用戶分享經驗以及聯系開發人員的好地方。有關詳細信息,請參閱
Pgpool-II網站。
你自己!
pgpool-II是一個開源項目。因此,它依賴於用戶社區的持續支持。當您開始使用Pgpool-II時,您將依賴其他人的幫助,無論是通過文檔還是通過郵件列表。考慮回饋您的知識。閱讀郵件列表並回答問題。 如果您學到了文檔中沒有的內容,請將其寫下來並貢獻出來。如果您向代碼添加功能,請貢獻它們。
限制
本節介紹 Pgpool-II 的當前限制。
PostgreSQL 的功能
- 如果您使用
pg_terminate_backend()停止后端,這將觸發故障轉移。發生這種情況的原因是PostgreSQL為終止的后端發送與完全關閉postmaster完全相同的消息。3.6版之前沒有解決方法。從版本3.6開始,此限制已得到緩解。如果函數的參數(即進程 ID)是常量,則可以安全地使用該函數。 在擴展協議模式下,您無法使用該功能。
負載均衡
多語句查詢(單行多個 SQL 命令)總是發送到主節點(在流復制模式下)或主節點(在其他模式下)。通常 Pgpool-II 將查詢分派到適當的節點,但不適用於多語句查詢。
身份驗證/訪問控制
-
在
replication模式或native replication模式下,支持trust和pam方法。自Pgpool-II 3.0起也支持md5。 使用身份驗證文件pool_passwd支持md5。自Pgpool-II 4.0起,還支持scram-sha-256、證書和明文密碼。pool_passwd是認證文件的默認名稱。以下是啟用md5身份驗證的步驟:- 以數據庫的操作系統用戶身份登錄並輸入:
pg_md5 --md5auth --username=your_username your_passwd用戶名和
md5加密密碼注冊到pool_passwd中。 如果pool_passwd還不存在,pg_md5命令會自動為你創建它。pool_passwd的格式是username:encrypted_passwd。- 您還需要將適當的
md5條目添加到pool_hba.conf。 - 請注意,用戶名和密碼必須與在
PostgreSQL中注冊的相同。 - 更改
md5密碼后(當然在pool_passwd和PostgreSQL中),您需要執行pgpool reload。
大對象
- 在流復制模式下,
Pgpool-II支持大對象。 - 在原生復制模式下,如果后端是
PostgreSQL 8.1或更高版本,Pgpool-II支持大對象。為此,您需要在pgpool.conf中啟用lobj_lock_table指令。但是,不支持使用后端函數lo_import進行大對象復制。 - 在其他模式下,包括 Slony 模式,不支持大對象。
臨時表
- 創建/插入/更新/刪除臨時表始終在原生復制模式下的主節點上執行。 這些表上的
SELECT也在primary表上執行。但是,如果臨時表名在SELECT中用作文字,則無法檢測到它,並且SELECT將進行負載均衡。 這將觸發"not found the table"錯誤或將找到另一個具有相同名稱的表。 為避免此問題,請使用SQL注釋。 - 請注意,用於訪問系統目錄的查詢中使用的此類文字表名稱確實會導致上述問題。
psql的\d命令產生這樣的查詢:
SELECT 't1'::regclass::oid;
在這種情況下,Pgpool-II 總是將查詢發送到主節點並且不會導致問題。
如果您使用的是 PostgreSQL 8.3 或更高版本,則通過在 reset_query_list 中指定 DISCARD ALL 將在會話結束時刪除由 CREATE TEMP TABLE 創建的表。
對於 8.2.x 或更早版本,由 CREATE TEMP TABLE 創建的表在退出會話后不會被刪除。這是因為連接池,從 PostgreSQL 的后端角度來看,它使會話保持活動狀態。為避免這種情況,您必須通過發出 DROP TABLE 顯式刪除臨時表,或在事務塊內使用 CREATE TEMP TABLE ... ON COMMIT DROP。
Native Replication 模式下的函數等
無法保證使用上下文相關機制(例如 random number, transaction ID, OID, SERIAL, sequence)提供的任何數據將在多個后端正確復制。 對於 SERIAL,啟用 insert_lock 將有助於復制數據。insert_lock 還有助於 SELECT setval() 和 SELECT nextval()。
使用 CURRENT_TIMESTAMP、CURRENT_DATE、now() 的 INSERT/UPDATE 將被正確復制。使用 CURRENT_TIMESTAMP、CURRENT_DATE、now() 作為默認值的表的 INSERT/UPDATE 也將被正確復制。 這是通過在查詢執行時用從 primary 獲取的常量替換這些函數來完成的。 但是有一些限制:
在 Pgpool-II 3.0 或之前的版本中,在某些情況下,表默認值中時態數據的計算並不准確。 例如下面的表定義:
CREATE TABLE rel1(
d1 date DEFAULT CURRENT_DATE + 1
)
被視為:
CREATE TABLE rel1(
d1 date DEFAULT CURRENT_DATE
)
Pgpool-II 3.1 或更高版本可以正確處理這些情況。 因此,"d1" 列將明天作為默認值。但是,如果使用擴展協議(例如,在 JDBC、PHP PDO 中使用)或 PREPARE,則此增強不適用。
請注意,如果列類型不是時間類型,則不執行重寫。這樣的例子:
foo bigint default (date_part('epoch'::text,('now'::text)::timestamp(3) with time zone) * (1000)::double precision)
假設我們有下表:
CREATE TABLE rel1(
c1 int,
c2 timestamp default now()
)
我們可以復制
INSERT INTO rel1(c1) VALUES(1)
因為這變成
INSERT INTO rel1(c1, c2) VALUES(1, '2009-01-01 23:59:59.123456+09')
然而,
INSERT INTO rel1(c1) SELECT 1
無法轉換,因此無法在當前實現中正確復制。 仍然會插入值,根本沒有任何轉換。
SQL 類型命令
SQL類型的命令不能用於擴展查詢模式。
多字節字符
Pgpool-II不會在客戶端和PostgreSQL之間對多字節字符進行編碼轉換。客戶端和后端的編碼必須相同。
多語句查詢
Pgpool-II不能處理多語句查詢。但是,當Pgpool-II通過psql連接時,是沒有問題的。psql解析多條語句,逐個發送一條語句。
libpq
libpq在構建Pgpool-II時被鏈接。libpq版本必須是3.0或更高版本。使用libpq 2.0版構建Pgpool-II將失敗。
參數狀態
- 當客戶端連接到
PostgreSQL時,PostgreSQL將一些parameter/value對發送回客戶端。該協議稱為ParameterStatus。參數/值對可以通過libpq的PQParameterStatus等API提取。Pgpool-II從多個PostgreSQL服務器收集ParameterStatus值,並且這些值可能在服務器之間有所不同。一個典型的例子是in_hot_standby,它是在PostgreSQL 14中引入的。該變量的值在主服務器為off和備用服務器上為on。問題是,Pgpool-II必須只返回其中一個客戶端。 在這種情況下,它選擇主服務器報告的值。所以PQParameterStatus將返回off。 另一方面,當客戶端發出show in_hot_standby時,返回值可以on或off,具體取決於會話的負載均衡節點。 - 請注意,如果服務器之間的值不同,
Pgpool-II將發出除in_hot_standby之外的日志消息。這是為了防止日志文件被淹沒,因為in_hot_standby總是不同的。
set_config
PostgreSQL具有set_config功能,它允許在當前會話中更改參數值,如SET命令(實際上set_config比SET具有更多功能。有關詳細信息,請參閱PostgreSQL手冊)。當Pgpool-II在集群模式設置為streaming_replication的情況下運行時,它只將函數發送到主服務器。由於該函數不發送到備用服務器,因此每個服務器的參數值不同。為避免該問題,您可以使用SET命令代替set_config。 由於SET命令已發送到用於此會話的所有服務器,因此不會發生此問題。但是,如果您使用超過2個PostgreSQL服務器,則需要禁用statement_level_load_balance並使用SET命令。這是因為,如果啟用了statement_level_load_balance,查詢可能會發送到除主服務器和分配給負載均衡節點的服務器之外的第三台服務器。- 如果需要使用
set_config,請關閉session的負載均衡(不僅對於set_config,還應在整個會話中禁用負載均衡)。你可以通過犧牲性能來避免這個問題。
