Show HN: PgDog – 앱을 변경하지 않고 Postgres 확장
Source: Hacker News
소개
Hey HN! Lev와 Justin입니다. 우리는 PgDog(https://pgdog.dev/)의 저자이며, PgDog은 PostgreSQL용 연결 풀러, 로드 밸런서, 그리고 데이터베이스 샤더입니다. 트래픽이 많은 앱을 구축하면 가장 먼저 고장 나는 것이 데이터베이스라는 것을 잘 아실 겁니다. 우리는 애플리케이션 코드 변경이나 데이터베이스 마이그레이션 없이도 작동하는 네트워크 프록시로 이 문제를 해결하고 있습니다.
우리의 지난해 게시물: https://news.ycombinator.com/item?id=44099187
Production Update
가장 중요한 업데이트: 우리는 현재 프로덕션 단계에 있습니다. Sharding이 많이 사용되고 있으며, direct‑to‑shard queries(쿼리당 하나의 샤드)가 거의 항상 작동합니다. Cross‑shard(또는 multi‑database) queries는 아직 진행 중이지만, 진전이 이루어지고 있습니다.
Features
Aggregate Functions
COUNT(), MIN(), MAX(), AVG(), STDDEV() 및 VARIANCE()와 같은 집계 함수는 애플리케이션을 리팩터링하지 않아도 작동합니다. PgDog은 쿼리를 투명하게 재작성하여 누락된 정보를 가져오면서 전송 중에 집계를 계산합니다. 예를 들어, 다중 데이터베이스 평균 계산을 위해서는 원래 합계를 구하기 위한 전체 행 수가 필요합니다. PgDog은 쿼리에 COUNT()가 없으면 추가하고, 애플리케이션에 전달되는 행에서는 이를 제거합니다.
Sorting and Grouping
DISTINCT를 포함한 정렬 및 그룹화가 작동합니다. 단, 참조된 컬럼이 결과 집합에 포함되어야 합니다. timestamp with time zone, 모든 정수형, varchar 등 10가지 이상의 데이터 타입을 지원합니다.
Cross‑Shard Writes
스키마 변경(CREATE/DROP/ALTER)을 포함한 크로스‑샤드 쓰기가 이제 원자적으로 수행되며, 2단계 커밋을 사용해 모든 샤드 간에 동기화됩니다. PgDog은 트랜잭션 상태를 내부적으로 추적하고 첫 번째 단계가 실패하면 트랜잭션을 롤백합니다. ORM을 위한 몽키패치가 필요하지 않습니다: PgDog은 COMMIT 문을 가로채 PREPARE TRANSACTION을 실행한 뒤 COMMIT PREPARED를 수행합니다.
Omnisharded Tables
전체 샤드에 복제되거나 미러링된 Omnisharded 테이블은 원자적인 읽기와 쓰기를 지원합니다. 대부분의 데이터베이스는 완전히 샤딩될 수 없으며, 모든 인스턴스 간에 동기화가 필요한 공통 데이터가 필요하기 때문에 중요합니다.
Multi‑Tuple Inserts
예시:
INSERT INTO table_x VALUES ($1, $2), ($3, $4);
와 같은 다중 튜플 삽입은 PgDog의 쿼리 리라이터에 의해 분할되어 적절한 샤드에 자동으로 배포됩니다. 이는 Prisma, Sequelize 등과 같은 ORM이 코드 변경 없이도 동작하도록 합니다.
Sharding‑Key Mutations
샤딩 키가 업데이트될 경우, PgDog은 UPDATE를 SELECT, INSERT, DELETE 세 개의 쿼리로 재작성하여 행을 샤드 간에 이동시킵니다. Citus(샤딩을 위한 PostgreSQL 확장)를 사용한다면 이 접근 방식이 관심을 끌 수 있습니다.
Cross‑Shard Unique Sequence
기본 키에 UUID 대신 정수를 선호한다면, PgDog은 프록시 내부에 구현된 크로스‑샤드 고유 시퀀스를 제공합니다. 시스템 시계(및 몇 가지 다른 입력)를 사용하며 일반 PostgreSQL 함수처럼 호출할 수 있습니다:
INSERT INTO my_table (id, created_at) VALUES (pgdog.unique_id(), now());
이 시퀀스는 단조 증가하며 초당 최대 400만 개의 번호를 생성할 수 있고, 69.73년 범위를 갖습니다. 따라서 UUIDv7으로 즉시 마이그레이션할 필요가 없습니다.
Load Balancing
샤딩은 좋은 로드 밸런서 없이는 제대로 동작하지 않습니다. PgDog은 복제본을 모니터링하고 장애 조치 시 승격된 프라이머리로 쓰기 트래픽을 이동시킬 수 있습니다. 이는 각 인스턴스에 SELECT pg_is_in_recovery()를 폴링하기만 하면 되므로 관리형 PostgreSQL 서비스(RDS/Aurora, Azure PostgreSQL, GCP Cloud SQL)와도 호환됩니다. 현재 프라이머리 선출은 지원되지 않으므로, Patroni와 같은 자체 호스팅 환경에서는 기존 선출 메커니즘을 유지해야 하지만, 데이터베이스 앞에 HAProxy를 둘 필요는 없습니다.
로드 밸런서는 SELECT FOR UPDATE 및 INSERT/UPDATE가 포함된 CTE와 같은 엣지 케이스도 처리합니다. 코드에서 읽기/쓰기 분리를 관리하고 싶다면, 런타임에 연결 파라미터(-c pgdog.role=primary), SET 문, 혹은 쿼리 주석을 통해 PgDog에 힌트를 제공하면 됩니다.
Connection Pooling & Transaction Management
PgDog은 미완료된 트랜잭션을 자동으로 롤백하고, 부분적으로 전송된 쿼리를 드레인/재동기화하여 데이터베이스 연결을 유지하도록 돕습니다. 애플리케이션 충돌 후 연결 폭풍으로 Postgres 인스턴스가 100 % CPU에 도달하면 PgDog이 이를 완화할 수 있습니다. 드레인은 포기된 쿼리에서 행을 받아 버리고 PostgreSQL 와이어 프로토콜을 통해 Sync 메시지를 전송함으로써 수행되며, 이는 쿼리 컨텍스트를 정리하고 연결을 정상 상태로 되돌립니다.
오픈 소스 및 문서
PgDog은 오픈 소스이며 모든 형태의 기여와 피드백을 환영합니다. 모든 기능은 설정 가능하며 켜거나 끌 수 있어, 여러분의 속도에 맞춰 채택할 수 있습니다.
Documentation: https://docs.pgdog.dev
읽어 주셔서 감사합니다. 즐거운 해킹 되세요!