Skip to main content

DDB : 샤딩 & 레플리케이션


Distributed Database Seminar Intro

1. 분산 데이터베이스 개요

1.1 분산 데이터베이스(DDB)란?

분산 데이터베이스(Distributed Database)는 하나의 데이터베이스를 여러 개의 노드(서버)에 물리적으로 나누어 저장하고 관리하는 시스템입니다. 단일 데이터베이스가 트래픽 증가로 인해 겪는 성능 저하, 용량 부족, 단일 장애점(SPOF) 문제를 해결하기 위해 사용됩니다.

1.2 CAP 이론

분산 시스템의 핵심 원칙으로, 다음 세 가지를 동시에 모두 만족할 수는 없다는 이론입니다.

Distributed Database Seminar Intro
  • Consistency (일관성): 모든 노드가 같은 시간에 같은 데이터를 보여줘야 한다.
  • Availability (가용성): 일부 노드에 장애가 생겨도 서비스는 계속되어야 한다.
  • Partition Tolerance (분할 허용성): 네트워크 단절이 발생해도 시스템은 동작해야 한다.
⚠️ 핵심

분산 환경에서는 네트워크 장애가 필연적이므로 P(분할 허용성) 는 반드시 안고 가야 하며, 시스템 목적에 따라 CP 또는 AP 중 하나를 선택하여 설계해야 합니다.


2. 샤딩 (Sharding)

2.1 샤딩이란

한 서버에서 감당할 수 없는 대용량 데이터를 여러 DB 서버(샤드)에 나누어 분산 저장하는 기술입니다. 페이스북이나 인스타그램 같은 대규모 서비스에서 필수적으로 사용됩니다.

  • 대규모 데이터 처리: 한 서버에서 처리할 수 없는 대량의 데이터를 여러 샤드로 나누어 분산 처리하여 효율적인 관리.
  • 트랜잭션 처리 속도 향상: 하나의 데이터베이스에서 처리하는 대신 여러개의 샤드에서 동시에 처리하여 성능 극대화.
  • 서버 부하 감소 및 확장성 향상: 특정 서버에 데이터가 집중되지 않도록 부하를 균등하게 분산.
  • 고가용성 및 장애 격리: 특정 샤드에 장애가 발생해도 다른 샤드는 정상적으로 운영 가능.
  • 네트워크 대역폭 절약: 데이터를 지역 또는 사용 패턴에 따라 분할하여 네트워크 트래픽 감소.

2.2 샤딩의 종류

  • 수직 샤딩 (Vertical): '사용자 DB', '주문 DB'처럼 기능이나 컬럼을 기준으로 쪼개는 방식. arch

  • 수평 샤딩 (Horizontal): 같은 테이블 스키마를 가지지만, 데이터 행(Row)을 샤딩 키 기준으로 나누는 방식. arch


3. 레플리케이션 (Replication)

  • 성능 향상: DB 요청의 60~80% 정도가 읽기 작업이기 때문에 Replication만으로도 성능 대폭 향상 가능
  • 지연시간 감소: 비동기 방식으로 운영되어 지연시간이 거의 없음
  • Failover: 일부 노드에 장애가 발생하더라도 서비스 접근 보장

arch

3.1 레플리케이션이란

데이터의 안정성을 위해 동일한 데이터를 여러 노드에 복제하는 방식입니다. 주로 Master-Slave 구조로 구성합니다.

  • Master: 쓰기(Write) 트래픽 전담
  • Slave: 읽기(Read) 트래픽 전담 (부하 분산 효과)

3.2 동작 원리 및 페일오버 (Failover)

arch

Master 노드에 변경이 생기면 로그를 생성하고, Slave 노드가 이를 가져와 자신의 데이터에 반영합니다.

Failover (장애 대응)

Master 노드가 죽으면 Replication만으로는 해결이 안 됩니다. 자동화된 툴을 통해 Slave 중 하나를 새로운 Master로 승격시켜 서비스 중단을 막아야 진정한 고가용성(HA)이 완성됩니다.

arch


4. Sharding 구현 및 테스트

구현은 Docker 환경에서 PostgreSQLCitus를 활용해 실제 성능 차이를 검증했습니다.

구현 목표 : PostgreSQL과 Citus 기반 샤딩 환경에서 데이터 조회 성능을 비교하여, 샤딩이 특정 쿼리 성능에 미치는 영향을 분석함. 이를 위해 샤딩된 테이블과 일반 테이블 간의 조건을 동등하게 하고 성능을 공정하게 비교.

4.1 아키텍처 (Architecture)

테스트를 위해 Docker Container를 사용하여 다음과 같은 가상 분산 환경을 구성했습니다.

  • Coordinator: 포트 5432 (애플리케이션 엔드포인트)
  • Worker 1: 포트 5433 (데이터 저장소 1)
  • Worker 2: 포트 5435 (데이터 저장소 2)

Architecture Diagram

4.2 구현 방향

  1. 데이터 준비: user_data 테이블을 생성하고 100만 개의 더미 데이터를 INSERT 합니다.
  2. 샤딩 적용: user_idShard Key로 설정하여 데이터를 분산합니다.
  3. 검증: 일반 테이블과 샤딩 테이블에서 동일한 SELECT 쿼리를 실행하여 CostExecution Time을 비교합니다.

4.3 단계별 구축 과정

1) Citus 활성화 및 Worker 노드 추가

PostgreSQL에 Citus 익스텐션을 활성화하고, 준비된 2개의 Worker 노드(Container)를 클러스터에 추가합니다.

-- Citus Extension 활성화
CREATE EXTENSION citus;

-- Worker 노드 등록 (Docker 컨테이너 호스트명/포트 기준)
SELECT citus_add_node('worker-1', 5432);
SELECT citus_add_node('worker-2', 5432);

2) Worker 노드 정상 등록 확인

citus_get_active_worker_nodes() 함수를 통해 노드들이 정상적으로 Coordinator와 통신 가능한지 확인합니다.

SELECT * FROM master_get_active_worker_nodes();
-- 결과: worker-1, worker-2 가 정상 출력됨을 확인
Architecture Diagram

3) 테이블 샤딩 (Sharding)

user_data 테이블을 user_id 컬럼을 기준으로 32개의 샤드로 분할합니다.

-- 테이블 생성
CREATE TABLE user_data_sharding (...);

-- user_id를 기준으로 분산 테이블 생성 (Shard Count: 32)
SELECT create_distributed_table('user_data_sharding', 'user_id');
Architecture Diagram

4) Round Robin 배치 확인

샤딩이 완료되면 32개의 논리적 샤드(Shard)가 2개의 물리적 워커 노드에 Round Robin 방식으로 균등하게 배포됩니다.

🧩 Round Robin 분배
  • Worker 1: Shard 1, 3, 5 ... (홀수 샤드)
  • Worker 2: Shard 2, 4, 6 ... (짝수 샤드)
  • 결과적으로 각 노드에 약 16개씩 샤드가 배치되어 부하가 균등하게 분산됩니다.
Architecture Diagram

5) Deep Dive: 해시 샤딩과 데이터 분배 원리

해시 샤딩은 특정 샤드에 데이터가 몰리는 것(Data Skew)을 방지하기 위해 결정적(Deterministic) 해시 알고리즘을 사용합니다. Coordinator는 이 과정을 통해 데이터가 저장될 위치를 정확히 계산합니다.

🔍 데이터는 어떻게 자기 자리를 찾아갈까?

샤딩 키(Shard Key)가 주어졌을 때, Citus는 다음과 같은 논리로 타겟 샤드를 결정합니다.

  1. 입력: 데이터의 샤딩 키를 확인합니다. (예: user_id = 1000)
  2. 해싱: 내부 해시 함수를 통해 고유한 정수값(Token)으로 변환합니다. (예: Hash(1000) -> 12345)
  3. 모듈러 연산: 해시 값을 전체 샤드 개수(32)로 나눈 나머지를 구합니다.
    • 12345 % 32 = 25
  4. 라우팅: 계산 결과에 따라 25번 샤드가 위치한 노드로 쿼리를 전송합니다.

Hash Sharding Mechanism

4.4 성능 비교

동일한 조건(100만 건 데이터)에서 일반 테이블과 샤딩 테이블에 대해 특정 사용자를 조회하는 쿼리를 실행했습니다.

쿼리 (Query):

EXPLAIN ANALYZE
SELECT * FROM user_data WHERE user_id = 'user_123';

테스트 결과:

Hash Sharding Mechanism Hash Sharding Mechanism
구분Execution Time결과 분석
일반 테이블33.945 ms전체 데이터를 스캔(Full Scan)하거나 인덱스를 타더라도 단일 노드 부하 발생
샤딩 테이블3.008 ms약 10배 성능 향상

분석: 해시 샤딩(Hash Sharding)을 적용했기 때문에, Coordinator가 user_id를 해싱하여 데이터가 저장된 특정 샤드(노드)로만 쿼리를 라우팅합니다. 불필요한 노드 탐색이 제거되어 비약적인 성능 향상이 가능했습니다.


5. Sharding + Replication

단순한 샤딩은 성능을 높여주지만, 노드 하나가 죽으면 데이터 일부가 유실되는 위험이 있습니다. 저희는 이를 보완하기 위해 Citus 샤딩 환경에 Streaming Replication을 결합하여 고가용성(HA) 아키텍처를 구축했습니다.

5.1 샤딩 + 레플리케이션 목표

  • 성능: 2개의 Worker 노드로 읽기/쓰기 분산 (Sharding)
  • 안정성: 각 Worker 노드마다 1개의 Slave 노드를 붙여 실시간 복제 (Replication)
  • 결과: Master 노드 장애 시에도 Slave 노드를 통해 서비스 지속

5.2 아키텍처

각 Worker 노드(Master) 뒤에 동일한 데이터를 가진 Slave 노드를 배치하여 총 5개의 컨테이너로 구성했습니다.

  • Coordinator: 쿼리 라우팅
  • Worker 1 (Master) ⇌ Worker 1 (Slave): 데이터 동기화
  • Worker 2 (Master) ⇌ Worker 2 (Slave): 데이터 동기화
Hash Sharding Mechanism

5.3 환경 구성: Citus 활성화 및 노드 추가

기존 샤딩 실습과 마찬가지로 Citus 확장을 활성화하고, 이번에는 복제 구성을 염두에 두고 Worker 노드 설정을 확인합니다.

-- 1. Citus Extension 활성화 (모든 노드)
CREATE EXTENSION citus;

-- 2. Worker 노드(Master) 2개 추가
SELECT citus_add_node('worker-1-master', 5432);
SELECT citus_add_node('worker-2-master', 5432);

5.4 테이블 샤딩 (Sharding)

테스트할 테이블을 만들고 user_id를 기준으로 데이터를 분산시킵니다.

-- 테이블 생성 및 샤딩 적용
CREATE TABLE user_data_ha (...);
SELECT create_distributed_table('user_data_ha', 'user_id');

정상적으로 실행되면 32개의 샤드가 두 개의 Master 노드에 분산 저장됩니다.

Architecture Diagram

5.5 Streaming Replication 적용 및 확인

PostgreSQL의 기본 기능인 Streaming Replication을 설정하여 Master와 Slave를 연결했습니다. 연결 후 pg_stat_wal_receiver 뷰를 통해 복제 상태를 검증합니다.

-- Slave 노드에서 복제 상태 확인 쿼리
SELECT status, sender_host, slot_name
FROM pg_stat_wal_receiver;
Architecture Diagram
확인 포인트
  • status: streaming 상태여야 정상적으로 실시간 복제가 이루어지고 있는 것입니다.
  • sender_host: Slave가 바라보고 있는 Master 노드의 주소가 정확한지 확인합니다.

5.6 데이터 동기화 검증 (Data Sync)

Master 노드에 데이터가 입력되었을 때, Slave 노드에도 즉시 반영되는지 확인합니다.

  1. Master: INSERT INTO user_data_ha ... 수행
  2. Slave: SELECT * FROM user_data_ha ... 수행
Architecture Diagram

결과: Slave 노드는 Read-Only 모드임에도 불구하고, Master와 완벽하게 동일한 데이터를 보유하고 있음을 확인했습니다. 자신이 복제한 Master 노드의 샤드 데이터만 정확히 가지고 있습니다.


5.7 장애 대응 (Failover)

가장 핵심적인 네트워크 장애 상황을 시뮬레이션했습니다.

🔥 장애 시나리오

상황: Worker 1번의 Master 노드 네트워크를 강제로 차단하여 다운시킴. 기대 결과: 서비스 중단 없이 Slave 노드를 통해 데이터를 읽어올 수 있어야 함.

Architecture Diagram

검증 결과: 기존에는 Master가 죽으면 쿼리 자체가 실패했으나, 레플리케이션 구성 후에는 Slave 노드에서 정상적으로 SELECT 쿼리가 수행되었습니다.

결론: 샤딩을 통해 성능을 확보하고, 레플리케이션을 통해 SPOF(단일 장애점) 문제를 해결하여 고가용성 분산 데이터베이스 환경을 성공적으로 구축했습니다.


6. 비교 분석

특징샤딩 (Sharding)레플리케이션 (Replication)
핵심 목적확장성 (Scalability)가용성 (Availability)
데이터 형태데이터를 조각내어 분산 저장데이터를 통째로 복제하여 저장
장점쓰기/읽기 부하 분산, 대용량 처리읽기 성능 향상, 장애 시 데이터 보존
단점관리 복잡도 증가, JOIN 연산 어려움데이터 동기화 지연(Lag) 발생 가능

결론

샤딩과 레플리케이션은 서로 대체재가 아닌 보완재입니다. 대규모 트래픽을 처리하는 백엔드 시스템에서는 샤딩으로 확장성을, 레플리케이션으로 안정성을 확보하는 전략을 함께 사용하는 것이 이상적입니다.