책 정리와 리뷰

[데이터중심 어플리케이션 설계] 6장 정리

maruoov 2023. 7. 22. 23:31

데이터가 매우 크거나 처리량이 높다면 복제본 만으로는 부족하고 데이터를 쪼갤 필요가 있다.
이를 파티션 혹은 샤딩 이라 한다.
파티셔닝을 하는 이유는 확장성이다. 클러스터에서 파티션은 다른 노드에[ 저장될수 있고, 질의 부하를 분산할 수 있다.

파티셔닝과 복제

보통 복제와 파티셔닝을 함께 적용해 각 파티션의 복사본을 여러 노드에 저장한다.
데이터가 한 파티션에 속하더라도, 이를 여러 다른 노드에도 저장해 내결함성을 보장할 수 있다.
파티셔닝의 목적은 데이터와 질의 부하를 고르게 분산시키는 것이다.
파티셔닝이 잘 이루어지지 않으면 특정 파티션이 데이터가 많거나 질의를 많이 받게 되는데, 이를 쏠렸다 (skewed)라 한다. 
이런 경우에 파티셔닝 효과가 매우 떨어지고, 불균형하게 부하가 높은 파티션을 핫스팟이라 한다.
그럼 파티셔닝을 어떤 기준으로 할수 있을까?

키 범위 기준 파티셔닝

각 파티션에 연속된 범위의 키를 할당하는 방법이 있다.
각 범위 사이 경계를 알면 어떤 키가 어떤 파티션에 속하는지 알 수 있다.
키 범위 크기가 동일할 필요는 없고, 파티션 경계를 데이터에 맞춰 조정해야 데이터가 고르게 분산된다

하지만 키 범위 기준 파티셔닝은 특정한 접근 패턴이 핫스팟을 유발하는 단점이 있다.
만약 키가 타임스탬프라면, 파티션은 시간 범위로 나눠질텐데, 특정 시간대의 데이터를 조회 했을때 특정 파티션에만 읽기 요청이 가고,
실시간으로 데이터가 기록되므로 쓰기 요청도 동일한 파티션으로 가게 된다.

키 해시값 기준 파티셔닝

쏠림과 핫스팟을 회피하기 위해 많은 분산 데이터저장소는 키의 파티션을 정하는 데 해시 함수를 사용한다.
좋은 해시 함수는 데이터를 균일하게 분산되게 한다.

하지만 파티셔닝 키에 해시값을 적용하면 범위 질의를 효율적으로 할수 있는 키 범위 파티셔닝의 장점을 잃어 버린다.
카산드라db 같은 경우 위의 단점을 보완하기 위해, 여러 칼럼을 포함하는 복합 기본키를 사용할 수 있다.
복합 키 첫번째 칼럼에 대해서는 범위 질의를 쓸수 없지만, 첫 번째 칼럼에 고정된 값을 지정하면 다른 칼럼에 대해선 범위 스캔을 실행할 수 있다.

 

쏠린 작업부하와 핫스팟 완화

키를 해싱하여 파티션을 정하면 핫스팟을 줄이는데 도움이 된다. 하지만 핫스팟을 완전히 제거할 순 없다.
대부분 데이터저장소가 쏠린 작업부하를 자동으로 보정하지 못하므로 애플리케이션에서 쏠림을 완화해야 한다.
간단한 해결책은 각 키 앞뒤로 임의의 숫자를 붙이는 것이다.
하지만 이 방법은 읽기 요청이 들어오면 추작업인 작업이 필요해진다.

 

파티셔닝과 보조 색인

레코드를 유일하게 식별하는 용도가 아닌 특정한 값이 있는 항목을 검색하기 위한 수단인 보조색인이 연관되면 상황은 복잡해진다.
보조색인은 관계형 데이터베이스의 핵심 요소이며, 문서 데이터베이스에서도 흔하다.

보조 색인은 파티션에 깔끔하게 대응되지 않는 문제점이 있다. 널리 쓰이는 두 가지 방식을 알아보자.

 

문서 기준 보조 색인 파티셔닝

각 문서에는 문서ID 라 부르는 고유 ID 가 있고, 문서 ID 기준으로 파티셔닝 된다.
특정 필드로 필터링 할수 있으려면, 해당 필드로 보조 색인을 만들어야 한다.
색인을 선언하면, 문서가 생성될때 자동으로 색인이 생성된다.

각 파티션은 완전히 독립적으로 동작한다.
각 파티션은 자신의 보조색인을 유지하며, 해당 파티션 내에 속하는 문서만 담당한다.
다른 파티션에 어떤 데이터가 저장되는지 신경쓰지 않고
문서 추가,삭제,갱신 등 쓰기 작업시에 쓰려고 하는 문서를 포함하는 파티션만 다루면 된다.
문서 파티셔닝 색인은 지역 색인이라고도 한다.

문서 기준 파티셔닝 시에 특정 필드로 필터링 할때 한 파티션 내에 모든 데이터가 존재하지 않을 수 있다.
그래서 모든 파티션으로 질의를 보내 얻은 결과를 모아야 한다.
이런 질의 방식을 스캐터/개더라고도 한다.
여러 파티션에 질의를 병렬 실행 하더라도, 꼬리 지연 시간 증폭이 발생하기 쉽다.

 

용어 기준 보조 색인 파티셔닝

각 파티션이 지역 색인을 갖게 하는 대신, 모든 파티션의 데이터를 담당하는 전역 색인을 만들수도 있다.
그러나 한 노드에만 색인을 저장할순 없기 때문에 전역 색인도 파티셔닝이 필요하다.

위 그림을 보면 color:a-r 은 파티션0에, color:s-z 는 파티션1에 저장되고 있다.
문서 파티셔닝에 비해 읽기 작업이 효율적이다.
모든 파티션에 스캐터/개더를 실행할 필요 없이 원하는 용어를 포함하는 파티션으로만 요청을 보낼수 있다.
하지만 전역 색인은 쓰기가 느리고 복잡하다는 단점이 있다.

 

파티션 재균형화

데이터는 시간이 지나면 변화가 생긴다.
변화가 생기면 데이터와 요청이 한 노드에서 다른 노드로 옮겨져야 한다.
클러스터에서 한 노드가 담당하던 부하를 다른 노드로 옮기는 과정을 재균형화라 한다.

재균형화가 실행될때 다음 사항을 만족할 것으로 기대한다.

  • 부하가 클러스터 내에 있는 노드들 사이에 균등하게 분배돼야 한다
  • 재균형화 도중에도 읽기 쓰기 요청을 처리해야 한다
  • 빨리 실행되고 네트워크, 디스크IO 부하를 최소화 할수 있도록 데이터가 필요 이상으로 옮겨져선 안된다.

재균형화 전략

재균형화 전략을 몇가지 알아보자

해시값에 modular N 연산 실행

이 방법은 사용하면 안된다. 
노드 추가/제거시에 대부분의 키가 옮겨져야 하는 문제가 발생한다.
데이터를 필요 이상으로 이동하지 않는 방법이 필요하다.

파티션 개수 고정

파티션을 노드 대수보다 많이 만들고 각 노드에 여러 파티션을 할당한다.
클러스터에 노드가 추가되면, 새 노드는 파티션 재분배 전까지 기존 노드들에서 파티션 몇개를 뺏어올 수 있다.

파티션은 통째로 이동만 하고, 전체 파티션 개수나 할당된 키도 변경되지 않는다.

이 방식을 사용할때 보통 처음 파티션 개수가 정해지면 이 값은 고정이고 이후에 변하지 않는다.
파티션이 너무 크면 리밸런싱, 장애 복구 비용이 크고 너무 작으면 오버헤드가 너무 커진다.

동적 파티셔닝

키 범위 파티셔닝을 이용하는 데이터베이스의 경우 파티션을 동적으로 만든다.
파티션 크기가 설정된 값을 넘어서면 파티션을 쪼개 원래 파티션의 데이터를 나눈다.
반대로 데이터 삭제가 많이 일어나 파티션 크기가 작아지면 다른 파티션과 합쳐질 수 있다.

파티션 개수가 데이터 용량에 맞춰 조정된다는 장점이 있다.

노드 비례 파티셔닝

파티션 개수가 노드 대수에 비례하게 할 수 있다.
노드당 할당되는 파티션 개수를 고정한다.
노드 대수가 변함 없는 동안 개별 파티션 크기는 데이터 크기에 비례해 증가하지만, 노드를 늘리면 파티션 크기는 다시 작아진다.
일반적으로 데이터 크기가 거질수록 노드도 많이 필요해지므로 개별 파티션 크기가 안정적으로 유지된다.

 

요청 라우팅

데이터를 여러 노드에 파티셔닝 했는데, 어떤 데이터에 접근할때 어느 노드로 접근해야 하는지 어떻게 알수 있을까?
파티션이 재균형화 되면 노드에 할당되는 파티션도 바뀐다.

이는 데이터베이스에만 국한되지 않은 서비스 찾기문제의 일종이다.

이에 대한 몇가지 접근법이 있다.

  • 아무 노드에나 접속하고, 해당 노드에 데이터가 있다면 직접 처리, 그렇지 않으면 올바른 노드로 전달하여 응답을 받고 클라이언트에 전달한다
  • 모든 요청을 라우팅 계층으로 먼저 보낸다. 라우팅 계층은 요청을 처리할 노드를 알아내고 해당 노드로 요청을 전달한다.
    라우팅 계층은 파티션 인지 로드밸런서로만 동작한다
  • 클라이언트가 파티셔닝 방법과 어떤 노드에 할당됐는지를 알고 있게 한다.

모든 경우 핵심 문제는 노드에 할당된 파티션의 변경 사항을 어떻게 아는지이다.
이 문제는 모든 곳에서 정보가 이일치해야 하므로 다루기 어렵다.

많은 분산 데이터시스템은 클러스터 메타데이터를 추적하기 위해 주키퍼 같은 코디네이션 서비스를 사용한다.