ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 6장 - 파티셔닝
    CS/데이터 중심 애플리케이션 설계 요약 2022. 12. 10. 00:01

    복제의 한계

    데이터셋이 매우 크거나 질의 처리량이 매우 높다면 복제만으로는 부족하고 데이터를 파티션으로 쪼갤 필요가 있습니다.

    이 작업을 샤딩이라고 합니다.

     

    파티션을 나눌 때는 보통 각 데이터 단위(레코드, 로우, 문서)가 하나의 파티션에 속하게 됩니다.

    각 파티션은 그 자체로 작은 데이터베이스입니다.

     

    파티셔닝과 복제

    보통 복제와 파티셔닝을 함께 적용해 각 파티션의 복사본을 여러 노드에 저장합니다.

    이를 통해 내결함성을 보장할 수 있습니다.

     

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

    대량의 데이터를 어떻게 파티셔닝해야 할까요?

    어떤 레코드를 어떤 노드에 어떻게 저장해야 할까요?

     

    파티셔닝의 목적은 데이터와 질의 부하를 노드 사이에 고르게 분산하는 것입니다.

    모든 노드가 동일한 분량의 담당한다고 가정할 때 10대의 노드를 사용하면 한 대를 사용할 때보다 이론상으로 10배의 데이터를 저장하고 10배의 읽기, 쓰기 요청을 처리할 수 있습니다.

     

    이때 파티셔닝이 적절하기 이루어지지 않으면 아무리 여러 노드를 사용하더라도 의미가 없습니다.

    이렇게 불균형하게 부하가 높은 파티션을 핫스팟이라 합니다.

     

    키 범위 기준 파티셔닝

    이런 핫스팟을 피하는 가장 간단한 방법은 레코드를 노드에 무작위로 할당하면 됩니다.

    하지만 그러면 어떤 데이터가 어떤 노드에 저장되어있는지 확인할 수 없습니다.

     

    따라서 단순하게 임의의 키값을 지정하여 0~100, 100~200, 200~300과 같이 연속된 범위의 키까지 할당하는 방법이 키-값 데이터 파티셔닝입니다.

     

     

    키의 해시값 기준 파티셔닝

    적절한 해쉬 함수를 활용하여 키 범위 대신 각 파티션에 해쉬값 범위를 할당하고 해시값이 파티션의 범위에 속하는 모든 키를 그 파티션에 할당하면 됩니다.

     

     

    이렇게 되면 범위 질의를 효율적으로 실행할 수 있는 능력이 떨어집니다.

    전에는 인접했던 키들이 모든 파티션에 흩어져 정렬 순서가 유지되지 않습니다.

     

    카산드라의 경우에는 두 가지 파티셔닝 전략을 혼합하여 사용함으로써 복합 기본키를 통해 범위 스캔을 효율적으로 실행할 수 있습니다.

     

    핫스팟 완화

    핫스팟을 완벽하게 제거할 수 없는 경우도 있습니다.

     

    요청이 많이 쏠리는 상황을 목격하였을 때 각 키의 시작이나 끝에 임의의 숫자를 붙여서 해결합니다.

    이렇게 그 키들은 다른 파티션으로 분산될 수 있습니다.

     

    하지만 읽기를 수행할 때 추가적으로 작업이 필요해집니다.

    키를 기준으로 분산된 파티션들을 읽어와 데이터를 조합해야 합니다.

     

    파티셔닝과 보조 색인

    예를 들어 중고차를 파는 웹사이트가 있습니다.

    문서 ID라고 부르는 고유 ID가 존재하고 데이터베이스를 문서 ID를 기준으로 파티셔닝합니다.

     

    사용자들이 차를 검색할 때 색상과 제조사로 필터딩할 수 있게 하려면 color와 make에 보조 색인을 만들어야 합니다.

     

    이렇게 되면 각 파티션은 자동으로 color:red 색인 항목에 해당하는 문서 ID 목록에 추가합니다.

     

    이해를 흔히 돕고자 우리가 흔히 아는 방식을 예시로 들면 다음과 같습니다.

    List<String> colorRedCars1 = new ArrayList<>();
    colorRedCars.add(문서ID);

     

    colorRedCars1 리스트를 하나의 파티션으로 보면 됩니다.

     

    이제 빨간 차를 찾고 싶다면 colorRedCars1 , colorRedCars2, .... , colorRedCarsN과 같은 파티션의 보조 색인을 조회하여 모두 조합하면 됩니다.

     

    모든 파티션에게 질의를 보내야 하기 때문에 큰 비용이 들 수 있습니다.

     

     

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

    각 파티션이 자신만의 보조 색인을 갖게 하는 대신, 모든 파티션의 데이터를 담당하는 전역 색인을 만들 수 있습니다.

    예를 들어 색깔 색인 a~r까지의 글자로 시작하는 색깔은 파티션 0에, s부터 z까지의 글자로 시작하는 색깔은 파티션 1에 저장되도록 파티셔닝합니다.

     

    용어 자체를 사용할 수 있으며 용어의 해시값을 사용할 수도 있습니다.

    이때는 읽기가 효율적이지만 쓰기에 여러 파티션에 영향을 주기 때문에 복잡해집니다.

     

    보통 전역 보조 색인은 대게 비동기로 갱신되며 시간은 1초도 소요되지 않지만 인프라에 결함이 발생하면 반영 지연 시간이 더 길어질 수 있습니다.

     

    파티션 재균형화

    시간이 지나면 데이터베이스에 변화가 발생합니다.

    - 질의 처리량이 증가하여 늘어난 부하를 처리하기 위해 CPU를 더 추가하고 싶다.

    - 데이터셋 크기가 증가해서 데이터셋 저장에 사용할 디스크와 램을 추가하고 싶다.

    - 장비애 장애가 발생해서 그 장비가 담당하던 역할을 다른 장비가 넘겨받아야 한다.

     

    이렇게 되면 데이터의 요청이 한 노드에서 다른 노드로 옮겨져야 합니다.

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

     

    재균형화가 이루어질 때 보통 만족시킬 것으로 기대되는 최소 요구사항이 존재합니다.

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

    - 재균형화 도중에도 DB는 읽기 쓰기  요청을 받는다.

    - 재균형화가 빨리 실행되고 네트워크와 디스크 I/O 부하를 최소화할 수 있도록 노드들 사이에 데이터가 필요 이상으로 옮겨져서는 안 된다.

     

    파티션 개수 고정

    파티션을 노드 대수보다 많이 만들고 각 노드에 여러 파티션을 할당합니다.

    예를 들어 1,000개의 파티션으로 쪼개고 각 노드마다 약 100개의 파티션을 할당할 수 있습니다.

     

    이제 클러스터에 노드가 추가되면 새 노드는 파티션이 다시 균일하게 분배될 때까지 기존 노드에서 파티션 몇 개를 뺏어올 수 있습니다.

     

    이제 파티션은 노드 사이에서 통째로 이동만 하면 됩니다.

     

    이 방식을 사용할 때는 DB를 처음 구축할 때 파티션 개수가 고정되고 이후로 변하지 않습니다.

    따라서 적절한 파티션의 개수를 정하는 것이 가장 어려운 문제입니다.

     

    동적 파티셔닝

    키 범위 파티셔닝을 이용할 때 파티션 경계와 개수가 고정되어 있다면 매우 불편합니다.

    경계를 잘못 지정하면 모든 데이터가 한 파티션에 저장됩니다.

     

    이런 이유로 HBase나 리싱크DB처럼 키 범위 파티셔닝을 사용하는 데이터베이스에서는 파티션을 동적으로 만듭니다.

    파티션 크기가 설정된 값을 넘어가면 파티션을 두 개로 쪼개 각각에 원래 파티션의 절반 정도의 데이터를 포함하게 합니다.

    반대로 데이터가 많이 삭제되어 파티션 크기가 임계값 아래로 떨어지면 인접한 파티션과 합쳐질 수 있습니다.

    B트리의 최상위 레벨에서 실행되는 작업과 유사합니다.

     

    이런 방법은 해시 파티셔닝에도 똑같이 사용될 수 있습니다.

    몽고 DB는 2.4 버전부터 키 범위 파티셔닝과 해시 파티셔닝을 모드 지원하고 두 경우 모드 파티션을 동적으로 분할합니다.

     

    노드 비례 파티셔닝

    동적 파티셔닝은 파티션의 개수가 데이터셋의 크기에 비례합니다.

    하지만 노드 비례 파티셔닝은 노드 대수에 비례하여 파티션 개수를 지정합니다.

     

    일반적으로 데이터 용량이 클수록 데이터를 저장할 노드도 많이 필요하므로 이 방법을 쓰면 개별 파티션 크기도 상당히 안정적으로 유지됩니다.

     

    새 노드가 클러스터에 추가되면 고정된 개수의 파티션을 무작위로 선택해 분할하고 각 분할된 파티션의 절반은 그대로 두고 다른 절반은 새 노드에 할당합니다.

     

    운영 : 자동과 수동

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

    자동과 수동 사이의 중간지점에 있습니다.

     

    카우치베이스 ,리악, 볼드모트는 자동으로 파티션 할당을 제안하지만 반영되려면 관리자가 확정해야 합니다.

    자동은 유지보수에 손이 덜 가지만 예측하기 어렵습니다.

    또한 대량의 데이터 노드 사이 이동이 일어날 수 있어 네트워크나 노드에 과부화가 걸릴 수 있습니다.

     

    이런 자동화과 자동 장애 감지가 조합되면 위험해질 수 있습니다.

    노드 한대에 과부하가 걸려 느려지고, 다른 노드들은 과부화된 노드가 죽었다고 간주하여 새로운 노드로 재균형화하려 합니다.

    이러면 과부화 걸린 노드, 다른 노드, 네트워크에 부하를 더해 상황이 악화되고 연쇄 장애가 발생할 수 있습니다.

     

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

     

    요청 라우팅

    데이터셋을 여러 장비에서 실행되는 여러 노드에 파티셔닝할 수 있습니다.

    하지만 클라이언트에서 요청을 보내려고 할 때 어느 노드로 접속해야 하는지 어떻게 알 수 있을까요?

    파티션이 재균형화되면서 노드에 할당되는 파티션이 계속 바뀝니다.

     

    누군가 "foo"키를 읽거나 쓰려면 어떤 IP 주소와 포트 번호로 접속해야 할까? 라는 질문에 답할 수 있도록 파티션 할당 변경을 훤히 알고 있어야 합니다.

     

    이 문제는 DB에 국한되지 않은 서비스 찾기(service discovery)의 일종입니다.

    네트워크를 통해 접속되는 소프트웨어라면 특히 고가용성을 지탱하는 서비스라면 모두 이 문제가 있습니다.

    여러 회사에서 자체 service discovery를 개발했고 그중 다수가 오픈소스로 공개되었습니다.

     

     

    상위 수준에서 보면 이 문제는 몇 가리 다른 접근법이 있습니다.

    1. 무작위로 아무 노드에 접근하고 요청을 적용할 파티션이 있다면 직접 처리하고 그렇지 않으면 올바른 노드로 전달

     

    2. 클라이언트의 모든 요청을 라우팅 계층에 보내고 라우팅 계층에서 요청을 처리할 노드를 알아내어 노드로 요청을 전달(라우팅 계층 = 로드밸런서로 동작)

     

    3. 클라이언트가 파티셔닝 방법과 파티션이 어떤 노드에 할당되었는지를 알고 있게 한다. 이 경우 클라이언트 중개자는 중간계층없이 올바른 노드로 직접 접속할 수 있습니다.

     

     

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

    각 노드는 주키퍼에 자신을 등록하고 주키퍼는 파티션과 노드 사이의 신뢰성 있는 할당 정보를 관리합니다.

     

    HBase, 솔라클라우드, 카프카도 파티션 할당을 추적하는데 주키퍼를 사용합니다.

    몽고DB도 아키텍처는 비슷하지만 자체적인 설정서버 구현에 의존하고 몽고스 데몬을 라우팅 계층으로 사용합니다.

     

    병렬 질의 실행

    지금까지는 단일 키를 읽거나 쓰는 매우 간단한 질의에 대해서만 설명했습니다.

     

    분석용으로 자주 사용되는 대규모 병렬 처리 관계형 데이터베이스 제품은 훨씬 더 복잡한 종류의 질의를 지원합니다.

     

    전형적인 데이터 웨어하우스 질의는 조인, 필터링, 그룹화, 집계 연ㅅ나을 몇 개 포함합니다.

     

    복잡한 질의를 여러 싱행 단계와 파티션으로 분해하며 이들 중 다수는 데이터베이스 클러스터 내의 서로 다른 노드에서 병렬적으로 실행될 수 있습니다.

     

    정리

    대용량 데이터셋을 작은 데이터셋으로 파티셔닝하는 다양한 방법에 대해 알아보았습니다.

     

    파티셔닝의 목적은 핫스팟이 생기지 않게 하면서 데이터와 질의 부하를 여러 장비에 균일하게 분배하는 것입니다.

     

    그러기 위해선 데이터에 적합한 파티셔닝 방식을 선택해야 하고 클러스터에 노드가 추가되거나 클러스터에 노드가 제거될 때 파티션 재균형화를 실행해야 합니다.

     

    - 키 범위 파티셔닝

    - 해시 파티셔닝

     

    - 문서 파티셔닝 색인(보조 색인)

    - 용어 파티셔닝 색인(전역 색인)

     

     

    더 나아가서

    설계상 모든 파티션은 대부분 독립적으로 동작합니다.

    따라서 파티셔닝된 DB는 여러 장비로 확장될 수 있습니다.

    그러나 여러 파티션에 기록해야 하는 연산은 어렵습니다.

    한 파티션에는 쓰기 성공했지만 한 파티션에는 쓰기 실패하면 어떻게 될까요?

    이어지는 장에서 이러한점들 다루고자 합니다.

     

     

     

     

     

     

     

     

     

     

    'CS > 데이터 중심 애플리케이션 설계 요약' 카테고리의 다른 글

    8장 - 분산 시스템의 골칫거리  (0) 2022.12.22
    7장 - 트랜잭션  (0) 2022.12.15
    5장 - 복제  (0) 2022.12.02
    4장 - 부호화와 발전  (0) 2022.11.18
    3장 - 저장소와 검색  (0) 2022.11.17

    댓글

Designed by Tistory.