테이블 샤드와 레플리카
테이블 샤드와 레플리카 (Table shards and replicas)
ClickHouse에서 테이블 샤드와 레플리카가 무엇인지, 그리고 분산 테이블에서 INSERT 라우팅과 SELECT 포워딩이 어떻게 동작하는지 개념적으로 설명해요.
출처: 문서
본문
이 주제는 ClickHouse Cloud에는 적용되지 않아요. Cloud에서는 Parallel Replicas가 전통적인 shared-nothing ClickHouse 클러스터의 여러 샤드처럼 동작하고, 객체 스토리지가 레플리카를 대체해서 고가용성과 내결함성을 보장하거든요.
ClickHouse에서 테이블 샤드란 무엇인가요?
전통적인 shared-nothing ClickHouse 클러스터에서 샤딩은 ① 데이터가 단일 서버에 너무 크거나 ② 단일 서버가 데이터를 처리하기에 너무 느릴 때 사용돼요. 다음 그림은 ①의 경우를 보여줘요. uk_price_paid_simple 테이블이 단일 머신의 용량을 초과한 상황이에요.
이런 경우 데이터는 테이블 샤드 형태로 여러 ClickHouse 서버에 분할될 수 있어요. 각 샤드는 데이터의 부분집합을 보유하고 독립적으로 쿼리할 수 있는 일반적인 ClickHouse 테이블처럼 동작해요. 그러나 쿼리는 그 부분집합만 처리하므로, 데이터 분포에 따라 유효한 사용 사례가 될 수 있어요. 일반적으로 (서버당 하나의) 분산 테이블이 전체 데이터셋의 통합된 뷰를 제공해요. 분산 테이블은 데이터를 저장하지 않고 SELECT 쿼리를 모든 샤드에 포워딩하고 결과를 조합하며, INSERT를 라우팅해서 데이터를 고르게 분산해요.
분산 테이블 생성
SELECT 쿼리 포워딩과 INSERT 라우팅을 설명하기 위해, What are table parts 예제 테이블이 두 ClickHouse 서버의 두 샤드에 분할된 경우를 생각해 봐요. 먼저 이 설정에 해당하는 Distributed 테이블을 생성하는 DDL 문을 보여줄게요:
CREATE TABLE uk.uk_price_paid_simple_dist ON CLUSTER test_cluster
(
date Date,
town LowCardinality(String),
street LowCardinality(String),
price UInt32
)
ENGINE = Distributed('test_cluster', 'uk', 'uk_price_paid_simple', rand())
ON CLUSTER 절은 DDL 문을 분산 DDL 문으로 만들어, test_cluster 클러스터 정의에 나열된 모든 서버에 테이블을 생성하도록 ClickHouse에 지시해요. 분산 DDL은 클러스터 아키텍처에 추가 Keeper 컴포넌트를 요구해요. 분산 엔진 파라미터로는 클러스터 이름(test_cluster), 샤딩 대상 테이블이 있는 데이터베이스 이름(uk), 샤딩 대상 테이블 이름(uk_price_paid_simple), 그리고 INSERT 라우팅을 위한 샤딩 키를 지정해요. 이 예제에서는 rand 함수를 사용해 행을 샤드에 무작위로 배정해요. 그러나 사용 사례에 따라 복잡한 표현식도 샤딩 키로 사용할 수 있어요. 다음 섹션에서 INSERT 라우팅이 어떻게 동작하는지 설명할게요.
INSERT 라우팅
아래 다이어그램은 분산 테이블에 대한 INSERT가 ClickHouse에서 어떻게 처리되는지 보여줘요.
① 분산 테이블을 대상으로 하는 INSERT(단일 행)가 직접 또는 로드 밸런서를 통해 테이블을 호스팅하는 ClickHouse 서버로 전송돼요. ② INSERT의 각 행(이 예제에서는 한 개)에 대해 ClickHouse가 샤딩 키(여기서는 rand())를 평가하고, 그 결과를 샤드 서버 수로 모듈러 연산한 값을 목표 서버 ID로 사용해요(ID는 0부터 시작해 1씩 증가). 그 행은 포워딩되어 ③ 해당 서버의 테이블 샤드에 삽입돼요. 다음 섹션에서 SELECT 포워딩이 어떻게 동작하는지 설명할게요.
SELECT 포워딩
이 다이어그램은 분산 테이블로 SELECT 쿼리를 처리하는 방법을 보여줘요.
① 분산 테이블을 대상으로 하는 SELECT 집계 쿼리가 해당 ClickHouse 서버로(직접 또는 로드 밸런서를 통해) 전송돼요. ② Distributed 테이블은 대상 테이블의 샤드를 호스팅하는 모든 서버로 쿼리를 포워딩하고, 각 ClickHouse 서버는 로컬 집계 결과를 병렬로 계산해요. 그런 다음, 처음 대상이 된 분산 테이블을 호스팅하는 ClickHouse 서버가 ③ 모든 로컬 결과를 수집하고, ④ 그것들을 최종 전역 결과로 병합한 뒤, ⑤ 쿼리 발신자에게 반환해요.
ClickHouse에서 테이블 레플리카란 무엇인가요?
ClickHouse의 복제는 여러 서버에 샤드 데이터의 복사본을 유지함으로써 데이터 무결성과 장애 극복(failover) 을 보장해요. 하드웨어 장애는 불가피하므로, 복제는 각 샤드가 여러 레플리카를 갖도록 하여 데이터 손실을 방지해요. 쓰기는 직접 또는 작업에 레플리카를 선택하는 분산 테이블을 통해 어느 레플리카로든 보낼 수 있어요. 변경 사항은 다른 레플리카로 자동 전파돼요. 장애나 유지보수 시 데이터는 다른 레플리카에 계속 유지되며, 실패한 호스트가 복구되면 최신 상태를 유지하기 위해 자동으로 동기화돼요. 복제는 클러스터 아키텍처에 Keeper 컴포넌트를 요구한다는 점을 유의해 주세요. 다음 다이어그램은 여섯 대의 서버를 가진 ClickHouse 클러스터를 보여줘요. 여기서 앞서 소개한 두 테이블 샤드 Shard-1과 Shard-2는 각각 세 개의 레플리카를 갖고 있어요. 이 클러스터에 쿼리가 전송돼요.
쿼리 처리는 레플리카가 없는 설정과 유사하게 동작하며, 각 샤드의 레플리카 하나만 쿼리를 실행해요.
레플리카는 데이터 무결성과 장애 극복을 보장할 뿐만 아니라 서로 다른 레플리카에서 여러 쿼리를 병렬로 실행할 수 있게 해서 쿼리 처리 처리량도 향상시켜요.
① 분산 테이블을 대상으로 하는 쿼리가 해당 ClickHouse 서버로(직접 또는 로드 밸런서를 통해) 전송돼요. ② Distributed 테이블은 각 샤드의 레플리카 하나에 쿼리를 포워딩하고, 선택된 레플리카를 호스팅하는 각 ClickHouse 서버는 로컬 쿼리 결과를 병렬로 계산해요. 나머지는 레플리카가 없는 설정과 동일하게 동작하며 위 다이어그램에는 표시되지 않아요. 처음 대상이 된 분산 테이블을 호스팅하는 ClickHouse 서버는 모든 로컬 결과를 수집해 최종 전역 결과로 병합하고 쿼리 발신자에게 반환해요. ②에 대한 쿼리 포워딩 전략을 구성할 수 있다는 점을 유의하세요. 기본적으로 — 위 다이어그램과 달리 — 분산 테이블은 가능하면 로컬 레플리카를 선호하지만, 다른 로드 밸런싱 전략도 사용할 수 있어요.
더 많은 정보를 찾을 수 있는 곳
테이블 샤드와 레플리카에 대한 이 높은 수준의 소개를 넘어 더 자세한 내용은 배포 및 확장 가이드를 확인해 보세요. ClickHouse 샤드와 레플리카를 더 깊이 파고들기 위해 이 튜토리얼 비디오도 강력히 추천해요.