분할 패턴

Azure SQL Database
Azure Cosmos DB

데이터 저장소를 수평 파티션 또는 분할 집합으로 나눕니다. 이렇게 하면 대량의 데이터를 저장하고 액세스할 때 확장성이 향상될 수 있습니다.

컨텍스트 및 문제점

단일 서버에서 호스트되는 데이터 저장소에는 다음과 같은 제한 사항이 적용될 수 있습니다.

  • 스토리지 공간. 대규모 클라우드 애플리케이션을 위한 데이터 저장소에는 시간이 지남에 따라 크게 늘어날 수 있는 대규모 데이터가 포함됩니다. 서버는 일반적으로 한정된 양의 디스크 스토리지만 제공하지만, 데이터 볼륨이 증가함에 따라 기존 디스크를 더 큰 디스크로 바꾸거나 컴퓨터에 디스크를 추가할 수 있습니다. 그러나 시스템은 결국 지정된 서버의 스토리지 용량을 쉽게 늘릴 수 없는 한도에 도달하게 됩니다.

  • 컴퓨팅 리소스. 클라우드 애플리케이션은 많은 수의 동시 사용자를 지원해야 하며, 각 사용자는 데이터 저장소에서 정보를 검색하는 쿼리를 실행합니다. 데이터 저장소를 호스트하는 단일 서버는 데이터 저장 및 검색을 시도하는 애플리케이션이 시간 초과되면서 사용자에 대한 응답 시간이 길어지고 빈번한 실패를 야기함에 따라 이 부하를 지원하는 데 필요한 컴퓨팅 기능을 제공하지 못할 수 있습니다. 메모리를 추가하거나 프로세서를 업데이트하는 것이 가능할 수도 있지만, 더 이상 컴퓨팅 리소스를 늘리는 것이 불가능하면 시스템은 한계에 도달하게 됩니다.

  • 네트워크 대역폭. 궁극적으로 단일 서버에서 실행되는 데이터 저장소의 성능은 서버가 요청을 검색하고 응답을 전송할 수 있는 속도에 따라 달라집니다. 네트워크 트래픽 볼륨이 서버에 연결하는 데 사용되는 네트워크의 용량을 초과하여 요청이 실패할 수 있습니다.

  • 지리. 법적, 규정 준수 또는 성능상의 이유로 특정 사용자가 생성한 데이터를 해당 사용자와 동일한 지역에 저장하거나 데이터 액세스 대기 시간을 줄여야 할 수 있습니다. 사용자가 여러 국가 또는 지역에 분산된 경우 애플리케이션의 전체 데이터를 단일 데이터 저장소에 저장하지 못할 수 있습니다.

디스크 용량을 더 추가하고, 전원, 메모리 및 네트워크 연결을 처리하여 수직으로 크기를 조정하면 이러한 제한 사항 중 일부의 영향을 연기할 수 있지만 임시 솔루션일 수 있습니다. 많은 사용자와 대용량 데이터를 지원할 수 있는 상용 클라우드 애플리케이션은 거의 무한정으로 크기 조정이 가능해야 하므로 수직적 확장이 반드시 최선의 해결책은 아닙니다.

솔루션

데이터 저장소를 수평 파티션 또는 분할된 데이터베이스로 나눕니다. 각 분할된 데이터베이스는 같은 스키마를 갖지만 고유의 자체 데이터 하위 집합을 보유합니다. 분할된 데이터베이스는 스토리지 노드 역할을 하는 서버에서 실행되는 자체적으로 데이터 저장소입니다(다양한 형식의 여러 엔터티에 대한 데이터를 포함할 수 있음).

이 패턴에는 다음과 같은 이점이 있습니다.

  • 추가 스토리지 노드에서 실행되는 분할된 데이터베이스를 더 추가하여 시스템을 확장할 수 있습니다.

  • 시스템은 각 스토리지 노드에 대해 특수하고 비용이 많이 드는 컴퓨터가 아닌 기성품 하드웨어를 사용할 수 있습니다.

  • 분할된 데이터베이스 간에 워크로드를 분산하여 경합을 줄이고 성능을 향상시킬 수 있습니다.

  • 클라우드에서 분할된 데이터베이스는 데이터에 액세스할 사용자와 물리적으로 가까운 위치에 있을 수 있습니다.

데이터 저장소를 분할된 데이터베이스로 나눌 때 분할된 각 데이터베이스에 배치할 데이터를 결정합니다. 분할된 데이터베이스는 일반적으로 데이터의 하나 이상의 특성에 의해 결정되는 지정된 범위 내에 속하는 항목을 포함합니다. 이러한 특성은 분할 키(파티션 키라고도 함)를 형성합니다. 분할된 데이터베이스 키는 정적 키여야 합니다. 변경될 수 있는 데이터를 기반으로 하면 안 됩니다.

분할은 데이터를 물리적으로 구성합니다. 애플리케이션이 데이터를 저장하고 검색할 때 분할 논리는 애플리케이션을 적절한 분할된 데이터베이스로 보냅니다. 이 분할 논리는 애플리케이션의 데이터 액세스 코드의 일부로 구현되거나 분할을 투명하게 지원하는 경우 데이터 스토리지 시스템에서 구현할 수 있습니다.

분할 논리에서 데이터의 실제 위치를 추상화하면 어떤 분할된 데이터베이스에 어떤 데이터가 포함되는지 높은 수준의 제어가 제공됩니다. 또한 분할된 데이터베이스에 있는 데이터가 추후 재배포되어야 할 경우(예: 분할된 데이터베이스가 불균형 상태가 되는 경우) 애플리케이션의 비즈니스 논리를 재작업하지 않고 분할된 데이터베이스 간에 데이터를 마이그레이션할 수 있습니다. 절충은 검색할 때 각 데이터 항목의 위치를 결정하는 데 필요한 추가 데이터 액세스 오버헤드입니다.

최적의 성능과 확장성을 보장하려면 애플리케이션이 수행하는 쿼리 유형에 적합한 방식으로 데이터를 분할하는 것이 중요합니다. 대부분의 경우 분할 체계가 모든 쿼리의 요구 사항과 정확히 일치할 가능성은 거의 없습니다. 예를 들어 다중 테넌트 시스템에서 애플리케이션은 테넌트 ID를 사용하여 테넌트 데이터를 검색해야 할 수도 있지만 테넌트의 이름 또는 위치와 같은 다른 특성에 따라 이 데이터를 조회해야 할 수도 있습니다. 이러한 상황을 처리하려면 가장 일반적으로 수행되는 쿼리를 지원하는 분할된 데이터베이스 키를 사용하여 분할 전략을 구현합니다.

쿼리가 특성 값의 조합을 사용하여 정기적으로 데이터를 검색하는 경우 특성을 함께 연결하여 복합 분할 키를 정의할 수 있습니다. 또는 인덱스 테이블과 같은 패턴을 사용하여 분할 키에서 다루지 않는 특성에 따라 데이터를 빠르게 조회할 수 있습니다.

분할 전략

분할된 데이터베이스 키를 선택하고 분할된 데이터베이스 간에 데이터를 배포하는 방법을 결정할 때 일반적으로 세 가지 전략이 사용됩니다. 분할된 데이터베이스와 이를 호스트하는 서버가 일대일로 대응할 필요는 없습니다. 단일 서버가 여러 분할된 데이터베이스를 호스트할 수 있습니다. 전략은 다음과 같습니다.

조회 전략입니다. 이 전략에서 분할 논리는 분할 키를 사용하여 데이터 요청을 해당 데이터가 포함된 분할된 데이터베이스로 라우트하는 맵을 구현합니다. 다중 테넌트 애플리케이션에서 테넌트의 모든 데이터는 테넌트 ID를 분할 키로 사용하여 분할된 데이터베이스에 함께 저장될 수 있습니다. 여러 테넌트가 동일한 분할된 데이터베이스를 공유할 수 있지만 단일 테넌트의 데이터는 여러 분할된 데이터베이스에 분산되지 않습니다. 다음 그림은 테넌트 ID를 기반으로 테넌트 데이터를 분할하는 것을 보여 줍니다.

그림 1 - 테넌트 ID를 기반으로 테넌트 데이터 분할

분할 키와 실제 스토리지 간의 매핑은 각 분할 키가 물리적 파티션에 매핑되는 물리적 분할된 데이터베이스를 기반으로 할 수 있습니다. 또는 분할된 데이터베이스를 리밸런싱하는 보다 유연한 방법은 가상 분할입니다. 여기서 분할 키는 동일한 수의 가상 분할에 매핑되며, 이 경우 실제 파티션 수가 줄어듭니다. 이 방법에서 애플리케이션은 가상 분할된 데이터베이스를 참조하는 분할된 데이터베이스 키를 사용하여 데이터를 찾고 시스템은 가상 분할된 데이터베이스를 실제 파티션에 투명하게 매핑합니다. 가상 분할된 데이터베이스와 물리적 파티션 간의 매핑은 다양한 분할 키 집합을 사용하기 위해 애플리케이션 코드를 수정하지 않고도 변경될 수 있습니다.

범위 전략입니다. 이 전략은 같은 분할된 데이터베이스의 관련된 항목을 함께 그룹화하고 분할 키에 따라 정렬합니다. 키는 순차적입니다. 범위 쿼리(지정된 범위 내에 속하는 분할된 데이터베이스 키에 대한 데이터 항목 집합을 반환하는 쿼리)를 사용하여 항목 집합을 자주 검색하는 애플리케이션에 유용합니다. 예를 들어 애플리케이션이 지정된 달에 지정된 모든 주문을 정기적으로 찾아야 하는 경우 한 달의 모든 주문이 동일한 분할된 데이터베이스에 날짜 및 시간 순서로 저장되는 경우 이 데이터를 더 빠르게 검색할 수 있습니다. 각 주문이 다른 분할된 데이터베이스에 저장된 경우 많은 수의 지점 쿼리(단일 데이터 항목을 반환하는 쿼리)를 수행하여 개별적으로 페치해야 합니다. 다음 그림은 순차적 데이터 집합(범위)을 분할된 데이터베이스에 저장하는 것을 보여 줍니다.

그림 2 - 분할된 데이터베이스에 데이터의 순차 집합(범위) 저장

이 예에서, 분할 키는 주문 월을 가장 중요한 요소로 포함하고 그 다음으로 주문한 날짜와 시간을 포함하는 복합 키입니다. 주문에 대한 데이터는 새 주문이 만들어지고 분할된 데이터베이스에 추가될 때 자연스럽게 정렬됩니다. 일부 데이터 저장소는 분할된 데이터베이스를 식별하는 파티션 키 요소와 분할된 데이터베이스의 항목을 고유하게 식별하는 행 키를 포함하는 두 부분으로 구성된 분할 키를 지원합니다. 데이터는 일반적으로 분할된 데이터베이스의 행 키 순서로 유지됩니다. 범위 쿼리가 적용되고 함께 그룹화해야 하는 항목은 파티션 키에 대해 동일한 값을 가지지만 행 키에 대한 고유한 값을 가진 분할된 데이터베이스 키를 사용할 수 있습니다.

해시 전략입니다. 이 전략의 목적은 핫스팟(부하가 불균형한 분할된 데이터베이스)의 가능성을 줄이는 것입니다. 각 분할된 데이터베이스의 크기와 각 분할된 데이터베이스가 발생할 평균 부하 간의 균형을 이루는 방식으로 분할된 데이터베이스에 데이터를 분산합니다. 분할 논리는 데이터의 하나 이상의 특성 해시에 따라 항목을 저장할 분할된 데이터베이스를 계산합니다. 선택한 해시 함수는 일부 임의 요소를 계산에 도입하여 분할된 데이터베이스 간에 데이터를 균등하게 분산해야 합니다. 다음 그림에서는 테넌트 ID의 해시를 기반으로 테넌트 데이터를 분할하는 방법을 보여 줍니다.

그림 3 - 테넌트 ID의 해시를 기반으로 테넌트 데이터 분할

다른 분할 전략에 비해 해시 전략의 이점을 이해하려면 새 테넌트를 순차적으로 등록하는 다중 테넌트 애플리케이션이 데이터 저장소의 분할된 데이터베이스에 테넌트를 할당하는 방법을 고려합니다. 범위 전략을 사용하는 경우 테넌트 1에서 n까지의 데이터는 모두 분할 A에 저장되고, 테넌트 n+1에서 m까지의 데이터는 모두 분할 B에 저장됩니다. 가장 최근에 등록된 테넌트가 가장 활성 상태인 경우 대부분의 데이터 작업은 적은 수의 분할된 데이터베이스에서 발생하며 이로 인해 핫스팟이 발생할 수 있습니다. 반면, 해시 전략은 테넌트 ID의 해시를 기반으로 분할된 데이터베이스에 테넌트를 할당합니다. 즉, 순차 테넌트는 서로 다른 분할된 데이터베이스에 할당될 가능성이 가장 높으므로 부하가 분산됩니다. 이전 그림에서는 테넌트 55 및 56에 대해 이를 보여 줍니다.

세 가지 분할 전략에는 다음과 같은 이점과 고려 사항이 있습니다.

  • 조회. 이렇게 하면 분할된 데이터베이스를 구성하고 사용하는 방법을 더 자세히 제어할 수 있습니다. 가상 분할된 데이터베이스를 사용하면 워크로드에 새 실제 파티션을 추가할 수 있으므로 데이터의 균형을 조정할 때의 영향을 줄일 수 있습니다. 분할된 데이터베이스를 구현하는 가상 분할된 데이터베이스와 실제 파티션 간의 매핑은 분할된 데이터베이스 키를 사용하여 데이터를 저장하고 검색하는 애플리케이션 코드에 영향을 주지 않고 수정할 수 있습니다. 분할된 데이터베이스 위치를 조회하면 추가 오버헤드가 부과됩니다.

  • 범위입니다. 이는 단일 작업에서 단일 분할된 데이터베이스에서 여러 데이터 항목을 가져올 수 있기 때문에 범위 쿼리를 구현하기 쉽고 잘 작동합니다. 이 전략은 더 쉬운 데이터 관리를 제공합니다. 예를 들어 같은 지역의 사용자가 같은 분할된 데이터베이스에 있을 경우 로컬 부하 및 요구 패턴에 따라 각 표준 시간대에 업데이트를 예약할 수 있습니다. 그러나 이 전략은 분할된 데이터베이스 간에 최적의 분산을 제공하지 않습니다. 분할된 데이터베이스의 균형을 다시 조정하는 것은 어렵고 대부분의 작업이 인접한 분할된 데이터베이스 키에 대한 경우 고르지 않은 부하 문제를 해결하지 못할 수 있습니다.

  • 해시. 이 전략은 더 균등한 데이터 및 부하 분산의 더 나은 기회를 제공합니다. 해시 함수를 사용하여 직접 요청 라우팅을 수행할 수 있습니다. 지도를 기본 필요가 없습니다. 해시를 계산하면 추가 오버헤드가 발생할 수 있습니다. 또한 분할된 데이터베이스의 리밸러싱이 어렵습니다.

가장 일반적인 분할 시스템은 위에서 설명한 방법 중 하나를 구현하지만 애플리케이션의 비즈니스 요구 사항 및 데이터 사용 패턴도 고려해야 합니다. 예를 들어 다중 테넌트 애플리케이션에서 다음을 수행합니다.

  • 워크로드를 기반으로 데이터를 분할할 수 있습니다. 별도의 분할된 데이터베이스에서 매우 휘발성이 높은 테넌트에 대한 데이터를 분리할 수 있습니다. 결과적으로 다른 테넌트에 대한 데이터 액세스 속도가 개선될 수 있습니다.

  • 테넌트의 위치에 따라 데이터를 분할할 수 있습니다. 특정 지역의 테넌트에 대한 데이터를 오프라인으로 가져와 해당 지역의 비성수기 시간 동안 백업 및 기본 테넌트에 대한 데이터를 사용할 수 있으며, 다른 지역의 테넌트에 대한 데이터는 업무 시간 동안 온라인으로 다시 기본 액세스할 수 있습니다.

  • 고가의 테넌트에는 자체 프라이빗, 고성능, 가볍게 로드된 분할된 데이터베이스가 할당될 수 있지만, 낮은 값의 테넌트는 더 조밀하게 압축된 바쁜 분할된 데이터베이스를 공유해야 할 수 있습니다.

  • 높은 수준의 데이터 격리 및 개인 정보가 필요한 테넌트에 대한 데이터는 완전히 별도의 서버에 저장할 수 있습니다.

크기 조정 및 데이터 이동 작업

각 분할 전략은 규모 감축, 규모 확장, 데이터 이동 및 상태 기본 관리하기 위한 다양한 기능과 복잡성 수준을 의미합니다.

조회 전략을 사용하면 온라인 또는 오프라인에서 사용자 수준에서 크기 조정 및 데이터 이동 작업을 수행할 수 있습니다. 이 기술을 사용하면 사용량이 많지 않을 때 일부 또는 모든 사용자 작업을 일시 중단하고, 데이터를 새로운 가상 파티션이나 물리적 분할된 데이터베이스로 이동하고, 매핑을 변경하고, 이 데이터를 보관하는 캐시를 무효화하거나 새로 고친 다음 사용자 활동을 다시 시작할 수 있습니다. 이러한 유형의 작업을 중앙에서 관리할 수 있는 경우가 많습니다. 조회 전략을 사용하려면 상태를 캐시할 수 있고 복제본(replica) 친숙해야 합니다.

범위 전략은 크기 조정 및 데이터 이동 작업에 몇 가지 제한 사항을 적용합니다. 일반적으로 데이터가 분할된 데이터베이스 간에 분할 및 병합되어야 하기 때문에 데이터 저장소의 일부 또는 전부가 오프라인일 때 수행해야 합니다. 대부분의 작업이 인접 분할 키 또는 같은 범위 내에 있는 데이터 식별자에 관한 것일 경우 데이터를 이동하여 분할된 데이터베이스 리밸러스로 불균등한 부하 문제를 해결할 수 없습니다. 범위 전략은 범위를 물리적 파티션에 매핑하기 위해 일부 상태를 유지 관리해야 할 수도 있습니다.

해시 전략은 파티션 키가 분할 키 또는 데이터 식별자의 해시이기 때문에 크기 조정 및 데이터 이동 작업을 더 복잡하게 만듭니다. 각 분할된 데이터베이스의 새 위치는 해시 함수 또는 올바른 매핑을 제공하도록 수정된 함수에서 결정해야 합니다. 그러나 해시 전략에는 상태의 기본 필요하지 않습니다.

문제 및 고려 사항

이 패턴을 구현할 방법을 결정할 때 다음 사항을 고려하세요.

  • 분할은 수직 분할 및 기능 분할과 같은 다른 형태의 분할에 보완적입니다. 예를 들어 단일 분할된 데이터베이스는 세로로 분할된 엔터티를 포함할 수 있으며 기능 파티션을 여러 분할된 데이터베이스로 구현할 수 있습니다. 분할에 대한 자세한 내용은 데이터 분할 지침을 참조 하세요.

  • 분할된 데이터베이스가 모두 비슷한 양의 I/O를 처리할 수 있도록 균형이 조정된 상태를 유지합니다. 데이터가 삽입되고 삭제되면 분할된 데이터베이스의 균형을 주기적으로 조정하여 균일한 분포를 보장하고 핫스팟의 가능성을 줄여야 합니다. 리밸런싱은 비용이 많이 드는 작업일 수 있습니다. 리밸런싱의 필요성을 줄이기 위해 각 분할된 데이터베이스에 예상되는 변경 볼륨을 처리할 수 있는 충분한 여유 공간이 있는지 확인하여 성장을 계획합니다. 또한 필요한 경우 분할된 데이터베이스의 균형을 빠르게 조정하는 데 사용할 수 있는 전략과 스크립트를 개발해야 합니다.

  • 분할 키에 안정적인 데이터를 사용합니다. 분할된 데이터베이스 키가 변경되면 해당 데이터 항목이 분할된 데이터베이스 간에 이동해야 할 수 있으므로 업데이트 작업으로 수행되는 작업의 양이 늘어나게 됩니다. 이러한 이유로 잠재적으로 휘발성 정보에 분할된 데이터베이스 키를 기반으로 하지 마십시오. 대신 고정되거나 자연스럽게 키를 형성하는 특성을 찾습니다.

  • 분할된 데이터베이스 키가 고유한지 확인합니다. 예를 들어 분할 키로 자동 증가 필드를 사용하지 않도록 합니다. 일부 시스템에서 자동 증가된 필드는 분할된 데이터베이스 간에 조정될 수 없으므로 다른 분할된 데이터베이스에 있는 항목이 같은 분할 키를 가지게 될 수 있습니다.

    분할 키가 아닌 다른 필드의 자동 증가 값으로 인해 문제가 발생할 수도 있습니다. 예를 들어 자동 증가 필드를 사용하여 고유한 ID를 생성하는 경우 서로 다른 분할된 데이터베이스에 있는 두 개의 서로 다른 항목에 동일한 ID가 할당될 수 있습니다.

  • 데이터에 대해 가능한 모든 쿼리의 요구 사항과 일치하는 분할 키를 디자인할 수 없습니다. 데이터를 분할하여 가장 빈번히 수행되는 쿼리를 지원하고, 필요한 경우 보조 인덱스 테이블을 만들어 분할 키에 속하지 않는 특성을 기반으로 하는 조건을 사용하여 데이터를 검색하는 쿼리를 지원합니다. 자세한 내용은 인덱스 테이블 패턴을 참조하세요.

  • 단일 분할된 데이터베이스에만 액세스하는 쿼리는 여러 분할된 데이터베이스에서 데이터를 검색하는 쿼리보다 더 효율적이므로 애플리케이션이 다른 분할된 데이터베이스에 저장된 데이터를 조인하는 많은 수의 쿼리를 수행하는 분할 시스템을 구현하지 않도록 합니다. 단일 분할된 데이터베이스는 여러 엔터티 유형의 데이터를 포함할 수 있습니다. 애플리케이션이 수행하는 별도의 읽기 수를 줄이기 위해 일반적으로 함께 쿼리되는 관련 엔터티(예: 고객의 세부 정보 및 주문)를 동일한 분할된 데이터베이스에 유지하도록 데이터를 비정규화하는 것이 좋습니다.

    한 분할된 데이터베이스의 엔터티가 다른 분할된 데이터베이스에 저장된 엔터티를 참조하는 경우 첫 번째 엔터티에 대한 스키마의 일부로 두 번째 엔터티에 대한 분할 키를 포함합니다. 이렇게 하면 분할된 데이터베이스에서 관련 데이터를 참조하는 쿼리의 성능을 향상시킬 수 있습니다.

  • 애플리케이션이 여러 분할된 데이터베이스에서 데이터를 검색하는 쿼리를 수행해야 하는 경우 병렬 작업을 사용하여 이 데이터를 가져올 수 있습니다. 예를 들어 여러 분할된 데이터베이스의 데이터를 병렬로 검색한 다음 단일 결과로 집계하는 팬아웃 쿼리가 있습니다. 그러나 이 방법은 솔루션의 데이터 액세스 논리에 복잡성을 더합니다.

  • 많은 애플리케이션에서 적은 수의 작은 분할된 데이터베이스를 만드는 것이 부하 분산을 위한 더 많은 기회를 제공할 수 있기 때문에 적은 수의 큰 분할된 데이터베이스를 보유하는 것보다 더 효율적일 수 있습니다. 또한 분할된 데이터베이스를 한 물리적 위치에서 다른 물리적 위치로 마이그레이션할 필요성이 예상될 경우에도 유용할 수 있습니다. 작은 분할된 데이터베이스를 이동하는 것이 큰 분할된 데이터베이스를 이동하는 것보다 빠릅니다.

  • 각 분할된 데이터베이스 스토리지 노드에 사용할 수 있는 리소스가 데이터 크기 및 처리량 측면에서 확장성 요구 사항을 충분히 처리할 수 있는지 확인합니다. 자세한 내용은 데이터 분할 참고 자료의 “스케일링 성능을 위한 파티션 디자인” 섹션을 참조하세요.

  • 모든 분할된 데이터베이스에 참조 데이터를 복제본(replica) 것이 좋습니다. 분할된 데이터베이스에서 데이터를 검색하는 작업도 동일한 쿼리의 일부로 정적 또는 느리게 이동하는 데이터를 참조하는 경우 이 데이터를 분할된 데이터베이스에 추가합니다. 그러면 애플리케이션은 별도의 데이터 저장소에 대한 추가 왕복을 하지 않고도 쿼리에 대한 모든 데이터를 쉽게 가져올 수 있습니다.

    여러 분할된 데이터베이스에 보관된 참조 데이터가 변경되면 시스템은 모든 분할된 데이터베이스에서 이러한 변경 내용을 동기화해야 합니다. 이 동기화가 발생하는 동안 시스템에서 어느 정도 불일치가 발생할 수 있습니다. 이렇게 하면 애플리케이션을 처리할 수 있도록 디자인해야 합니다.

  • 분할된 데이터베이스 간의 참조 무결성 및 일관성을 기본 어려울 수 있으므로 여러 분할된 데이터베이스의 데이터에 영향을 주는 작업을 최소화해야 합니다. 애플리케이션이 분할된 데이터베이스에서 데이터를 수정해야 하는 경우 전체 데이터 일관성이 실제로 필요한지 여부를 평가합니다. 대신 클라우드의 일반적인 접근 방식은 최종 일관성을 구현하는 것입니다. 각 파티션에 있는 데이터가 개별적으로 업데이트되고, 애플리케이션 논리를 사용하여 업데이트를 모두 성공적으로 완료할 수 있도록 하며, 최종적으로 일치하는 작업이 실행되는 동안 데이터 쿼리에서 발생할 수 있는 불일치를 처리해야 합니다. 최종 일관성을 구현하는 방법에 대한 자세한 내용은 데이터 일관성 입문을 참조 하세요.

  • 많은 수의 분할된 데이터베이스를 구성하고 관리하는 것은 어려울 수 있습니다. 모니터링, 백업, 일관성 검사, 로깅 또는 감사와 같은 작업은 여러 분할된 데이터베이스 및 서버에서 수행되어야 하며, 여러 위치에 있을 수 있습니다. 이러한 작업은 스크립트나 다른 자동화 솔루션으로 구현되기 쉽지만 추가적인 관리 요구 사항을 완전히 없애지는 못할 수 있습니다.

  • 분할된 데이터베이스는 포함된 데이터가 해당 데이터베이스를 사용하는 애플리케이션의 인스턴스에 가까울 수 있도록 지리적 위치를 지정할 수 있습니다. 이 접근 방식은 성능을 크게 개선할 수 있지만, 다른 위치에서 여러 분할된 데이터베이스에 액세스해야 하는 작업도 추가로 고려해야 합니다.

이 패턴을 사용해야 하는 경우

데이터 저장소가 단일 스토리지 노드에서 사용할 수 있는 리소스 이상으로 확장하거나 데이터 저장소의 경합을 줄여 성능을 향상해야 하는 경우 이 패턴을 사용합니다.

참고 항목

분할의 주안점은 시스템의 성능 및 확장성을 개선하는 것이지만 부가적으로 데이터가 별도의 파티션으로 어떻게 분할되느냐에 따라 가용성을 개선할 수도 있습니다. 한 파티션의 오류로 인해 애플리케이션이 다른 파티션에 저장된 데이터에 액세스할 수 있는 것은 아니고, 연산자는 애플리케이션에 대한 전체 데이터를 액세스할 수 없으면 하나 이상의 파티션을 기본 테넌트 또는 복구를 수행할 수 있습니다. 자세한 내용은 데이터 분할 지침을 참조 하세요.

워크로드 디자인

설계자는 분할 패턴을 워크로드 디자인에 사용하여 Azure Well-Architected Framework 핵심 요소에서 다루는 목표와 원칙을 해결하는 방법을 평가해야 합니다. 예시:

핵심 요소 이 패턴이 핵심 목표를 지원하는 방법
안정성 디자인 결정은 워크로드가 오작동에 대한 복원력을 갖도록 하고 오류가 발생한 후 완전히 작동하는 상태로 복구 되도록 하는 데 도움이 됩니다. 데이터 또는 처리가 분할된 데이터베이스에 격리되므로 한 분할된 데이터베이스의 오작동은 해당 분할된 데이터베이스에 격리된 기본.

- RE:06 데이터 분할
- RE:07 자기 보존
비용 최적화는 워크로드의 투자 수익률을 유지하고 개선하는 데 중점을 줍니다. 분할된 데이터베이스를 구현하는 시스템은 비용이 많이 드는 단일 리소스가 아닌 비용이 저렴한 컴퓨팅 또는 스토리지 리소스의 여러 인스턴스를 사용하는 것이 좋습니다. 대부분의 경우 이 구성으로 비용을 절감할 수 있습니다.

- CO:07 구성 요소 비용
성능 효율성은 크기 조정, 데이터, 코드의 최적화를 통해 워크로드가 수요를 효율적으로 충족하는 데 도움이 됩니다. 크기 조정 전략에서 분할을 사용하는 경우 데이터 또는 처리는 분할된 데이터베이스로 격리되므로 해당 분할된 데이터베이스로 전송되는 다른 요청과만 리소스를 위해 경쟁합니다. 분할을 사용하여 지리에 따라 최적화할 수도 있습니다.

- PE:05 크기 조정 및 분할
- PE:08 데이터 성능

디자인 결정과 마찬가지로 이 패턴으로 도입될 수 있는 다른 핵심 요소의 목표에 대한 절충을 고려합니다.

예시

전 세계적으로 출판 된 책에 대한 정보의 광대 한 컬렉션을 표면 웹 사이트를 고려하십시오. 이 워크로드에 분류된 가능한 책 수와 일반적인 쿼리/사용 패턴은 책 정보를 저장하는 단일 관계형 데이터베이스의 사용량을 나타냅니다. 워크로드 설계자는 분할 키에 대해 책의 정적 ISBN(International Standard Book Number)을 사용하여 여러 데이터베이스 인스턴스에 데이터를 분할하기로 결정합니다. 특히 ISBN의 검사 자리(0-10)를 사용하여 11개의 가능한 논리 분할된 데이터베이스를 제공하며 데이터는 각 분할된 데이터베이스에서 상당히 분산됩니다. 먼저 11개의 논리 분할된 데이터베이스를 세 개의 실제 분할된 데이터베이스로 공동 배치하기로 결정합니다. 조회 분할 방법을 사용하고 키-서버 매핑 정보를 분할된 데이터베이스 맵 데이터베이스에 저장합니다.

Azure 앱 서비스, 4개의 Azure SQL Database 및 1개의 Azure AI Search를 보여 주는 다이어그램

여러 Azure SQL Database 인스턴스 및 Azure AI Search 인스턴스에 연결된 "책 카탈로그 웹 사이트"로 레이블이 지정된 Azure 앱 서비스를 보여 주는 다이어그램 데이터베이스 중 하나는 ShardMap 데이터베이스로 레이블이 지정되며, 이 문서에 추가로 나열된 매핑 테이블의 일부를 미러 예제 테이블이 있습니다. 세 개의 분할된 데이터베이스 인스턴스도 나열됩니다. bookdbshard0, bookdbshard1 및 bookdbshard2. 각 데이터베이스에는 테이블의 예제 목록이 있습니다. 세 가지 예제는 모두 동일합니다. "Books" 및 "LibraryOfCongressCatalog"의 테이블과 더 많은 테이블의 표시기가 나열됩니다. Azure AI Search 아이콘은 패싯 탐색 및 사이트 검색에 사용됨을 나타냅니다. 관리 ID는 Azure 앱 서비스와 연결된 것으로 표시됩니다.

분할된 데이터베이스 맵 조회

분할된 데이터베이스 맵 데이터베이스에는 다음과 같은 분할된 데이터베이스 매핑 테이블과 데이터가 포함됩니다.

SELECT ShardKey, DatabaseServer
FROM BookDataShardMap
| ShardKey | DatabaseServer |
|----------|----------------|
|        0 | bookdbshard0   |
|        1 | bookdbshard0   |
|        2 | bookdbshard0   |
|        3 | bookdbshard1   |
|        4 | bookdbshard1   |
|        5 | bookdbshard1   |
|        6 | bookdbshard2   |
|        7 | bookdbshard2   |
|        8 | bookdbshard2   |
|        9 | bookdbshard0   |
|       10 | bookdbshard1   |

예제 웹 사이트 코드 - 단일 분할된 데이터베이스 액세스

웹 사이트는 실제 분할된 데이터베이스의 수(이 경우 3개)나 분할된 데이터베이스 키를 데이터베이스 인스턴스에 매핑하는 논리를 인식하지 못하지만, 웹 사이트는 책의 ISBN의 검사 숫자를 분할 키로 간주해야 한다는 것을 알고 있습니다. 웹 사이트에는 분할된 데이터베이스 맵 데이터베이스에 대한 읽기 전용 액세스 권한과 모든 분할된 데이터베이스에 대한 읽기/쓰기 권한이 있습니다. 이 예제에서 웹 사이트는 연결 문자열 비밀을 유지하기 위해 권한 부여를 위해 웹 사이트를 호스팅하는 Azure 앱 Service의 시스템 관리 ID를 사용합니다.

웹 사이트는 이 예제와 같이 파일에서 또는 App Service 앱 설정을 통해 다음 연결 문자열 구성됩니다appsettings.json.

{
  ...
  "ConnectionStrings": {
    "ShardMapDb": "Data Source=tcp:<database-server-name>.database.windows.net,1433;Initial Catalog=ShardMap;Authentication=Active Directory Default;App=Book Site v1.5a",
    "BookDbFragment": "Data Source=tcp:SHARD.database.windows.net,1433;Initial Catalog=Books;Authentication=Active Directory Default;App=Book Site v1.5a"
  },
  ...
}

분할된 데이터베이스 맵 데이터베이스에 대한 연결 정보를 사용할 수 있는 경우 웹 사이트에서 워크로드의 데이터베이스 분할된 데이터베이스 풀에 대해 실행한 업데이트 쿼리의 예는 다음 코드와 유사합니다.

...

// All data for this book is stored in a shard based on the book's ISBN check digit,
// which is converted to an integer 0 - 10 (special value 'X' becomes 10).
int isbnCheckDigit = book.Isbn.CheckDigitAsInt;

// Establish a pooled connection to the database shard for this specific book.
using (SqlConnection sqlConn = await shardedDatabaseConnections.OpenShardConnectionForKeyAsync(key: isbnCheckDigit, cancellationToken))
{
  // Update the book's Library of Congress catalog information
  SqlCommand cmd = sqlConn.CreateCommand();
  cmd.CommandText = @"UPDATE LibraryOfCongressCatalog
                         SET ControlNumber = @lccn,
                             ...
                             Classification = @lcc
                       WHERE BookID = @bookId";

  cmd.Parameters.AddWithValue("@lccn", book.LibraryOfCongress.Lccn);
  ...
  cmd.Parameters.AddWithValue("@lcc", book.LibraryOfCongress.Lcc);
  cmd.Parameters.AddWithValue("@bookId", book.Id);

  await cmd.ExecuteNonQueryAsync(cancellationToken);
}

...

앞의 예제 코드에서 978-8-1130-1024-6인 경우 book.Isbn6isbnCheckDigit이어야 합니다. 호출 OpenShardConnectionForKeyAsync(6) 은 일반적으로 캐시 배제 방법을 사용하여 구현됩니다. 분할 키 6에 대한 캐시된 분할된 데이터베이스 정보가 없는 경우 연결 문자열 ShardMapDb 식별된 분할된 데이터베이스 맵 데이터베이스를 쿼리합니다. 애플리케이션의 캐시 또는 분할된 데이터베이스에서 bookdbshard2은 연결 문자열 대신 SHARDBookDbFragment 사용됩니다. 풀링된 연결은 bookdbshard2.database.windows.net 설정되고, 열리고, 호출 코드로 반환됩니다. 그런 다음 코드는 해당 데이터베이스 인스턴스의 기존 레코드를 업데이트합니다.

예제 웹 사이트 코드 - 여러 분할된 데이터베이스 액세스

드문 경우이지만 웹 사이트에서 직접 분할된 데이터베이스 간 쿼리가 필요한 경우 애플리케이션은 모든 분할된 데이터베이스에서 병렬 팬아웃 쿼리를 수행합니다.

...

// Retrieve all shard keys
var shardKeys = shardedDatabaseConnections.GetAllShardKeys();

// Execute the query, in a fan-out style, against each shard in the shard list.
Parallel.ForEachAsync(shardKeys, async (shardKey, cancellationToken) =>
{
  using (SqlConnection sqlConn = await shardedDatabaseConnections.OpenShardConnectionForKeyAsync(key: shardKey, cancellationToken))
  {
    SqlCommand cmd = sqlConn.CreateCommand();
    cmd.CommandText = @"SELECT ...
                          FROM ...
                         WHERE ...";

    SqlDataReader reader = await cmd.ExecuteReaderAsync(cancellationToken);

    while (await reader.ReadAsync(cancellationToken))
    {
      // Read the results in to a thread-safe data structure.
    }

    reader.Close();
  }
});

...

이 워크로드의 분할된 데이터베이스 간 쿼리 대신 사이트 검색 또는 패싯 탐색 기능과 같이 Azure AI Search에서 외부에서 기본 관련 인덱스를 사용할 수 있습니다.

분할된 데이터베이스 인스턴스 추가

워크로드 팀은 데이터 카탈로그 또는 동시 사용량이 크게 증가하는 경우 3개 이상의 데이터베이스 인스턴스가 필요할 수 있음을 알고 있습니다. 워크로드 팀은 데이터베이스 서버를 동적으로 추가할 것으로 예상하지 않으며 새 분할된 데이터베이스를 온라인 상태로 만들어야 하는 경우 워크로드 가동 중지 시간을 지속합니다. 새 분할된 데이터베이스 인스턴스를 온라인으로 전환하려면 분할된 데이터베이스 맵 테이블에 대한 업데이트와 함께 기존 분할된 데이터베이스에서 새 분할된 데이터베이스로 데이터를 이동해야 합니다. 이 상당히 정적인 접근 방식을 사용하면 워크로드가 웹 사이트 코드에서 분할된 데이터베이스 키 데이터베이스 매핑을 자신 있게 캐시할 수 있습니다.

이 예제의 분할된 데이터베이스 키 논리에는 최대 실제 분할된 데이터베이스의 상한이 11개입니다. 워크로드 팀이 부하 예측 테스트를 수행하고 11개 이상의 데이터베이스 인스턴스가 결국 필요할 것으로 평가하는 경우 분할 키 논리에 대한 침입적 변경이 필요합니다. 이 변경에는 새 키 논리로 코드 수정 및 데이터 마이그레이션을 신중하게 계획해야 합니다.

SDK 기능

분할된 데이터베이스 관리를 위한 사용자 지정 코드를 작성하고 Azure SQL Database 인스턴스로 라우팅하는 쿼리 대신 Elastic Database 클라이언트 라이브러리를 평가합니다. 이 라이브러리는 C# 및 Java 모두에서 분할된 데이터베이스 맵 관리, 데이터 종속 쿼리 라우팅 및 분할된 데이터베이스 간 쿼리를 지원합니다.

다음 단계

이 패턴을 구현할 때 다음 지침도 관련이 있을 수 있습니다.

  • Data Consistency Primer(데이터 일관성 입문서). 여러 분할된 데이터베이스에 분산된 데이터의 일관성을 기본 수 있습니다. 분산된 데이터의 일관성 유지 관리와 관련된 문제를 요약하고 다양한 일관성 모델의 장점과 단점을 설명합니다.
  • 데이터 분할 지침. 데이터 저장소 분할에 다양한 문제가 추가로 제기될 수 있습니다. 확장성을 개선하고 경합을 줄이며 성능을 최적화하기 위해 클라우드의 데이터 저장소 분할과 관련하여 이러한 문제를 설명합니다.

이 패턴을 구현할 때 다음 패턴도 관련이 있을 수 있습니다.

  • 인덱스 테이블 패턴입니다. 분할된 데이터베이스 키의 디자인을 통해서만 쿼리를 완전히 지원할 수 없는 경우도 있습니다. 애플리케이션이 분할 키 이외의 키를 지정하여 대규모 데이터 저장소에서 데이터를 신속하게 검색할 수 있도록 합니다.
  • 구체화된 뷰 패턴. 일부 쿼리 작업의 성능을 유지 관리하려면 데이터를 집계하고 요약하는 구체화된 뷰를 만드는 것이 유용합니다. 이 요약 데이터가 분할된 데이터베이스 간에 분산된 정보를 기반으로 할 경우에 특히 유용합니다. 이러한 뷰를 생성하고 채우는 방법을 설명합니다.