샤딩
•
큰 데이터를 여러 서브셋으로 나누어 여러 인스턴스에 저장하는 방법이다. 이때 각 서브셋을 샤드(shard)라고 한다.
◦
파티셔닝은 하나의 인스턴스에서 테이블을 분리하여 사용한다.
•
데이터를 여러 인스턴스로 분산해 쿼리할 데이터의 양이 줄어듦에 따라 쿼리 성능을 향상시킬 수 있다.
단점
1.
재샤딩에 비용이 많이 든다 : 추후, 수요가 증가/감소해 서버를 추가/제거하는 경우 데이터를 재샤딩하는 것이 복잡하다. 데이터를 샤딩하기 위해 주어진 조건에 따라 데이터를 다시 정렬해야 하므로, 비용이 많이 든다.
2.
샤드는 불균형이 될 수 있다 : 샤드를 나누는 방식에 따라 데이터 불균형이 발생할 수 있다.
3.
샤드 병합이 복잡하다
4.
Join 비용이 증가한다 : 데이터가 여러 서버에 분산되어 있는 경우 모든 서버에서 조인 작업을 수행해야 하므로 매우 복잡하다.
샤딩 종류
1. Hash Sharding
•
열, 또는 열 조합을 선택하고 해시 함수 결과값을 통해 샤드를 결정하는 방식이다.
•
아래 그림은 그 중 하나인 Modular Sharding 방식으로 PK값의 모듈러 연산 결과를 통해 샤드를 결정하는 방식이다.
•
PK값을 샤드의 개수로 모듈러 연산해 해시값을 얻으므로, 총 샤드 수가 정해져있을 때 유용하다.
•
단점 : 샤드 추가/감소 시 해시 함수 변경이 필요하고, 이에 따라 데이터를 재정렬 해야한다. (재샤딩)
2. Range Based Sharding
•
범위(날짜 범위, 기본 키 등)를 기반으로 샤드를 만드는 방식이다.
•
아래와 같이 PK가 0-9인 데이터는 0번 샤드에, 10-19인 데이터는 1번 샤드에 저장할 수 있다.
•
샤드 추가/감소 비용이 Hash Sharing 방식보다는 낮다.
•
단점: 샤드의 불균형이 발생할 수 있다. 즉, 특정 샤드에만 부하가 집중될 수 있다.
3. Directory Based Sharding
•
각 샤드에 대한 카테고리(shard key)를 설정해 데이터의 종류에 따라 동일한 샤드로 그룹화하는 방식이다.
•
이러한 카테고리는 지역, 성별등이 될 수 있다. (카디널리티가 낮은)
•
lookup table에 shard key를 추가하면 되므로, 샤드 추가/감소에 비교적 유연하다.
•
단점: 반드시 샤드와 데이터를 매핑하는 lookup table을 만들고 유지해야 한다.
•
단점: 쿼리를 수행하기 전 반드시 lookup table을 거쳐야하므로 성능이 낮아질 수 있다. lookup table이 단일 장애 지점이 될 수 있다.
4. Entity Group Based Sharding
•
관련된 데이터를 기반으로 데이터를 분할하는 방식이다.
•
관계형 데이터를 다른 샤드에 보관하면 조인 작업을 수행하는 것이 복잡해지므로, 관련된 데이터는 같은 샤드에 저장하는 방식이다.
•
아래와 같이 Users 데이터를 기반으로 샤드를 결정하고, 해당 User와 관련된 모든 데이터를 동일한 샤드에 보관한다.
•
Join 비용을 줄여 쿼리 성능 최적화 가능
•
단점: 관계형 데이터베이스에 적합하다.
샤딩 해야하나?
이런 상황에서 유용하다
•
애플리케이션 데이터 양이 단일 데이터베이스 서버의 스토리지 한계를 초과했을 때
•
Write & Read 양이 단일 데이터베이스 서버나 read replica가 핸들링할 수 있는 수준을 넘어서서 반응이 느려졌을 때
•
단일 데이터베이스 서버 또는 read replica에 가능한 네트워크 대역폭을 초과해 반응 속도가 느려졌을 때
샤딩은 복잡도가 높아지므로, 최적화할 수 있는 모든 다른 옵션들을 검토해야 한다
•
캐시(Cache): 읽기 성능이 문제라면, 캐시를 통해 이미 요청된 데이터들을 일시적으로 메모리에 저장해 읽기 성능 향상 가능.
•
복제(Replication): read replica를 추가해 읽기 성능 향상 가능
결론
sharding은 데이터베이스 수평 확장을 고려할 때 좋은 해결책이 될 수 있다. 하지만 복잡성과 잠재적 실패 지점을 만들 수도 있다. 어떤 이에게는 필요할 수도 있지만, 다른 경우 sharding이 주는 이점보다 sharded architecture를 만들고 유지하는데 드는 시간과 비용이 압도적일 수도 있다.