본문으로 건너뛰기

12.3 Citus 통합

Citus는 PostgreSQL을 여러 노드에 걸친 분산 데이터베이스로 확장하는 extension입니다. coordinator가 쿼리를 받아 worker들의 shard로 분배하는 구조인데, coordinator와 worker 각각이 단일 장애점이 되므로 노드 그룹마다 HA가 필요합니다. Patroni는 3.0부터 Citus 통합을 내장했습니다. 공식 문서의 표현을 빌리면 coordinator와 worker는 "physically different PostgreSQL/Patroni clusters that are just logically grouped together", 즉 물리적으로는 서로 다른 Patroni 클러스터이고 논리적으로만 하나의 Citus 클러스터로 묶입니다.

Citus 클러스터의 Patroni 그룹 구조

설정: citus 섹션 2키​

patroni.yml에 넣을 것은 두 키뿐입니다.

scope: demo
citus:
group: 0 # coordinator 는 0, worker 는 1, 2, 3, ...
database: citus # 전 노드에서 동일해야 함

group은 이 노드가 속한 Citus 그룹의 정수 id입니다. coordinator가 0, worker 그룹이 1 이상을 씁니다. database는 citus extension을 만들 database 이름으로, coordinator와 worker 전부 같아야 하고 현재는 단일 database만 지원합니다.

전제 조건은 다음과 같습니다.

  • Citus 10.0 이상. 투명한 worker switchover와 재시작은 Citus 11.2 이상 권장
  • superuser 자격증명이 coordinator와 모든 worker에서 동일
  • worker에서 coordinator로의 REST API 접근 허용
  • scope가 전 그룹에서 동일
  • citus extension이 모든 노드에 설치

Patroni가 대신해 주는 것​

citus 섹션이 있으면 Patroni가 Citus 운영에 필요한 연결 설정을 자동으로 처리합니다.

  • citus를 shared_preload_libraries에 추가합니다
  • max_prepared_transactions가 설정되어 있지 않으면 2 * max_connections로 설정합니다 (Citus의 2PC 트랜잭션용)
  • bootstrap.dcs.synchronous_mode를 quorum으로 설정합니다
  • citus.local_hostname을 localhost에서 실제 접속 가능한 값으로 조정합니다
  • superuser 자격증명을 pg_dist_authinfo에 넣어 노드 간 인증을 연결합니다
  • coordinator의 primary가 worker 그룹의 primary들을 자동 발견해 pg_dist_node에 등록합니다
  • worker 그룹에서 failover나 switchover가 나면 pg_dist_node를 갱신해 coordinator가 새 primary를 가리키게 합니다

Citus에서 노드 명단의 정본은 coordinator의 pg_dist_node 테이블입니다. 이 테이블을 Patroni가 관리한다는 것이 통합의 실질입니다. DBA가 worker 주소를 직접 등록하고 장애 때마다 고쳐 줄 필요가 없어집니다.

노트

superuser의 username, password, sslcert, sslkey를 바꾸면 pg_dist_authinfo의 인증 정보도 함께 걸려 있으므로 주의해서 진행합니다. Patroni 4.0.0부터는 noloadbalance tag가 없는 Citus secondary 노드도 pg_dist_node에 등록되어, read-only 쿼리를 secondary로 보내는 구성에 쓰입니다 (해당 GUC 설정 필요).

worker switchover 흐름​

분산 클러스터에서 까다로운 지점은 worker의 primary가 바뀌는 순간입니다. coordinator가 구 primary로 쿼리를 계속 보내면 오류가 나므로, Patroni는 coordinator의 해당 shard 트래픽을 잠시 멈췄다가 새 primary로 재개합니다. 그 통지 수단이 citus_update_node()입니다.

worker가 정지하기 전에 coordinator에 알리고, promote가 끝나 새 primary가 준비되면 다시 알려 멈춰 둔 트래픽을 흘려보냅니다. 클라이언트 입장에서는 해당 shard 쿼리가 잠시 대기했다가 이어지는 모양이 됩니다.

patronictl에서의 Citus​

patronictl list는 Citus 클러스터를 group 컬럼과 함께 한 화면에 보여 줍니다.

+ Citus cluster: demo ----------+----------------+---------+----+
| Group | Member | Host | Role | State | TL |
| 0 | coord1 | 172.27.0.10 | Replica | running | 1 |
| 0 | coord3 | 172.27.0.4 | Leader | running | 1 |
| 1 | work1-2 | 172.27.0.2 | Leader | running | 1 |

patronictl 명령 대부분이 --group 옵션을 받아 특정 그룹만 대상으로 삼습니다.

# worker 그룹 1 만 switchover
patronictl switchover demo --group 1

# coordinator 그룹의 설정만 편집
patronictl edit-config demo --group 0

정리​

  • citus.group(coordinator 0, worker 1 이상)과 citus.database 두 키로 Citus 통합이 켜집니다. scope 동일, superuser 동일, Citus 10.0+(권장 11.2+)가 전제입니다.
  • Patroni는 shared_preload_libraries, max_prepared_transactions, quorum synchronous mode, pg_dist_authinfo, pg_dist_node를 자동 관리합니다.
  • worker switchover는 citus_update_node() 통지로 coordinator 트래픽을 일시정지했다가 새 primary로 재개하는 흐름으로 진행됩니다.