Gidhub BE Developer

[데이터 중심 애플리케이션 설계] 6장. 파티셔닝 : 3. 파티션 재균형화

2022-05-09
goodGid

이 글은 내용을 토대로 작성하였습니다.

목차

  1. 키-값 데이터 파티셔닝

  2. 파티셔닝과 보조 인덱스

  3. 파티션 재균형화

  4. 요청 라우팅


Goal

  • 파티셔닝 글 시리즈에서는 다음과 같은 부분들을 살펴본다.
  1. 대용량 데이터셋을 파티셔닝하는 방법

  2. 인덱싱과 파티셔닝의 상호작용 방법

  3. 클러스터에 노드 추가/삭제 시 재균형화 과정

  4. DB가 어떻게 요청을 올바른 파티션에 전달 및 질의를 하는지 그 실행 과정에 대학 학습


파티션 재균형화

  • 운영을 하다 보면 DB에 변화가 생긴다.
질의 처리량이 증가해서 늘어난 부하를 처리하기 위해 CPU를 추가하고 싶다.
데이터셋 크기가 증가해서 데이터셋 저장에 사용할 디스크와 램을 추가하고 싶다.
장비에 장애가 발생해서 그 장비가 담당하던 역할을 다른 장비가 넘겨받아야 한다.
  • 이런 변화가 생기면 데이터와 요청이 한 노드에서 다른 노드로 옮겨져야 한다.

    클러스터에서 한 노드가 담당하던 부하를 다른 노드로 옮기는 과정을 재균형화(Rebalancing)라고 한다.


재균형화 최소 조건

  • 재균형화 후 부하가 클러스터 내에 있는 노드들 사이에 균등하게 분배돼야 한다.

  • 재균형화 도중에도 DB는 R/W 요청을 받아들여야 한다.

  • 재균형화가 빨리 실행되고 네트워크와 디스크 I/O 부하를 최소화할 수 있도록

    노드들 사이에 데이터가 필요 이상으로 옮겨져서는 안 된다.


재균형화 전략

해시값에 모드 N 연산

  • 해시값에 모드 N 연산을 사용하여

    그 나머지 값을 활용해 파티션을 노드에 할당하는 방법은 사용해선 안 된다.

  • 모드 N 방식의 문제는

    노드 개수 N이 바뀌면 대부분 키가 노드 사이에 옮겨져야 한다는 점이다.

  • 예를 들어 hash(key) = 123456이라고 하자.

    처음에 노드가 10대라면 이 키는 노드 6에 할당된다.

    ( 123456 % 10 = 6 )

  • 노드가 11대로 늘어나면 이 키는 노드 3으로 옮겨져야 하고

    ( 123456 % 11 = 3 )

    노드가 12대로 늘어나면 이 키는 노드 0으로 옮겨져야 한다.

    ( 123456 % 12 = 0 )

  • 이렇게 키가 자주 이동하면 재균형화 비용이 지나치게 커진다.

    즉 데이터를 필요 이상으로 이동하지 않는 방법이 필요하다.


파티션 개수 고정

  • 다행스럽게도 간단한 해결책이 있다.

    파티션을 노드 대수보다 많이 만들고

    각 노드에 여러 파티션을 할당하는 것이다.

  • 예를 들어 노드 10대로 구성된 클러스터에서 실행되는 DB는

    처음부터 파티션을 1,000개로 쪼개서

    각 노드마다 약 100개의 파티션을 할당할 수 있다.

  • 이런 재균형화 방법은 리악, 엘라스틱서치, 카우치베이스, 볼드모트에서 사용된다.


클러스터에 노드 추가/제거 시

  • 클러스터에 노드가 추가되면

    새 노드는 파티션이 다시 균일하게 분배될 때까지

    기존 노드에서 파티션 몇 개를 뺏어올 수 있다.

  • 노드가 제거되면 이 과정이 반대로 실행된다.

  • 파티션은 노드 사이에서 통째로 이동하기만 한다.

    파티션 개수는 바뀌지 않고 파티션에 할당된 키도 변경되지 않는다.

  • 유일한 변화는 노드에 어떤 파티션이 할당되는가 뿐이다.

  • 파티션 할당 변경은 즉시 반영되지 않고

    네트워크를 통해 대량의 데이터를 전송해야 하므로 시간이 걸린다.

    따라서 데이터 전송이 진행 중인 동안에 R/W 요청은 기존에 할당된 파티션을 사용한다.


주의할 점

  • 이 방식을 사용할 때는

    보통 DB가 처음 구축될 때

    파티션 개수가 고정되고 이후에 변하지 않음을 가정한다.

  • 이론적으로는 파티션을 쪼개거나 합치는 게 가능하지만

    파티션 개수가 고정되면 운영이 단순해지므로

    고정 파티션을 사용하는 DB는 파티션 분할을 지원하지 않는 경우가 많다.

  • 따라서 처음 설정된 파티션 개수가

    사용 가능한 노드 대수의 최대치가 되므로

    미래에 증가할 것을 예상하여 적당한 값으로 선택해야 한다.

  • 그러나 개별 파티션도 관리 오버헤드가 있으므로

    너무 큰 수를 선택하면 역효과를 낳을 수 있다.


정리

  • 전체 데이터셋의 크기 변동이 심하다면 적절한 파티션 개수를 정하기 어렵다.

  • 예를 들어 처음에는 데이터셋이 작지만 시간이 지나면서 훨씬 커질 수 있다.

  • 각 파티션에는 전체 데이터의 고정된 비율이 포함되므로

    개별 파티션 크기는 클러스터의 전체 데이터 크기에 비례해서 증가한다.

    파티션이 너무 크면 재균형화를 실행할 때와 노드 장애로부터 복구할 때 비용이 크다.

  • 그러나 파티션이 너무 작으면 오버헤드가 너무 커진다.

    파티션 크기가 너무 크지도 너무 작지도 않고 적당해야 성능이 가장 좋지만

    파티션 개수는 고정돼 있고 데이터셋 크기는 변한다면 적절한 크기를 정하기 어려울 수 있다.


동적 파티셔닝

  • 키 범위 파티셔닝을 사용하는 DB에서는

    파티션 경계와 개수가 고정돼 있으면 매우 불편하다.

  • 왜냐하면 파티션 경계를 잘못 지정하면

    모든 데이터가 한 파티션에 저장되고 나머지 파티션은 빌 수도 있기 때문이다.

  • 이런 이유로 HBase처럼 키 범위 파티셔닝을 사용하는 DB에서는

    파티션을 동적으로 만든다.


동적 파티셔닝 동작 과정

  • 파티션 크기가 설정된 값을 넘어서면

    파티션을 2개로 쪼개고

    기존 파티션이 가진 데이터도 절반씩 나눠 갖게 한다.

  • 반대로 데이터가 많이 삭제되어 파티션 크기가 임곗값 아래로 떨어지면

    인접한 파티션과 합쳐질 수 있다.


노드와 파티션간의 관계

  • 파티션 개수가 고정된 경우와 마찬가지로

    각 파티션은 노드 하나에 할당되고

    각 노드는 여러 파티션을 담당할 수 있다.

  • 큰 파티션이 쪼개진 후 부하의 균형을 맞추기 위해

    분할된 파티션 중 하나가 다른 노드로 이동될 수 있다.

  • HBase의 경우 기분 분산 파일 시스템인 HDFS를 통해 파티션 파일이 전송된다.


장점

  • 동적 파티셔닝은 파티션 개수가 전체 데이터 용량에 맞춰 조정된다는 이점이 있다.

    데이터양이 적으면 파티션 개수가 적어도 되므로 오버헤드도 작다.

    데이터 양이 많아지면 개별 파티션의 크기는 설정된 최대치로 제한된다.


함정

  • 데이터가 비어있는 DB는 파티션 경계를 어디로 정해야 하는지에 관한 사전 정보가 없으므로

    시작할 때는 파티션이 1개라는 함정이 있다.

  • 데이터 셋이 작아서

    첫 번째 파티션이 분할될 정도로 데이터가 쌓이기 전까지는

    모든 쓰기 요청이 하나의 노드에서 실행되고 다른 노드들은 유휴 상태에 머물게 된다.

  • 이런 문제를 해결하기 위해

    HBase와 몽고DB에서는 빈 DB에

    초기 파티션 집합을 설정할 수 있는 기능을 제공하고

    이러한 개념을 사전 분할(Pre-Splitting)이라고 부른다.


참고

  • 동적 파티셔닝은 키 범위 파티셔닝에만 적합한 것은 아니고

    해시 파티셔닝에도 똑같이 사용될 수 있다.

  • 몽고DB는 2.4 버전부터 키 범위 파티셔닝과 해시 파티셔닝을 모두 지원하고

    두 경우 모두 파티션을 동적으로 나눈다.


노드 비례 파티셔닝

  • 동적 파티셔닝에서는 파티션 분할과 병합을 통해

    개별 파티션 크기가 어떤 고정된 최솟값과 최댓값 사이에 유지되게 하므로

    파티션 개수가 데이터셋 크기에 비례한다.

  • 반면 파티션 개수를 고정하면 개별 파티션의 크기가 데이터셋 크기에 비례한다.

    (= 데이터가 많아지면 해당 파티션의 크기는 커진다.)

    두 경우 모두 파티션 개수는 노드 대수와 독립적이다.


파티션과 노드 대수의 관계

  • 파티션 개수가 노드 대수에 비례하게 한다.

    즉 노드당 할당되는 파티션 개수를 고정한다.

  • 이 경우 노드 대수가 변함없는 동안은

    개별 파티션 크기가 데이터셋 크기에 비례해서 증가하지만

    노드 대수를 늘리면 파티션 크기는 다시 작아진다.

  • 일반적으로 데이터 용량이 클수록 데이터를 저장할 노드도 많이 필요하므로

    이 방법을 쓰면 개별 파티션 크기도 상당히 안정적으로 유지된다.


새 노드가 클러스터에 추가될 경우

  • 새 노드가 클러스터에 추가되면

    고정된 개수의 파티션을 무작위로 선택해 분할하여

    절반은 그대로 두고 다른 절반은 새 노드에 할당한다.

  • 파티션을 랜덤으로 선택해 균등하지 않은 분할이 생길 수 있지만

    여러 파티션에 대해 평균적으로 보면

    새 노드는 기존 노드들이 담당하던 부하에서 균등한 몫을 할당받게 된다.

    // 카산드라 3.0에는 불균등한 분할을 회피할 수 있는 대안적인 재균형화 알고리즘이 추가됐다.


운영 관점

자동 vs 수동 재균형화

  • 재균형화는 자동으로 실행될까? 아니면 수동으로 실행해야 할까?

  • 완전 자동 재균형화와 완전 수동 재균형화 사이에는 중간 지점이 있다.

  • 예를 들어 카우치베이스, 리악, 볼드모트는

    자동으로 파티션 할당을 제안하지만 반영되려면 관리자가 확정해야 한다.


완전 자동 재균형화

  • 완전 자동 재균형화는 일상적인 유지보수에 손이 덜 가므로 편리할 수 있다.

    하지만 예측하기 어렵다.

  • 재균형화는 요청 경로를 재설정해야 하고

    대량의 데이터를 노드 사이에 이동해야 하므로 비용이 큰 연산이다.

  • 주의 깊게 처리하지 않으면 네트워크나 노드에 과부하가 걸릴 수 있고

    재균형화가 진행 중인 동안에 실행되는 다른 요청의 성능이 저하될 수 있다.


최악의 상황

  • 이런 자동화는 자동 장애 감지와 조합되면 위험해질 수도 있다.

  • 예를 들어 1대 노드에 과부하가 걸려

    일시적으로 요청에 대한 응답이 느려졌다고 하자.

  • 다른 노드들은 과부하 걸린 노드가 죽었다고 간주하고

    해당 노드로부터 부하를 다른 곳으로 옮기기 위해

    자동으로 클러스터를 재균형화하려고 한다.

  • 그러면 과부하 걸린 노드 + 다른 노드들 + 네트워크에 부하를 더해서

    상황이 더 안 좋아지고 연쇄 장애가 발생할 가능성도 있다.


책 글쓴이의 생각

  • 이런 이유로 재균형화 과정에서 사람이 개입하는 게 좋을 수 있다.

  • 완전 자동 처리보다는 느릴 수 있지만

    운영상 예상치 못한 일을 방지하는 데 도움이 될 수 있기 때문이다.


Refernece


Recommend

Index