From: 관계형 데이터베이스 실전 입문

Sharding?

  • 샤딩은 행별로 데이터의 저장 위치를 변경하는 구조를 말한다.
  • 각 샤드의 스키마 구조는 같다. 다른 것은 데이터의 내용이다.
  • 애플리케이션은 ID나 지역 등을 기준으로 데이터를 어느 샤드에 저장하는지를 판별한다.
    • 이 판별 로직을 애플리케이션에서 구현해야 한다.
  • 갱신 처리 성능 향상에 한계가 있을 때 샤딩을 검토할 수 있다.

문제점

  • 여러 샤드를 넘나드는 쿼리를 실행할 수 없다.
    • 해당 DB 서버 내부의 데이터만 join할 수 있다.
  • 각각의 샤드는 같은 구조의 스키마를 갖지만, 자동으로 동기화되지는 않는다는 점에 주의.
    • 스키마 구조를 변경하려면 DBA가 모든 샤드에 적용해줘야 한다.

From: 데이터 중심 애플리케이션 설계

5장에서 동일한 데이터의 복사본 여러 개를 다른 노드에 저장하는 개념인 복제를 다뤘다. 데이터셋이 매우 크거나 질의 처리량이 매우 높다면 복제만으로는 부족하고 데이터를 파티션으로 쪼갤 필요가 있다. 이 작업을 샤딩이라고도 한다.1

  • 샤딩: 대용량 데이터베이스를 의도적으로 작은 단위(partition)로 쪼개는 방법.

한편, 파티션이라는 단어는 여러 DB에서 다른 용어로 쓰이고 있다.2

여기서 말하는 파티션은 몽고DB, 엘라스틱서치, 솔라클라우드의 샤드(shard)에 해당한다. HBase에서는 리전(region), 빅테이블에서는 태블릿(tablet), 카산드라와 리악에서는 브이노드(vnode), 카우치베이스에서는 브이버켓(vBucket)이라고 부른다. 그러나 파티셔닝이 가장 널리 쓰이는 용어이므로 이 책에서는 계속 파티션을 사용한다.

파티셔닝의 목적에 대해서는 다음과 같이 나온다.

파티셔닝의 목적은 핫스팟(불균형적으로 높은 부하를 받는 노드)이 생기지 않게 하면서 데이터와 질의 부하를 여러 장비에 균일하게 분배하는 것이다. 그렇게 하려면 데이터에 적합한 파티셔닝 방식을 선택해야 하고 클러스터에 노드가 추가되거나 클러스터에서 노드가 제거될 때 파티션 재균형화를 실행해야 한다.

Partitioning by Key Range

키 범위 기준 파티셔닝

  • 각 파티션에 연속된 범위를 할당하는 방법.
  • 각 범위의 크기가 동일할 필요는 없다.
    • 범위가 동일하면 데이터가 고르지 않게 분포할 위험이 있다.
  • 파티션 경계는 수동/자동으로 설정할 수 있다.
  • hot spot 발생 위험이 있다.
    • hot spot: 다른 파티션보다 데이터가 많거나 질의를 많이 받는 파티션.

핫스팟 발생 위험 사례

  • 여러 센서에서 데이터를 받아오고, 타임스탬프를 key로 삼아 저장하는 경우.
    • 시간의 흐름에 따라 센서에서 값이 측정될 때마다 쓰기 연산이 특정 타임스탬프 범위에 몰리게 된다.
    • 즉 쓰기 연산이 한 파티션에 몰리게 되어, 해당 파티션에 과부하가 걸린다.
  • 해결방법
    • 타임스탬프가 아닌 값을 key로 사용한다.
    • 가령 타임스탬프 앞에 센서 이름을 붙여서, 파티셔닝의 기준에 영향을 줄 수 있다.
    • 이렇게 하면 동시에 작동하는 센서가 많을수록 쓰기 연산이 분산된다.

Partitioning by Hash of Key

키 해시값 기준 파티셔닝

  • 쏠림과 핫스팟 위험(risk of skew and hot spots) 때문에 많은 분산 데이터스토어는 키의 파티션을 정하는 데에 해시 함수를 사용한다.
  • 파티셔닝에 쓸 해시 함수가 암호학적으로 강력할 필요는 없다. 분산을 잘 해주면 된다.
  • 적절한 해시 함수를 구했다면, 각 파티션에 해시값 범위를 할당하고, 해시값이 파티션의 범위에 해당하는 모든 key를 해당 파티션에 할당하면 된다.
  • 범위 질의를 효율적으로 실행할 수 없다는 단점이 있다.
    • 몽고 DB에서는 범위 기반 샤딩 모드를 활성화하면 범위 질의가 모든 파티션에 전송된다.
    • 해시값 기준 파티셔닝 설정시 범위 질의가 지원되지 않는 DB도 있다.
  • 만약 동일한 key를 자주 읽고 쓰는 상황이 있다면 핫스팟을 피할 수 없다.
    • 가령, 유명한 영화배우가 트위터에 뭔가 흥미로운 일을 하면 많은 사람들의 관심이 쏠릴 것이므로 해당 영화배우의 ID를 기준으로 많은 데이터가 쌓일 것이다.
    • 이런 경우엔 각 키에 접두어/접미어로 임의의 숫자를 붙이는 꼼수가 있다. 두 자리 숫자만 잘 붙여도 100가지 경우의 수가 생긴다.
      • 물론 이렇게 하면 읽기를 실행할 때 추가 작업이 필요하므로 주의.

Secondary Index 문제

보조 색인이 있는 DB라면 다음 두 가지 방식의 파티셔닝이 널리 쓰인다.

  • document-based partitioning
  • term-based partitioning

document-based partitioning

  • local index: 문서 파티셔닝의 인덱스는 지역 색인(local index)이라고 부르기도 한다.
  • 경우에 따라 모든 파티션으로 질의를 보내서 그 결과를 모아야 할 수도 있다.

term-based partitioning

  • 모든 파티션의 데이터를 담당하는 전역 색인(global index)을 만들 수 있다.
  • 전역 색인을 한 노드에 저장하면, 해당 노드가 병목이 되므로 전역 색인도 파티셔닝한다.
    • term-partitioned: 특정 용어 기준으로 전역 색인을 범위별로 파티션에 할당하는 방법.
    • 물론 용어의 해시값을 기준으로 파티셔닝할 수도 있다.
  • 전역 색인의 갱신은 보통 비동기 방식으로 이루어진다.

rebalancing

재균형화: 한 노드가 담당하던 부하를 다른 노드로 옮기는 과정을 말한다.

재균형화는 다음을 목표로 한다.

  • 부하(읽기 쓰기 요청)가 노드들 사이에 균등하게 분배된다.
  • 재균형화 도중에도 DB는 읽기 쓰기 요청을 받을 수 있어야 한다.
  • 데이터가 필요 이상으로 많이 옮겨지면 안된다(작업 시간 최소화, 리소스 낭비 최소화).

다음과 같은 파티셔닝 방법에 따라 재균형화 전략은 달라진다.

  • Fixed number of partitions(파티션 개수 고정)
  • Dynamic partitioning(동적 파티셔닝)
  • Partitioning proportionally to nodes(노드 비례 파티셔닝)

Fixed number of partitions

  • 파티션을 노드 대수보다 많이 만들고, 각 노드에 여러 파티션을 할당하는 방법.
    • 예: 노드 10대인 클러스터에서 각 노드가 100개의 파티션을 할당받음.
    • 성능이 좋은 하드웨어가 섞여 있는 경우, 성능 좋은 노드가 더 많은 파티션을 할당받도록 할 수도 있다.
    • 이 방법을 쓰면 운영 편의를 위해 파티션 개수를 고정하게 되어, 처음 설정된 파티션 개수가 노드 대수의 최대치가 될 수 있으므로 주의한다.
    • 그렇다고 파티션 수가 너무 많으면 관리 오버헤드가 있으므로 주의한다.
    • 파티션이 너무 크면 재균형화 비용, 노드 장애 복구 비용이 크다.
    • 파티션이 너무 작으면 관리 오버헤드가 크다.
  • 클러스터에 노드가 추가되면 새 노드는 파티션이 다시 균일하게 분배될 때까지 기존 노드에서 파티션 몇 개를 뺏어오는 방식.
    • 이 방식에서 파티션은 노드에서 노드로 통째로 이동하게 된다.
    • 파티션을 복사하는 도중 읽기/쓰기가 발생하면 기존에 할당된 파티션을 사용한다.
  • 노드가 제거되면 추가될 때의 과정을 거꾸로 실행한다.

Dynamic partitioning

  • key 범위 파티셔닝을 쓰고 있다면, 파티션 경계와 개수가 고정되어 있는 것이 불편할 수 있다.
    • 특정 파티션으로 데이터가 몰릴 수 있다.
    • 수동으로 파티션 경계를 설정하는 것도 매우 성가신 일이다.
  • HBase, Resync DB 처럼 키 범위 파티셔닝을 사용하는 DB에서는 동적 파티셔닝을 쓴다.
    • 파티션 크기가 설정값을 넘어서면 파티션을 두 개로 쪼개는 방식.
    • 파티션 크기가 설정값 아래로 내려가면 다른 파티션과 합쳐지는 방식.
    • (B tree 최상위 레벨에서 실행되는 작업과 유사하다)
  • 동적 파티셔닝은 파티션 개수가 전체 데이터 용량에 맞춰 조정된다.

Partitioning proportionally to nodes

  • 파티션 개수가 노드 대수에 비례하게 하는 방법.
  • 즉, 노드당 할당되는 파티션 개수를 고정한다.
    • 노드 대수를 늘리면 파티션 수가 늘어나므로 파티션 하나하나의 크기는 작아진다.
    • 노드 대수가 변함이 없다면, 파티션 하나하나의 크기는 데이터 증가에 따라 점점 커진다.
  • 새 노드가 클러스터에 추가되면?
    • 고정된 개수의 파티션을 랜덤하게 선택해 반으로 쪼갠 다음, 쪼갠 절반을 새 노드에 할당한다.

참고문헌

  • 관계형 데이터베이스 실전 입문 / 오쿠노 미키야 저 / 성창규 역 / 위키북스 / 초판 2016년 07월 20일 / 원서 : 理論から學ぶデ-タベ-ス實踐入門 リレ-ショナルモデルによる效率的なSQL/奧野幹也
  • 데이터 중심 애플리케이션 설계 / 마틴 클레프만 저/정재부, 김영준, 이도경 역 / 위키북스 / 초판발행 2018년 04월 12일

주석

  1. 데이터 중심 애플리케이션 설계. 6장. 199쪽. 

  2. 데이터 중심 애플리케이션 설계. 6장. 199쪽.