시분할(Sharding)이란 무엇인가?
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
데이터 분석
대상자
- 데이터베이스 설계 및 확장성 문제 해결에 관심 있는 개발자, 시스템 아키텍트
- 중간~고급 수준의 데이터베이스 운영 지식을 가진 사용자
핵심 요약
- 시분할(Sharding)은 데이터베이스의 수평 확장 방법으로, 데이터를 여러 서버에 분산하여 성능 향상과 고가용성 확보를 목표로 합니다.
- 주요 이점: 수평 확장, 고가용성, 성능 개선, 고 동시성 처리. 단점: 복잡한 쿼리 관리, 재분할 작업, 일관성 유지 어려움.
- 핵심 용어: Shard Key, 수평 확장(Horizontal Scaling), 최종 일관성(Eventual Consistency).
섹션별 세부 요약
1. 문제 상황: 스케일링의 필요성
- 초기 단일 데이터베이스가 성능 저하로 인해 부하 발생 (예: RSVP 처리 지연, 페이지 로딩 속도 감소).
- 데이터베이스 테이블의 과도한 읽기/쓰기 패턴, 인덱스 부하, 디스크 IOPS/CPU 사용량 제한.
- 단일 데이터베이스 구조가 성능, 확장성, 고가용성 요구에 부적합.
2. 시분할의 정의 및 이점
- 시분할은 데이터를 여러 셰드(Shard)로 나누어 분산 저장 (예: 사용자 ID 범위, 지역, 해시 값 기준).
- 수평 확장 가능 (서버 추가 시 처리량 증가), 고가용성 확보 (한 셰드 실패 시 다른 셰드 영향 없음), 쿼리 성능 향상 (핫스팟(Hot Spot) 줄임).
- 고 동시성 처리 지원 (각 셰드가 독립적으로 쿼리 처리).
3. 시분할 유형 및 전략
- 범위 기반(Range Based): 사용자 ID 1–100 → 셰드 A, 101–200 → 셰드 B 등.
- 지리 기반(Geo Based): 미국 사용자 → 셰드 A, 유럽 사용자 → 셰드 B.
- 해시 기반(Hash Based):
hash(user_id) % number_of_shards
계산. - 디렉토리 기반(Directory Based): 중앙 관리 테이블로
user_id → shard_id
매핑. - 특성 기반(Featured Based): 특정 특성(예: 이벤트 유형) 기준 분할.
4. 시분할의 단점 및 고려 사항
- 운영 복잡성 증가: 모니터링, 백업, 배포 관리 어려움.
- 데이터 관리 복잡성: 셰드 간 데이터 이동 및 재분할 작업 필요.
- 크로스 셰드 쿼리 어려움: JOIN, 집계, 트랜잭션 처리 시 성능 저하.
- 불균형한 부하 분배: 잘못된 셰드 키 선택 → "핫 셰드" 발생.
- 최종 일관성 유지: 셰드 간 데이터 동기화 지연으로 인한 일관성 문제.
5. 시분할 구현 단계
- 데이터 및 작업량 분석: 고부하 테이블 식별 (예:
users
,rsvps
). - 셰드 키 선택: 고유성과 균형된 부하 분배를 고려 (예:
user_id
,location
). - 시분할 전략 결정: 지리 기반, 테넌트 기반 등 선택.
- 어플리케이션 로직 업데이트: 셰드 라우팅, 크로스 셰드 쿼리 처리.
- 클라이언트/서버 측 셰드 라우팅 결정: 클라이언트 측 또는 서버 측(예: AWS Aurora, MongoDB).
6. 시분할 도구 및 예제
- 도구:
- Vitess (MySQL 시분할), MongoDB (내장 시분할), Citus (PostgreSQL 확장), ProxySQL (MySQL 라우팅).
- 예제 코드:
```javascript
// shard-config.js
export const shardMap = {
US: {
name: 'Shard A',
connectionString: 'postgres://user:pass@shard-us.example.com/meetupdb',
},
EU: {
name: 'Shard B',
connectionString: 'postgres://user:pass@shard-eu.example.com/meetupdb',
},
};
```
```javascript
// db-router.js
import { shardMap } from './shard-config.js';
import { Client } from 'pg';
export function getShardClient(region) {
const shard = shardMap[region];
if (!shard) throw new Error(No shard found for region: ${region}
);
const client = new Client({ connectionString: shard.connectionString });
return client;
}
```
결론
- 시분할은 대규모 데이터베이스 확장에 효과적이지만, 셰드 키 선택 및 재분할 전략이 필수적.
- 지리 기반 셰드 키 사용 시, 지역별 데이터 분산으로 지연 감소 가능 (예: 미국 사용자 → 셰드 A).
- 시분할 도구(Vitess, Citus 등) 활용을 통해 복잡성을 줄이고, 성능 향상에 집중.