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

Sharding?

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

문제점

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

From: MySQL 성능 최적화

샤딩(Sharding)은 더 많은 소스 호스트에서 동시에 더 많은 쓰기를 실행할 수 있도록 데이터를 각기 다른 더 작은 데이터베이스 클러스터로 분할하는 것을 의미합니다. 1

기능적 샤딩과 수평적 샤딩

Functional sharding means splitting specific tables that serve a specific business function into a dedicated cluster in order to manage separately this data set’s uptime, performance, or even access controls.

Horizontal sharding is when you have a data set that has grown past the size you can reliably serve out of a single cluster, so you split it into multiple clusters and serve the data from several nodes, relying on some look-up mechanism to locate the subset you need.

기능적 샤딩은 데이터 세트의 가동 시간, 성능 또는 엑세스 제어를 별도로 관리하기 위해 특정 비즈니스 기능을 수행하는 특정 테이블을 전용 클러스터로 분할하는 것을 의미합니다.

수평적 샤딩은 단일 클러스터에서 안정적으로 제공할 수 있는 크기 이상으로 데이터 세트가 증가한 경우, 이를 여러 클러스터로 분할하여 여러 노드의 데이터를 제공하고 필요한 하위 집합을 찾는 조회 메커니즘에 따라 데이터를 제공하는 것입니다. 2

이 책은 "기능적 샤딩(Functional sharding)"과 "수평적 샤딩(Horizontal sharding)"에 대해 "기능적 파티셔닝(Functional partitioning)"과 "데이터 샤딩(Data sharding)"으로 혼용한다.

기능적 파티셔닝 또는 업무 분담은 다른 노드를 다른 작업에 할당하는 것을 의미합니다. 사용자 레코드를 한 클러스터에 배치하고 청구서를 다른 클러스터에 두는 예를 들 수 있습니다. 이 접근방식을 사용하면 각 클러스터를 독립적으로 확장할 수 있습니다. 사용자 등록의 급증은 사용자 클러스터에 부담을 줄 수 있습니다. 별도의 시스템을 사용하면 청구 클러스터의 로드가 줄어 고객에게 청구가 가능합니다. 반대로 청구 주기가 매월 1일이면 사용자 등록에 영향을 미치지 않는다는 것을 알고 실행할 수 있습니다.

데이터 샤딩은 오늘날의 초대형 MySQL 애플리케이션을 확장하기 위한 가장 보편적이고 성공적인 접근 방식입니다. 데이터를 더 작은 조각 또는 샤드로 분할하고 다른 노드에 저장함으로써 데이터를 샤딩합니다.

대부분의 애플리케이션은 샤딩이 필요한 데이터(일반적으로 매우 커질 데이터 세트의 일부)만 샤딩합니다. 블로그 서비스를 구축한다고 가정합시다. 1,000만 명의 사용자가 있을 것으로 예상 되는 경우 모든 사용자(또는 해당 사용자의 활성 하위 집합)를 메모리에 완전히 저장할 수 있으므로 사용자 등록정보를 분할할 필요가 없습니다. 반면에 5억 명의 사용자가 예상된다면 이 데이터를 샤딩해야 합니다. 게시물이나 댓글과 같은 사용자가 생성하는 콘텐츠는 어느 경우든 샤딩이 필요할 것이 거의 확실합니다. 왜냐하면 이러한 레코드는 훨씬 크고 더 많기 때문입니다.

대규모 애플리케이션에는 다르게 분할할 수 있는 여러 논리적 데이터 세트가 있을 수 있습니다. 다른 서버 세트에 저장할 수 있지만 꼭 그럴 필요는 없습니다. 액세스 방법에 따라 동일한 데이터를 다양한 방법으로 샤딩할 수도 있습니다. 3

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

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

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

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

여기서 말하는 파티션은 몽고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

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

함께 읽기

참고문헌

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

주석

  1. MySQL 성능 최적화. 11장. 339쪽. 

  2. MySQL 성능 최적화. 2장. 41쪽. 

  3. MySQL 성능 최적화. 11장. 340쪽. 

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

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