LLM WikiAccess-protected knowledge portal
← 스터디 홈
3편 · 약 11분

분산 아키텍처: 샤딩과 복제

샤드와 레플리카 — 두 축의 의미

ClickHouse 클러스터는 두 가지 독립적인 차원으로 확장한다.

  • 샤드(Shard): 데이터를 수평 분할한다. 샤드 수를 늘리면 쓰기·쿼리 처리량이 늘어난다.
  • 레플리카(Replica): 같은 데이터를 여러 노드에 복사한다. 레플리카 수를 늘리면 읽기 가용성과 장애 내성이 높아진다.

두 축은 독립적으로 설계한다. 샤드 수가 쿼리 병렬성을 결정하고, 레플리카 수가 데이터 내구성을 결정한다.

Distributed Table (쿼리 라우터) ↓ 팬아웃
샤드 1 (데이터 A) 레플리카 1-1 레플리카 1-2
샤드 2 (데이터 B) 레플리카 2-1 레플리카 2-2
샤드 3 (데이터 C) 레플리카 3-1 레플리카 3-2
샤딩과 복제의 두 축: 샤드는 수평 분할, 레플리카는 고가용성

클러스터 설정

클러스터 토폴로지는 config.xml(또는 /etc/clickhouse-server/config.d/ 내 파일)의 <remote_servers> 블록에 정의한다.

<remote_servers>
  <my_cluster>
    <shard>
      <weight>1</weight>
      <internal_replication>true</internal_replication>
      <replica><host>ch-shard1-r1</host><port>9000</port></replica>
      <replica><host>ch-shard1-r2</host><port>9000</port></replica>
    </shard>
    <shard>
      <weight>1</weight>
      <internal_replication>true</internal_replication>
      <replica><host>ch-shard2-r1</host><port>9000</port></replica>
      <replica><host>ch-shard2-r2</host><port>9000</port></replica>
    </shard>
  </my_cluster>
</remote_servers>

핵심 설정 두 가지:

  • <weight>: 샤드별 데이터 할당 비율. 기본값 1. weight가 9:10이면 9/19, 10/19 비율로 데이터가 분배된다.
  • <internal_replication>true</internal_replication>: Distributed 테이블이 한 레플리카에만 쓰고 나머지는 ReplicatedMergeTree가 알아서 동기화하도록 한다. false로 설정하면 Distributed가 모든 레플리카에 직접 중복 쓰기를 한다. ReplicatedMergeTree를 사용할 때는 반드시 true로 설정해야 한다.

ReplicatedMergeTree와 ClickHouse Keeper

레플리카 간 동기화 조정은 ZooKeeper 또는 ClickHouse 내장 구현인 ClickHouse Keeper가 담당한다.

ClickHouse Keeper는 ZooKeeper의 데이터 모델과 클라이언트 프로토콜을 C++로 재구현하되, 합의 알고리즘으로 ZAB 대신 Raft를 사용한다. 신규 클러스터라면 별도 ZooKeeper 없이 Keeper를 전용 3-노드 앙상블로 운영하는 것이 권장된다. 3노드 앙상블은 1대 장애를 허용하고, 5노드는 2대 장애를 허용한다.

Keeper는 실제 데이터를 저장하지 않는다. Keeper가 추적하는 것:

  • 어떤 파트가 존재하는지 (parts registry)
  • 복제 로그(log) — INSERT·MERGE·MUTATION 작업 목록
  • 블록 번호 — 중복 삽입 방지용 deduplication token
  • Distributed DDL 큐
ClickHouse Keeper (Raft 3노드) parts registry replication log block numbers (dedup)
⇄ 메타데이터 조율
레플리카 A (INSERT 수신 + 파트 기록) ↓ HTTP 직접 전송 레플리카 B (파트 페치 + 로컬 기록)
Keeper의 역할: 메타데이터 조율만 담당, 데이터는 레플리카 간 직접 전송

복제 프로토콜: INSERT → 파트 동기화

INSERT 한 번이 어떻게 모든 레플리카에 반영되는지 단계별로 본다.

  1. 클라이언트가 레플리카 A에 INSERT — 레플리카 A가 데이터를 로컬 파일시스템에 새 파트로 기록한다.
  2. Keeper에 로그 항목 추가 — "파트 X가 생성됨"을 복제 로그에 기록한다.
  3. 레플리카 B가 로그를 폴링 — 새 항목을 감지한다.
  4. 레플리카 B가 레플리카 A에서 파트를 직접 HTTP fetch — Keeper를 거치지 않고 노드 간 직접 전송한다.
  5. 레플리카 B가 파트를 로컬에 기록하고 Keeper에 완료 상태를 보고한다.

MERGE와 MUTATION도 같은 흐름이다. 각 레플리카는 동일한 로그를 보고 독립적으로 작업을 실행하거나, 다른 레플리카에서 이미 완료된 결과 파트를 페치한다.

Quorum 쓰기

기본 INSERT는 단일 레플리카 쓰기 후 즉시 반환한다. 나머지 레플리카로의 전파는 비동기다. 내구성이 더 필요하면 quorum 옵션을 쓴다.

SET insert_quorum = 2;        -- 2개 레플리카가 확인해야 반환
SET insert_quorum = 'auto';   -- 과반수 레플리카가 확인해야 반환

quorum INSERT는 지정된 수의 레플리카가 "파트 기록 완료"를 Keeper에 보고할 때까지 클라이언트를 블록한다. 내구성이 높아지는 대신 쓰기 지연이 늘어난다.

Distributed 테이블과 샤딩 키

Distributed 테이블 자체에는 데이터가 없다. 쿼리 라우터 역할만 한다.

CREATE TABLE events_dist AS events_local
ENGINE = Distributed(
    my_cluster,           -- 클러스터 이름
    default,              -- 데이터베이스
    events_local,         -- 각 샤드의 로컬 테이블 이름
    cityHash64(user_id)   -- 샤딩 키 표현식
);

INSERT 시 Distributed는 각 행에 대해 샤딩 키를 평가하고 결과 % 총_샤드_weight로 타깃 샤드를 결정한다.

샤딩 키특성적합한 경우
rand()균등 분산, 데이터 지역성 없음쓰기 부하만 분산할 때
cityHash64(user_id)user_id 기준 지역성 확보사용자별 집계 쿼리가 많을 때
toYYYYMM(event_date)시간 분할특정 샤드에 쿼리가 집중될 수 있으니 주의

샤딩 키 선택 원칙: 쿼리에서 필터로 자주 사용하는 고카디널리티 컬럼을 기준으로 삼으면 Distributed 쿼리가 관련 샤드에만 팬아웃된다. 카디널리티가 낮은 컬럼(예: 성별)은 특정 샤드에 쓰기가 집중되는 핫스팟을 만든다.

읽기 흐름과 max_parallel_replicas

SELECT를 Distributed 테이블에 실행하면:

  1. 코디네이터 노드가 모든 샤드로 서브쿼리를 팬아웃한다.
  2. 각 샤드에서 가장 응답이 빠른 레플리카 1개가 선택되어 로컬 실행한다.
  3. 결과가 코디네이터로 반환되어 병합된다.

max_parallel_replicas 설정을 활성화하면 한 샤드 내 여러 레플리카가 데이터를 나눠 읽어 처리 속도를 높인다.

한 줄 정리

ClickHouse 분산 아키텍처는 Keeper가 메타데이터만 조율하고 실제 데이터는 레플리카 간 직접 이동시키는 구조로, 샤딩 키 선택과 internal_replication 설정이 클러스터 설계의 핵심이다.

References

  • https://clickhouse.com/docs/architecture/replication
  • https://clickhouse.com/docs/engines/table-engines/special/distributed
  • https://clickhouse.com/docs/shards
  • https://clickhouse.com/docs/guides/sre/keeper/clickhouse-keeper
  • https://sairamkrish.medium.com/clickhouse-sharding-and-replication-95b3275c873e
  • https://altinity.com/wp-content/uploads/2024/05/Deep-Dive-on-ClickHouse-Sharding-and-Replication-2024-1-1.pdf
  • https://severalnines.com/blog/clickhouse-scaling-and-sharding-best-practices/
  • https://chistadata.com/sharding-and-resharding-strategies-in-clickhouse/