使用 pgactive 來支援主動-主動式複寫 - Amazon Relational Database Service

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 pgactive 來支援主動-主動式複寫

pgactive 延伸模組使用主動主動複寫,以支援和協調 PostgreSQL 資料庫的多個 RDS上的寫入操作。Amazon RDS for PostgreSQL 支援下列版本的pgactive擴充功能:

  • RDS 適用於 PostgreSQL 16.1 和更新版本 16

  • RDS 適用於 PostgreSQL 15.4-R2 和更新版本 15

  • RDS 適用於 PostgreSQL 14.10 和更新版本 14

  • RDS 適用於 PostgreSQL 13.13 和更新版本 13

  • RDS 適用於 PostgreSQL 12.17 和更新版本 12

  • RDS 適用於 PostgreSQL 11.22

注意

當複寫組態中的多個資料庫上有寫入操作時,可能會發生衝突。如需詳細資訊,請參閱 處理主動-主動式複寫中的衝突

初始化 pgactive 延伸模組功能

若要初始化 RDS for PostgreSQL 資料庫執行個體上的pgactive延伸功能,請將 rds.enable_pgactive 參數的值設定為 ,1然後在資料庫中建立延伸。這樣做就會自動開啟參數 rds.logical_replicationtrack_commit_timestamp,並將 wal_level 的值設定為 logical

您必須具有做為 rds_superuser 角色的許可,才能執行這些任務。

您可以使用 AWS Management Console 或 AWS CLI 來建立 PostgreSQL 資料庫執行個體RDS所需的 。下列步驟假設RDS您的 for PostgreSQL 資料庫執行個體與自訂資料庫參數群組相關聯。如需建立自訂資料庫參數群組的相關資訊,請參閱 的參數組 RDS

若要初始化 pgactive 延伸模組功能
  1. 登入 AWS Management Console 並在 開啟 Amazon RDS主控台https://console.aws.amazon.com/rds/

  2. 在導覽窗格中,選擇適用於 PostgreSQL 資料庫執行個體RDS的 。

  3. 開啟RDS適用於 PostgreSQL 資料庫執行個體的組態索引標籤。在執行個體詳細資訊中,找到資料庫執行個體參數群組連結。

  4. 選擇連結以開啟與 RDS for PostgreSQL 資料庫執行個體相關聯的自訂參數。

  5. 找到 rds.enable_pgactive 參數,並將其設定為 1 以初始化 pgactive 功能。

  6. 選擇 Save changes (儲存變更)。

  7. 在 Amazon RDS主控台的導覽窗格中,選擇資料庫

  8. 選取您的 RDS for PostgreSQL 資料庫執行個體,然後從動作功能表中選擇重新啟動

  9. 確認資料庫執行個體重新開機,以讓您的變更生效。

  10. 當資料庫執行個體可用時,您可以使用 psql 或任何其他 PostgreSQL 用戶端連線至 RDS for PostgreSQL 資料庫執行個體。

    下列範例假設您的 RDS for PostgreSQL 資料庫執行個體具有名為 的預設資料庫 postgres.

    psql --host=mydb.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=master username --password --dbname=postgres
  11. 若要驗證 pgactive 是否已初始化,請執行下列命令。

    postgres=>SELECT setting ~ 'pgactive' FROM pg_catalog.pg_settings WHERE name = 'shared_preload_libraries';

    如果 pgactiveshared_preload_libraries 中,則上述命令將傳回以下內容:

    ?column? ---------- t
  12. 建立延伸模組,如下所示。

    postgres=> CREATE EXTENSION pgactive;
若要初始化 pgactive 延伸模組功能

若要pgactive使用 初始化 AWS CLI,請呼叫 modify-db-parameter-group操作來修改自訂參數群組中的特定參數,如下列程序所示。

  1. 使用下列 AWS CLI 命令將 rds.enable_pgactive 設定為 1,以初始化 RDS for PostgreSQL 資料庫執行個體pgactive的功能。

    postgres=>aws rds modify-db-parameter-group \ --db-parameter-group-name custom-param-group-name \ --parameters "ParameterName=rds.enable_pgactive,ParameterValue=1,ApplyMethod=pending-reboot" \ --region aws-region
  2. 使用以下 AWS CLI 命令重新啟動 RDS for PostgreSQL 資料庫執行個體,以便初始化pgactive程式庫。

    aws rds reboot-db-instance \ --db-instance-identifier your-instance \ --region aws-region
  3. 當執行個體可用時,請使用 psql連線到 Aurora Postgre 資料庫叢集的寫入器執行個體。RDS for PostgreSQL 資料庫執行個體。

    psql --host=mydb.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=master user --password --dbname=postgres
  4. 建立延伸模組,如下所示。

    postgres=> CREATE EXTENSION pgactive;

設定適用於 的主動主動複寫RDS SQL

下列程序說明如何在相同區域中啟動執行 之間的主動-主動複寫。RDS SQL SQL若要執行多區域高可用性範例,您需要在兩個不同區域中部署 Amazon RDS for PostgreSQL 執行個體,並設定VPC對等。如需詳細資訊,請參閱VPC對等

注意

在多個地區之間傳送流量可能會產生額外費用。

這些步驟假設RDS適用於 PostgreSQL 資料庫執行個體的 已使用 pgactive 擴充功能設定。如需詳細資訊,請參閱初始化 pgactive 延伸模組功能

使用 pgactive 延伸設定第一個 RDS PostgreSQL 資料庫執行個體

下列範例說明如何建立pgactive群組,以及在 RDS for PostgreSQL 資料庫執行個體上建立pgactive擴充功能所需的其他步驟。

  1. 使用 psql或其他用戶端工具連線至您的第一個 RDS for PostgreSQL 資料庫執行個體。

    psql --host=firstinstance.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=master username --password --dbname=postgres
  2. 使用下列命令在 RDS for PostgreSQL 執行個體上建立資料庫:

    postgres=> CREATE DATABASE app;
  3. 使用下列命令將連線切換至新資料庫:

    \c app
  4. 若要檢查 shared_preload_libraries 參數是否包含 pgactive,請執行下列命令:

    app=>SELECT setting ~ 'pgactive' FROM pg_catalog.pg_settings WHERE name = 'shared_preload_libraries';
    ?column? ---------- t
  5. 使用下列SQL陳述式建立和填入範例資料表:

    1. 使用以下SQL陳述式建立範例資料表。

      app=> CREATE SCHEMA inventory; CREATE TABLE inventory.products ( id int PRIMARY KEY, product_name text NOT NULL, created_at timestamptz NOT NULL DEFAULT CURRENT_TIMESTAMP);
    2. 使用下列SQL陳述式將資料表填入一些範例資料。

      app=> INSERT INTO inventory.products (id, product_name) VALUES (1, 'soap'), (2, 'shampoo'), (3, 'conditioner');
    3. 使用下列SQL陳述式來驗證資料表中是否存在資料。

      app=>SELECT count(*) FROM inventory.products; count ------- 3
  6. 在現有資料庫上建立 pgactive 延伸模組。

    app=> CREATE EXTENSION pgactive;
  7. 使用下列命令建立並初始化 pgactive 群組:

    app=> SELECT pgactive.pgactive_create_group( node_name := 'node1-app', node_dsn := 'dbname=app host=firstinstance.111122223333.aws-region.rds.amazonaws.com user=master username password=PASSWORD');

    node1-app 是您指派的名稱,用於單獨識別 pgactive 群組中的節點。

    注意

    若要在可公開存取的資料庫執行個體上成功執行此步驟,您必須將 rds.custom_dns_resolution 參數設定為 1 以將它開啟。

  8. 若要檢查資料庫執行個體是否已就緒,請使用下列命令:

    app=> SELECT pgactive.pgactive_wait_for_node_ready();

    如果命令成功,您會看到以下輸出內容:

    pgactive_wait_for_node_ready ------------------------------ (1 row)
RDS 為 PostgreSQL 執行個體設定第二個 並將其加入pgactive群組

下列範例說明如何將 RDS for PostgreSQL 資料庫執行個體加入 pgactive群組,以及在資料庫執行個體上建立pgactive擴充功能所需的其他步驟。

這些步驟假設另一個 RDS的 PostgreSQL 資料庫執行個體已使用 pgactive 延伸設定。如需詳細資訊,請參閱初始化 pgactive 延伸模組功能

  1. 使用 psql 來連線至您想要從發佈者接收更新的執行個體。

    psql --host=secondinstance.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=master username --password --dbname=postgres
  2. 使用下列命令在第二個 上建立 PostgreSQL 資料庫執行個體RDS的資料庫:

    postgres=> CREATE DATABASE app;
  3. 使用下列命令將連線切換至新資料庫:

    \c app
  4. 在現有資料庫上建立 pgactive 延伸模組。

    app=> CREATE EXTENSION pgactive;
  5. 將適用於 RDS第二個資料庫執行個體SQL加入pgactive群組,如下所示。

    app=> SELECT pgactive.pgactive_join_group( node_name := 'node2-app', node_dsn := 'dbname=app host=secondinstance.111122223333.aws-region.rds.amazonaws.com user=master username password=PASSWORD', join_using_dsn := 'dbname=app host=firstinstance.111122223333.aws-region.rds.amazonaws.com user=postgres password=PASSWORD');

    node2-app 是您指派的名稱,用於單獨識別 pgactive 群組中的節點。

  6. 若要檢查資料庫執行個體是否已就緒,請使用下列命令:

    app=> SELECT pgactive.pgactive_wait_for_node_ready();

    如果命令成功,您會看到以下輸出內容:

    pgactive_wait_for_node_ready ------------------------------ (1 row)

    如果 RDS PostgreSQL 資料庫的第一個資料庫相對較大,您可以看到 pgactive.pgactive_wait_for_node_ready() 發出還原操作的進度報告。輸出結果類似如下:

    NOTICE: restoring database 'app', 6% of 7483 MB complete NOTICE: restoring database 'app', 42% of 7483 MB complete NOTICE: restoring database 'app', 77% of 7483 MB complete NOTICE: restoring database 'app', 98% of 7483 MB complete NOTICE: successfully restored database 'app' from node node1-app in 00:04:12.274956 pgactive_wait_for_node_ready ------------------------------ (1 row)

    從這裡開始,pgactive 會在兩個資料庫執行個體之間同步資料。

  7. 您可以使用下列命令來驗證第二個資料庫執行個體的資料庫是否有資料:

    app=> SELECT count(*) FROM inventory.products;

    如果資料已成功同步,您會看到下列輸出內容:

    count ------- 3
  8. 執行下列命令以插入新值:

    app=> INSERT INTO inventory.products (id, product_name) VALUES ('lotion');
  9. 連線至第一個資料庫執行個體的資料庫,然後執行下列查詢:

    app=> SELECT count(*) FROM inventory.products;

    如果主動-主動式複寫已初始化,則會輸出類似下列內容:

    count ------- 4
pgactive 群組卸離並移除資料庫執行個體

您可以利用下列步驟將資料庫執行個體從 pgactive 群組卸離並移除:

  1. 您可以使用下列命令將第二個資料庫執行個體從第一個資料庫執行個體卸離:

    app=> SELECT * FROM pgactive.pgactive_detach_nodes(ARRAY[‘node2-app']);
  2. 使用下列命令從第二個資料庫執行個體移除 pgactive 延伸模組:

    app=> SELECT * FROM pgactive.pgactive_remove();

    若要強制移除延伸模組:

    app=> SELECT * FROM pgactive.pgactive_remove(true);
  3. 使用以下命令刪除延伸模組:

    app=> DROP EXTENSION pgactive;

處理主動-主動式複寫中的衝突

pgactive 延伸模組是在每個資料庫上運作,而不是每個叢集。使用 pgactive 的每個資料庫執行個體都是獨立的執行個體,可接受任何來源的資料變更。將變更傳送至資料庫執行個體時,PostgreSQL 會在本機遞交變更,然後使用 將變更非同步pgactive複寫至其他資料庫執行個體。當兩個 PostgreSQL 資料庫執行個體幾乎同時更新相同的記錄時,可能會發生衝突。

pgactive 延伸模組提供了衝突偵測和自動解決的機制。它會追蹤交易在兩個資料庫執行個體上得到認可的時間戳記,並自動套用具有最新時間戳記的變更。pgactive 延伸模組也會記錄 pgactive.pgactive_conflict_history 資料表中發生的衝突。

pgactive.pgactive_conflict_history 會持續成長。您可能想要定義清除政策。這可以透過定期刪除某些記錄或定義此關係的分割方案 (以及之後分離、捨棄、截斷感興趣的分割區) 來完成。若要定期實作清除政策,其中一個選項是使用pg_cron延伸模組。請參閱下列pg_cron有關歷史記錄表範例的資訊,使用 PostgreSQL pg_cron 延伸模組 排程維護

處理主動-主動式複寫中的序列

具有 pgactive 擴充功能的 RDS for PostgreSQL 資料庫執行個體使用兩種不同的序列機制來產生唯一值。

全域序列

若要使用全域序列,請使用 CREATE SEQUENCE 陳述式建立本機序列。不要使用 usingnextval(seqname),而是使用 pgactive.pgactive_snowflake_id_nextval(seqname) 來取得序列中的下一個唯一值。

下列範例會建立全域序列:

postgres=> CREATE TABLE gstest ( id bigint primary key, parrot text );
postgres=>CREATE SEQUENCE gstest_id_seq OWNED BY gstest.id;
postgres=> ALTER TABLE gstest \ ALTER COLUMN id SET DEFAULT \ pgactive.pgactive_snowflake_id_nextval('gstest_id_seq');
分割序列

在分割步驟或分割序列中,每個節點都會使用一般 PostgreSQL 序列。每個序列會以相同的量遞增,並從不同的偏移量開始。例如,若是步進 100,節點 1 會產生序列為 101、201、301,依此類推,而節點 2 會產生序列為 102、202、302,依此類推。即使節點無法長時間通訊,此結構仍能正常運作,但是設計人員必須在建立結構描述時指定最大節點數,並且需要每個節點的組態。若發生錯誤,便容易導致序列重疊。

透過在節點上建立所需的序列來對 pgactive 設定此方法相對較為簡單,如下所示:

CREATE TABLE some_table (generated_value bigint primary key);
postgres=> CREATE SEQUENCE some_seq INCREMENT 100 OWNED BY some_table.generated_value;
postgres=> ALTER TABLE some_table ALTER COLUMN generated_value SET DEFAULT nextval('some_seq');

然後在每個節點上呼叫,以提供不同的偏移量起始值,如下所示。

postgres=> -- On node 1 SELECT setval('some_seq', 1); -- On node 2 SELECT setval('some_seq', 2);

pgactive 延伸模組的參數參考

您可以使用下列查詢來檢視與 pgactive 延伸模組相關聯的所有參數。

postgres=> SELECT * FROM pg_settings WHERE name LIKE 'pgactive.%';

測量 pgactive 成員之間的複寫延遲

您可以使用下列查詢來檢視pgactive成員之間的複寫延遲。在每個pgactive節點上執行此查詢以取得完整圖片。

postgres=# SELECT *, (last_applied_xact_at - last_applied_xact_committs) AS lag FROM pgactive.pgactive_node_slots; -{ RECORD 1 ]----------------+----------------------------------------------------------------- node_name | node2-app slot_name | pgactive_5_7332551165694385385_0_5__ slot_restart_lsn | 0/1A898A8 slot_confirmed_lsn | 0/1A898E0 walsender_active | t walsender_pid | 69022 sent_lsn | 0/1A898E0 write_lsn | 0/1A898E0 flush_lsn | 0/1A898E0 replay_lsn | 0/1A898E0 last_sent_xact_id | 746 last_sent_xact_committs | 2024-02-06 18:04:22.430376+00 last_sent_xact_at | 2024-02-06 18:04:22.431359+00 last_applied_xact_id | 746 last_applied_xact_committs | 2024-02-06 18:04:22.430376+00 last_applied_xact_at | 2024-02-06 18:04:52.452465+00 lag | 00:00:30.022089

pgactive 延伸模組的現制

  • 所有資料表都需有主索引鍵,否則不允許更新和刪除操作。主索引鍵欄中的值不應更新。

  • 序列可能有間隙,有時可能不按順序。序列未複寫。如需詳細資訊,請參閱處理主動-主動式複寫中的序列

  • DDL 和大型物件不會複寫。

  • 次要唯一索引可能會導致資料差異。

  • 群組中所有節點的定序都必須相同。

  • 節點之間的負載平衡是一種反模式。

  • 大型交易可能造成複寫延遲。