pgactive를 사용하여 액티브-액티브 복제 지원 - Amazon Relational Database Service

pgactive를 사용하여 액티브-액티브 복제 지원

pgactive 확장은 액티브-액티브 복제를 사용하여 여러 RDS for PostgreSQL 데이터베이스에서 쓰기 작업을 지원하고 조정합니다. Amazon RDS for PostgreSQL은 다음 버전에서 pgactive 확장을 지원합니다.

  • RDS for PostgreSQL 16.1 이상의 16 버전

  • RDS for PostgreSQL 15.4-R2 이상의 15 버전

  • RDS for PostgreSQL 14.10 이상의 14 버전

  • RDS for PostgreSQL 13.13 이상의 13 버전

  • RDS for PostgreSQL 12.17 이상의 12 버전

  • RDS for PostgreSQL 11.22

참고

복제 구성에서 둘 이상의 데이터베이스에 쓰기 작업이 있는 경우 충돌이 발생할 수 있습니다. 자세한 내용은 액티브-액티브 복제의 충돌 처리 단원을 참조하세요.

pgactive 확장 기능 초기화

RDS for PostgreSQL DB 인스턴스에서 pgactive 확장 기능을 초기화하려면 rds.enable_pgactive 파라미터 값을 1로 설정한 다음 데이터베이스에 확장을 생성합니다. 이렇게 하면 파라미터 rds.logical_replicationtrack_commit_timestamp가 자동으로 활성화되고 wal_level 값이 logical로 설정됩니다.

이러한 작업을 수행하려면 rds_superuser 역할의 권한이 있어야 합니다.

AWS Management Console 또는 AWS CLI를 사용하여 PostgreSQL DB 인스턴스에 필요한 RDS를 생성할 수 있습니다. 다음 단계에서는 RDS for PostgreSQL DB 인스턴스가 사용자 지정 DB 파라미터 그룹에 연결되어 있다고 가정합니다. 사용자 지정 DB 파라미터 그룹 생성에 대한 자세한 내용은 Amazon RDS의 파라미터 그룹 단원을 참조하세요.

pgactive 확장 기능을 초기화하려면
  1. https://console.aws.amazon.com/rds/에서 AWS Management Console에 로그인한 후 Amazon RDS 콘솔을 엽니다.

  2. 탐색 창에서 RDS for PostgreSQL DB 인스턴스를 선택합니다.

  3. RDS for PostgreSQL DB 인스턴스의 구성 탭을 엽니다. 인스턴스 세부 정보에서 DB 인스턴스 파라미터 그룹 링크를 찾습니다.

  4. 링크를 선택하여 RDS for PostgreSQL DB 인스턴스와 연결된 사용자 지정 파라미터를 엽니다.

  5. rds.enable_pgactive 파라미터를 찾아 1로 설정하여 pgactive 기능을 초기화합니다.

  6. Save changes(변경 사항 저장)를 선택합니다.

  7. Amazon RDS 콘솔의 탐색 창에서 데이터베이스를 선택합니다.

  8. RDS for PostgreSQL DB 인스턴스를 선택한 다음 작업 메뉴에서 재부팅을 선택합니다.

  9. DB 인스턴스 재부팅을 확인하여 변경 사항을 적용합니다.

  10. DB 인스턴스를 사용할 수 있게 되면 psql 또는 다른 PostgreSQL 클라이언트를 사용하여 RDS for PostgreSQL DB 인스턴스에 연결합니다.

    다음 예시에서는 RDS for PostgreSQL DB 인스턴스에 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 확장 기능을 초기화하려면

AWS CLI를 사용하여 pgactive를 초기화하려면 다음 절차와 같이 modify-db-parameter-group 작업을 호출하여 사용자 지정 파라미터 그룹의 특정 파라미터를 수정합니다.

  1. 다음 AWS CLI 명령으로 rds.enable_pgactive1로 설정하여 RDS for PostgreSQL DB 인스턴스의 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 DB 인스턴스를 재부팅하여 pgactive 라이브러리가 초기화되도록 합니다.

    aws rds reboot-db-instance \ --db-instance-identifier your-instance \ --region aws-region
  3. 인스턴스를 사용할 수 있다면 psql을 사용하여 RDS for PostgreSQL DB 인스턴스에 연결합니다.

    psql --host=mydb.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=master user --password --dbname=postgres
  4. 다음과 같이 확장을 생성합니다.

    postgres=> CREATE EXTENSION pgactive;

RDS for PostgreSQL DB 인스턴스용 액티브-액티브 복제 설정

다음 절차는 동일한 리전에서 PostgreSQL 15.4 이상을 실행하는 RDS for PostgreSQL DB 인스턴스 간에 액티브-액티브 복제를 시작하는 방법을 보여줍니다. 다중 리전 고가용성 예제를 실행하려면 Amazon RDS for PostgreSQL 인스턴스를 서로 다른 두 리전에 배포하고 VPC 피어링을 설정해야 합니다. 자세한 내용은 VPC 피어링을 참조하세요.

참고

여러 리전 간에 트래픽을 전송하면 추가 비용이 발생할 수 있습니다.

이 단계에서는 RDS for PostgreSQL DB 인스턴스가 pgactive 확장을 이용해 설정되었다고 가정합니다. 자세한 내용은 pgactive 확장 기능 초기화 단원을 참조하십시오.

pgactive 확장을 사용하여 첫 번째 RDS for PostgreSQL DB 인스턴스를 구성하려면

다음 예제는 pgactive 그룹을 생성하는 방법과 RDS for PostgreSQL에서 pgactive 확장을 생성하는 데 필요한 기타 단계를 보여줍니다.

  1. psql 또는 다른 클라이언트 도구를 사용하여 첫 번째 RDS for PostgreSQL DB 인스턴스에 연결할 수 있습니다.

    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 그룹 내 노드를 고유하게 식별하기 위해 할당하는 이름입니다.

    참고

    공개적으로 액세스할 수 있는 DB 인스턴스에서 이 단계를 성공적으로 수행하려면 rds.custom_dns_resolution 파라미터를 1로 설정하여 활성화해야 합니다.

  8. DB 인스턴스가 준비되었는지 확인하려면 다음 명령을 사용합니다.

    app=> SELECT pgactive.pgactive_wait_for_node_ready();

    이 명령이 제대로 실행되면 다음과 같은 출력이 표시됩니다.

    pgactive_wait_for_node_ready ------------------------------ (1 row)
두 번째 RDS for PostgreSQL 인스턴스를 구성하고 pgactive 그룹에 연결하려면

다음 예제는 RDS for PostgreSQL DB 인스턴스를 pgactive 그룹에 조인하는 방법과 DB 인스턴스에서 pgactive 확장을 생성하는 데 필요한 기타 단계를 보여줍니다.

이 단계에서는 다른 RDS for PostgreSQL DB 인스턴스pgactive 확장을 이용해 설정되었다고 가정합니다. 자세한 내용은 pgactive 확장 기능 초기화 단원을 참조하십시오.

  1. psql을 사용하여 게시자로부터 업데이트를 수신할 인스턴스에 연결합니다.

    psql --host=secondinstance.111122223333.aws-region.rds.amazonaws.com --port=5432 --username=master username --password --dbname=postgres
  2. 다음 명령을 사용하여 두 번째 RDS for PostgreSQL DB 인스턴스에 데이터베이스를 생성합니다.

    postgres=> CREATE DATABASE app;
  3. 다음 명령을 사용하여 새 데이터베이스로 연결을 전환합니다.

    \c app
  4. 기존 데이터베이스에 pgactive 확장을 생성합니다.

    app=> CREATE EXTENSION pgactive;
  5. 다음과 같이 RDS for PostgreSQL 두 번째 DB 인스턴스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. DB 인스턴스가 준비되었는지 확인하려면 다음 명령을 사용합니다.

    app=> SELECT pgactive.pgactive_wait_for_node_ready();

    이 명령이 제대로 실행되면 다음과 같은 출력이 표시됩니다.

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

    첫 번째 RDS for 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는 두 DB 인스턴스 간에 데이터를 동기화합니다.

  7. 다음 명령을 사용하여 두 번째 DB 인스턴스의 데이터베이스에 데이터가 있는지 확인할 수 있습니다.

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

    데이터가 성공적으로 동기화되면 다음과 같은 출력이 표시됩니다.

    count ------- 3
  8. 다음 명령을 실행하여 새 값을 삽입합니다.

    app=> INSERT INTO inventory.products (id, product_name) VALUES ('lotion');
  9. 첫 번째 DB 인스턴스의 데이터베이스에 연결하고 다음 쿼리를 실행합니다.

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

    액티브-액티브 복제가 초기화된 경우 출력은 다음과 비슷합니다.

    count ------- 4
pgactive 그룹에서 DB 인스턴스를 분리하고 제거하려면

다음 단계를 사용하여 pgactive 그룹에서 DB 인스턴스를 분리하고 제거할 수 있습니다.

  1. 다음 명령을 사용하여 첫 번째 DB 인스턴스에서 두 번째 DB 인스턴스를 분리할 수 있습니다.

    app=> SELECT * FROM pgactive.pgactive_detach_nodes(ARRAY[‘node2-app']);
  2. 다음 명령을 사용하여 두 번째 DB 인스턴스에서 pgactive 확장을 제거합니다.

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

    확장을 강제로 제거하려면:

    app=> SELECT * FROM pgactive.pgactive_remove(true);
  3. 다음 명령을 사용하여 확장을 제거합니다.

    app=> DROP EXTENSION pgactive;

액티브-액티브 복제의 충돌 처리

pgactive 확장은 클러스터별이 아니라 데이터베이스별로 작동합니다. pgactive를 사용하는 각 DB 인스턴스는 독립 인스턴스이며 모든 소스의 데이터 변경을 수락할 수 있습니다. 변경 사항이 DB 인스턴스로 전송되면 PostgreSQL은 변경 사항을 로컬에서 커밋한 다음 pgactive를 사용하여 변경 사항을 다른 DB 인스턴스에 비동기적으로 복제합니다. 두 PostgreSQL DB 인스턴스가 거의 동시에 같은 레코드를 업데이트하는 경우 충돌이 발생할 수 있습니다.

pgactive 확장은 충돌 감지 및 자동 해결을 위한 메커니즘을 제공합니다. 두 DB 인스턴스 모두에서 트랜잭션이 커밋된 시점의 타임스탬프를 추적하고 최신 타임스탬프와 함께 변경 사항을 자동으로 적용합니다. 또한 pgactive 확장은 pgactive.pgactive_conflict_history 테이블에서 충돌이 발생하는 경우에 이를 로깅합니다.

pgactive.pgactive_conflict_history는 계속 규모가 늘어납니다. 제거 정책을 정의할 수 있습니다. 정기적으로 일부 레코드를 삭제하거나 이 관계에 대한 파티션 스키마를 정의하여 수행할 수 있으며, 나중에 원하는 파티션을 분리, 삭제, 잘라낼 수 있습니다. 정기적으로 제거 정책을 구현하기 위한 한 가지 옵션은 pg_cron 확장을 사용하는 것입니다. PostgreSQL pg_cron 확장을 사용하여 유지 관리 일정 예약 pg_cron 기록 테이블에 대한 다음 예제 정보를 참조하세요.

액티브-액티브 복제의 시퀀스 처리

pgactive 확장이 포함된 RDS for PostgreSQL DB 인스턴스는 서로 다른 두 개의 시퀀스 메커니즘을 사용하여 고유한 값을 생성합니다.

글로벌 시퀀스

글로벌 시퀀스를 사용하려면 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');

그런 다음 각 노드에서 setval을 호출하여 다음과 같이 다른 오프셋 시작 값을 지정합니다.

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 및 대형 객체는 복제되지 않습니다.

  • 보조 고유 인덱스로 인해 데이터 차이가 발생할 수 있습니다.

  • 그룹 내 모든 노드에서 데이터 정렬이 동일해야 합니다.

  • 노드 간 로드 밸런싱은 안티 패턴입니다.

  • 대규모 트랜잭션으로 인해 복제 지연이 발생할 수 있습니다.