데이터 분할 전략

Azure Table Storage

이 문서에서는 다양한 Azure 데이터 저장소의 데이터 분할 전략을 설명합니다. 데이터 분할 시기 및 모범 사례에 대한 일반 지침은 데이터 분할을 참조하세요.

Azure SQL Database 분할

단일 SQL 데이터베이스에는 포함할 수 있는 데이터 볼륨에 대한 제한이 있습니다. 처리량은 아키텍처 요소 및 지원되는 동시 연결 수에 의해 제약을 받습니다.

탄력적 풀은 SQL 데이터베이스에 수평 확장을 지원합니다. 탄력적 풀을 사용하면 여러 SQL 데이터베이스에 분산되어 있는 분할된 데이터베이스로 데이터를 분할할 수 있습니다. 처리해야 하는 데이터 볼륨이 늘거나 줄어들면 분할된 데이터베이스를 추가 또는 제거할 수도 있습니다. 탄력적 풀은 여러 데이터베이스에 부하를 분산하여 경합을 줄일 수도 있습니다.

각 분할된 데이터베이스는 SQL 데이터베이스로 구현됩니다. 분할된 데이터베이스 하나는 두 개 이상의 데이터 세트(shardlet이라고 함)를 보관할 수 있습니다. 각 데이터베이스는 포함된 shardlet을 설명하는 메타데이터를 유지 관리합니다. shardlet은 단일 데이터 항목이거나 동일한 shardlet 키를 공유하는 항목 그룹입니다. 예를 들어 다중 테넌트 애플리케이션에서 shardlet 키는 테넌트 ID일 수 있으며, 테넌트에 대한 모든 데이터를 동일한 shardlet에 보관할 수 있습니다.

클라이언트 애플리케이션은 데이터 세트를 shardlet 키와 연결하는 역할을 담당합니다. 별도의 SQL 데이터베이스는 전역 분할된 데이터베이스 맵 관리자 역할을 합니다. 이 데이터베이스에는 시스템의 모든 분할된 데이터베이스 및 shardlet 목록이 포함됩니다. 애플리케이션은 분할된 데이터베이스 맵 관리자 데이터베이스에 연결하여 분할된 데이터베이스 맵 복사본을 획득합니다. 분할된 데이터베이스 맵을 로컬로 캐시하고, 맵을 사용하여 데이터 요청을 적절한 분할된 데이터베이스로 라우팅합니다. 이 기능은 Elastic Database 클라이언트 라이브러리에 포함된 일련의 API에 포함되어 있으며, Java 및 .NET에 제공됩니다.

탄력적 풀에 대한 자세한 내용은 Azure SQL Database를 사용하여 확장을 참조하세요.

글로벌 분할된 데이터베이스 맵 관리자 데이터베이스를 복제하여 대기 시간을 줄이고 가용성을 향상할 수 있습니다. 프리미엄 가격 책정 계층을 사용하면 활성 지역 복제를 구성하여 다른 지역에 있는 데이터베이스에 지속적으로 데이터를 복사할 수 있습니다.

또 다른 방법으로 Azure SQL 데이터 동기화 또는 Azure Data Factory를 사용하여 여러 지역에 분할된 데이터베이스 맵 관리자 데이터베이스를 복제할 수 있습니다. 이러한 형태의 복제는 정기적으로 실행되며, 분할된 데이터베이스 맵이 드물게 변경되고 프리미엄 계층이 필요 없는 경우에 적합합니다.

Elastic Database는 다음과 같이 shardlet에 데이터를 매핑하고 분할된 데이터베이스에 저장할 수 있는 두 가지 구성표를 제공합니다.

  • 목록 분할된 데이터베이스 맵은 shardlet에 단일 키를 연결합니다. 예를 들어 다중 테넌트 시스템에서 각 테넌트에 대한 데이터를 고유 키와 연결하고 자체 shardlet에 저장할 수 있습니다. 격리를 보장하기 위해 각 shardlet을 자체 분할된 데이터베이스에 보관할 수 있습니다.

    Diagram that shows a list shard map to store tenant data in separate shards.

    이 다이어그램의 Visio 파일을 다운로드합니다.

  • 범위 분할된 데이터베이스 맵은 연속 키 값 집합을 shardlet에 연결합니다. 예를 들어 동일한 shardlet 내에 있는 테넌트 집합(각각 자체 키를 갖고 있는)의 데이터를 그룹화할 수 있습니다. 이 구성표는 테넌트가 데이터 스토리지를 공유하기 때문에 첫 번째보다 저렴하지만 격리가 부족합니다.

    Diagram that shows a range shard map to store data for a range of tenants in a shard.

    이 다이어그램의 Visio 파일 다운로드

분할된 데이터베이스 하나에 여러 shardlet의 데이터가 포함될 수 있습니다. 예를 들어 목록 shardlet을 사용하여 연속되지 않은 다양한 테넌트 데이터를 동일한 분할된 데이터베이스에 저장할 수 있습니다. 범위 shardlet과 목록 shardlet을 동일한 분할된 데이터베이스에 혼합할 수도 있지만, 다른 맵을 통해 처리됩니다. 다음 다이어그램은 이 방법을 보여줍니다.

Diagram that shows multiple shard maps.

이 다이어그램의 Visio 파일을 다운로드합니다.

탄력적 풀을 사용하면 데이터 볼륨이 축소 및 증가함에 따라 분할을 추가 및 제거할 수 있습니다. 클라이언트 애플리케이션은 분할된 데이터베이스를 동적으로 생성 및 삭제하고, 분할된 데이터베이스 맵 관리자를 투명하게 업데이트할 수 있습니다. 그러나 분할된 데이터베이스를 제거하는 것도 분할된 데이터베이스에 있는 모든 데이터를 삭제해야 하는 삭제 작업입니다.

애플리케이션에서 분할된 데이터베이스 하나를 두 개의 분할된 데이터베이스로 분할하거나 분할된 데이터베이스를 결합해야 하는 경우 분할-병합 도구를 사용합니다. 이 도구는 Azure 웹 서비스로 실행되며, 분할된 데이터베이스 간에 데이터를 안전하게 마이그레이션합니다.

파티션 구성표는 시스템 성능에 상당한 영향을 미칠 수 있습니다. 분할된 데이터베이스를 추가하거나 제거해야 하는 속도 또는 데이터를 분할된 데이터베이스에 다시 분할해야 하는 속도에도 영향을 미칠 수 있습니다. 다음 사항을 고려합니다.

  • 함께 사용되는 데이터를 동일한 분할된 데이터베이스에 그룹화하고, 여러 분할된 데이터베이스의 데이터에 액세스하는 작업을 피해야 합니다. 분할된 데이터베이스는 그 자체로 SQL 데이터베이스이며, 데이터베이스 간 조인은 클라이언트 쪽에서 수행해야 합니다.

    SQL Database는 데이터베이스 간 조인을 지원하지 않지만 탄력적 데이터베이스 도구를 사용하여 다중 분할 쿼리를 수행할 수 있습니다. 다중 분할된 데이터베이스 쿼리는 각 데이터베이스에 개별 쿼리를 보내고 결과를 병합합니다.

  • 분할된 데이터베이스 간에 종속성이 있는 시스템을 디자인하면 안 됩니다. 한 데이터베이스의 참조 무결성 제약 조건, 트리거 및 저장 프로시저는 다른 데이터베이스의 개체를 참조할 수 없습니다.

  • 쿼리에서 자주 사용하는 참조 데이터가 있는 경우 이 데이터를 여러 분할된 데이터베이스에 복제하는 방안을 고려해보세요. 이 방법은 데이터를 여러 데이터베이스에서 조인할 필요가 없습니다. 원칙적으로 복제 작업을 최소화하고 오래될 가능성을 줄이려면 이러한 데이터가 정적이거나 이동 속도가 느려야 합니다.

  • 동일한 분할된 데이터베이스 맵에 속하는 shardlet의 스키마는 동일해야 합니다. 이 규칙은 SQL Database에는 적용되지 않지만 데이터 관리에 적용되며, 각 shardlet에 다른 스키마가 있는 경우 쿼리가 매우 복잡해집니다. 대신, 각 스키마에 대한 별도의 분할된 데이터베이스 맵을 만드세요. 서로 다른 shardlet에 속하는 데이터를 동일한 분할된 데이터베이스에 저장할 수 있습니다.

  • 트랜잭션 작업은 한 분할된 데이터베이스의 데이터에만 지원되며, 분할된 데이터베이스 간에는 지원되지 않습니다. shardlet이 동일한 분할된 데이터베이스의 일부인 경우 트랜잭션이 여러 shardlet에 걸쳐 있을 수 있습니다. 따라서 비즈니스 논리에서 트랜잭션을 수행해야 하는 경우 데이터를 동일한 분할된 데이터베이스에 저장하거나 최종 일관성을 구현합니다.

  • 분할된 데이터베이스는 해당 분할된 데이터베이스의 데이터에 액세스하는 사용자와 가깝게 배치합니다. 이 전략은 대기 시간을 줄이는 데 도움이 됩니다.

  • 고도로 활성 상태인 분할된 데이터베이스와 상대적으로 비활성인 분할된 데이터베이스를 혼합하지 않도록 합니다. 분할된 데이터베이스 간에 부하를 균등하게 분산하려고 합니다. 이를 위해 분할 키를 해시해야 할 수 있습니다. 분할된 데이터베이스의 지리적 위치를 지정하는 경우 해시된 키가 해당 데이터에 액세스하는 사용자 가까이 저장된 분할된 데이터베이스에서 보관하는 shardlet으로 매핑되도록 합니다.

Azure Table 스토리지 분할

Azure Table 스토리지는 분할을 중심으로 디자인된 키-값 저장소입니다. 모든 엔터티가 파티션에 저장되고 파티션은 Azure Table 스토리지에서 내부적으로 관리됩니다. 테이블에 저장된 각 엔터티는 다음과 같이 두 개의 부분 키를 제공해야 합니다.

  • 파티션 키. Azure Table 스토리지에서 엔터티를 배치할 파티션을 결정하는 문자열 값입니다. 파티션 키가 동일한 모든 엔터티는 동일한 파티션에 저장됩니다.

  • 행 키. 파티션 내에서 엔터티를 식별하는 문자열 값입니다. 파티션 내의 모든 엔터티는 이 키에 따라 어휘순 및 오름차순으로 정렬됩니다. 파티션 키와 행 키의 조합은 엔터티별로 고유해야 하며 길이가 1KB 이하여야 합니다.

이전에 사용되지 않은 파티션 키를 사용하여 엔터티를 테이블에 추가하면 Azure Table 스토리지에서 이 엔터티를 위한 새 파티션을 만듭니다. 파티션 키가 동일한 기타 엔터티도 동일한 파티션에 저장됩니다.

이 메커니즘은 자동 확장 전략을 효과적으로 구현합니다. 단일 파티션에서 데이터를 검색하는 쿼리가 신속하게 실행될 수 있도록 각 파티션은 Azure 데이터 센터의 동일한 서버에 저장됩니다.

Microsoft는 Azure Storage에 대한 확장성 목표를 게시했습니다. 시스템이 이러한 제한을 초과할 가능성이 있으면 엔터티를 여러 테이블로 분할하는 방안을 고려해보세요. 수직 분할을 사용하여 함께 액세스할 가능성이 높은 그룹으로 필드를 나눕니다.

다음 다이어그램은 예제 스토리지 계정의 논리 구조를 보여줍니다. 스토리지 계정에는 3개의 테이블(고객 정보, 제품 정보, 주문 정보)이 포함됩니다.

The tables and partitions in an example storage account

각 테이블에는 여러 개의 파티션이 있습니다.

  • 고객 정보 테이블에서, 데이터는 고객이 있는 도시에 따라 분할됩니다. 행 키에는 고객 ID가 포함됩니다.
  • 제품 정보 테이블에서, 제품은 제품 범주별로 분할되고 행 키에는 제품 번호가 포함됩니다.
  • 주문 정보 테이블에서, 주문은 주문 날짜에 따라 분할되고 행 키는 주문을 받은 시간을 지정합니다. 모든 데이터는 각 파티션의 행 키로 정렬됩니다.

Azure Table 스토리지에 대한 엔터티를 디자인할 때 다음 사항을 고려하세요.

  • 데이터 액세스 방법에 따라 파티션 키와 행 키를 선택합니다. 대부분의 쿼리를 지원하는 파티션 키/행 키 조합을 선택합니다. 가장 효율적인 쿼리는 파티션 키와 행 키를 지정하여 데이터를 검색합니다. 파티션 키와 행 키의 범위를 지정하는 쿼리는 하나의 파티션을 검색하여 완료할 수 있습니다. 이 방법은 데이터를 행 키 순서대로 보관하기 때문에 상대적으로 빠릅니다. 쿼리에서 검색할 파티션을 지정하지 않으면 모든 파티션을 검색해야 합니다.

  • 엔터티에 하나의 기본 키가 있으면 이를 파티션 키로 사용하고 빈 문자열을 행 키로 지정합니다. 엔터티에 두 속성으로 구성되는 복합 키가 있으면 가장 느리게 변경되는 속성을 파티션 키로 선택하고 다른 속성을 행 키로 선택합니다. 엔터티에 키 속성이 세 개 이상 있으면 속성 연결을 사용하여 파티션 키와 행 키를 제공합니다.

  • 파티션 키 및 행 키 이외의 필드를 사용하여 데이터를 조회하는 쿼리를 정기적으로 수행하는 경우 인덱스 테이블 패턴을 구현하거나 Azure Cosmos DB처럼 인덱싱을 지원하는 다른 데이터 저장소를 고려해보세요.

  • 단조 시퀀스를 사용하여 파티션 키를 생성하고(예: "0001", "0002", "0003") 각 파티션에 제한된 양의 데이터만 포함되는 경우 Azure Table 스토리지는 이러한 파티션을 동일한 서버에 물리적으로 그룹화할 수 있습니다. Azure Storage는 애플리케이션이 파티션(범위 쿼리)의 연속된 범위에서 쿼리를 수행할 가능성이 가장 높으며 이러한 경우에 최적화된 것으로 가정합니다. 그러나 이 방법은 새 엔터티를 삽입할 때마다 연속된 범위의 한 쪽 끝에 집중될 가능성이 있으므로 핫스폿이 발생할 수 있습니다. 또한 확장성이 떨어질 수 있습니다. 부하를 보다 균등하게 분산하려면 파티션 키를 해시하는 방안을 고려해보세요.

  • Azure Table 스토리지는 동일한 파티션에 속하는 엔터티에 대한 트랜잭션 작업을 지원합니다. 애플리케이션이 다중 삽입, 업데이트, 삭제, 바꾸기 또는 병합 작업을 원자 단위(트랜잭션의 엔터티가 100개 이하이고 요청 페이로드가 4MB 이하인 경우)로 수행할 수 있습니다. 여러 파티션에 분산된 작업은 트랜잭션이 아니며, 최종 일관성을 구현해야 할 수도 있습니다. 테이블 스토리지 및 트랜잭션에 대한 자세한 내용은 엔터티 그룹 트랜잭션 수행을 참조하세요.

  • 파티션 키의 세분성을 고려합니다.

    • 모든 엔터티에 동일한 파티션 키를 사용하면 단일 파티션이 한 서버에 보관됩니다. 이렇게 하면 파티션이 확장되지 않고 단일 서버의 부하에 집중됩니다. 결과적으로 이 방법은 적은 수의 엔터티를 저장하는 시스템에만 적합합니다. 그러나 이 방법은 모든 엔터티가 엔터티 그룹 트랜잭션에 참여할 수 있습니다.

    • 모든 엔터티에 고유 파티션 키를 사용하면 테이블 스토리지 서비스에서 각 엔터티에 대해 별도의 파티션을 만들어 다수의 작은 파티션이 생길 가능성이 있습니다. 이 방법은 단일 파티션 키를 사용하는 방법보다 확장성이 뛰어나지만 엔터티 그룹 트랜잭션을 수행할 수 없습니다. 또한 엔터티를 두 개 이상 가져오는 쿼리에 두 개 이상의 서버를 읽는 작업이 포함될 수 있습니다. 그러나 애플리케이션에서 범위 쿼리를 수행한 다음, 파티션 키에 단조 시퀀스를 사용하면 쿼리를 최적화하는 데 도움이 될 수 있습니다.

    • 엔터티 하위 집합에서 파티션 키를 공유하면 동일한 파티션에서 관련 엔터티를 그룹화할 수 있습니다. 관련 엔터티가 포함된 작업은 엔터티 그룹 트랜잭션을 사용하여 수행할 수 있으며, 관련 엔터티 집합을 가져오는 쿼리는 단일 서버에 액세스하여 처리할 수 있습니다.

자세한 내용은 Azure Storage 테이블 디자인 가이드확장 가능한 분할 전략을 참조하세요.

Azure Blob Storage 분할

Azure Blob Storage를 사용하면 큰 이진 개체를 보관할 수 있습니다. 대용량 데이터를 신속하게 업로드 또는 다운로드해야 하는 시나리오에는 블록 Blob을 사용합니다. 페이지 BLOB은 데이터 일부에 직렬 액세스가 아닌 랜덤 액세스가 필요한 애플리케이션에 사용됩니다.

각 Blob(블록 또는 페이지)은 Azure Storage 계정의 컨테이너에 보관됩니다. 컨테이너를 사용하여 보안 요구 사항이 동일한 관련 Blob을 그룹화할 수 있습니다. 해당 그룹화는 물리적이 아니라 논리적입니다. 컨테이너 내에 있는 각 Blob에는 고유의 이름이 있습니다.

Blob의 파티션 키는 계정 이름 + 컨테이너 이름 + Blob 이름입니다. 파티션 키는 데이터를 범위로 파티션하는 데 사용되며 이러한 범위는 시스템 전체에서 부하가 분산됩니다. 액세스를 확장하기 위해 blob을 여러 서버에 분산시킬 수 있지만 단일 blob은 단일 서버에 의해서만 처리될 수 있습니다.

명명 체계에 타임스탬프 또는 숫자 식별자를 사용하면 한 파티션에 과도한 트래픽이 전송되어 시스템이 부하 균형을 효율적으로 조정할 수 없게 됩니다. 예를 들어 일상적인 작업에서 yyyy-mm-dd 같은 타임스탬프가 포함된 Blob 개체를 사용하는 경우 해당 작업의 모든 트래픽이 단일 파티션 서버로 전송될 수 있습니다. 대신 이름 앞에 세 자리 해시를 사용하는 것이 좋습니다. 자세한 내용은 파티션 명명 규칙을 참조하세요.

단일 블록 또는 페이지를 쓰는 작업은 원자성이지만, 여러 블록, 페이지 또는 Blob을 아우르는 작업은 그렇지 않습니다. 여러 블록, 페이지 및 Blob에서 쓰기 작업을 수행할 때 일관성을 유지해야 하는 경우에는 Blob 임대를 사용하여 쓰기 잠금을 제거합니다.

Azure Storage 큐 분할

Azure Storage 큐를 사용하면 프로세스 간에 비동기 메시징을 구현할 수 있습니다. Azure Storage 계정에는 큐가 개수에 관계없이 포함될 수 있으며 각 큐에는 메시지가 개수에 관계없이 포함될 수 있습니다. 유일한 제한은 스토리지 계정에서 사용 가능한 공간입니다. 개별 메시지의 최대 크기는 64KB입니다. 이보다 큰 메시지가 필요한 경우 Azure Service Bus 큐를 사용하는 것이 좋습니다.

각 스토리지 큐에는 스토리지 큐가 포함된 스토리지 계정 내에서 고유한 이름이 있습니다. Azure 파티션 큐는 이름을 기반으로 합니다. 동일한 큐의 모든 메시지는 단일 서버에서 제어하는 동일한 파티션에 저장됩니다. 부하 분산을 위해 큐마다 다른 서버에서 관리할 수 있습니다. 서버에 대한 큐 할당이 애플리케이션 및 사용자에게 투명합니다.

대규모 애플리케이션에서는 애플리케이션의 모든 인스턴스에 대해 동일한 스토리지 큐를 사용하지 마세요. 이 방법을 사용하면 큐를 호스팅하는 서버가 핫스폿이 될 수 있기 때문입니다. 대신 애플리케이션 기능 영역별로 다른 큐를 사용합니다. Azure Storage 큐는 트랜잭션을 지원하지 않으므로 메시지를 다른 큐로 보내는 것은 메시징 일관성에 거의 영향을 미치지 않습니다.

Azure Storage 큐는 초당 최대 2000개의 메시지를 처리할 수 있습니다. 이보다 더 빠른 속도로 메시지를 처리해야 하는 경우에는 다중 큐를 만드는 것이 좋습니다. 예를 들어 전역 애플리케이션에서는 별도의 스토리지 계정에 별도의 스토리지 큐를 만들어 각 지역에서 실행되는 애플리케이션 인스턴스를 처리합니다.

Azure Service Bus 분할

Azure Service Bus는 메시지 브로커를 사용하여 Service Bus 큐 또는 토픽으로 전송된 메시지를 처리합니다. 기본적으로 큐 또는 토픽으로 전송된 모든 메시지를 동일한 메시지 브로커 프로세스로 처리합니다. 이 아키텍처는 전체 메시지 큐 처리량을 제한할 수 있습니다. 그러나 큐 또는 토픽을 만들 때 분할할 수도 있습니다. 큐 또는 토픽 설명의 EnablePartitioning 속성을 true로 설정하여 처리량을 분할할 수 있습니다.

분할된 큐 또는 토픽은 여러 조각으로 나뉘며 각 조각은 별도의 메시지 저장소 및 메시지 브로커에서 지원합니다. Service Bus는 이러한 조각을 만들고 관리하는 작업을 담당합니다. 애플리케이션에서 분할된 큐 또는 항목에 메시지를 게시하면 Service Bus가 해당 큐 또는 항목의 조각에 메시지를 할당합니다. 큐 또는 구독에서 애플리케이션으로 메시지가 전송되면 Service Bus에서 사용 가능한 다음, 메시지가 있는지 각 조각을 확인한 다음, 처리를 위해 애플리케이션에 전달합니다.

이러한 구조는 여러 메시지 브로커와 메시지 저장소에 부하를 분산하여 확장성을 높이고 가용성을 향상시키는 데 도움이 됩니다. 하나의 조각에 대한 메시지 브로커 또는 메시지 저장소를 일시적으로 사용할 수 없는 경우 Service Bus는 나머지 사용 가능한 조각 중 하나에서 메시지를 검색할 수 있습니다.

Service Bus에서 조각에 메시지를 할당하는 방법은 다음과 같습니다.

  • 메시지가 세션에 속하는 경우 SessionId 속성 값이 동일한 모든 메시지를 동일한 조각으로 전송합니다.

  • 메시지가 세션에 속하지 않지만 발신자가 PartitionKey 속성 값을 지정한 경우 PartitionKey 값이 동일한 모든 메시지를 동일한 조각으로 전송합니다.

    참고

    SessionIdPartitionKey 속성이 모두 지정된 경우, 동일한 값으로 설정되어야 하며 그러지 않으면 메시지가 거부됩니다.

  • 메시지에 SessionIdPartitionKey 속성이 지정되어 있지 않지만 중복 검색을 사용할 수 있는 경우 MessageId 속성을 사용합니다. MessageId가 동일한 모든 메시지를 동일한 조각으로 이동합니다.

  • 메시지에 SessionId, PartitionKey 또는 MessageId 속성이 포함되지 않은 경우에는 Service Bus에서 순차적으로 메시지를 조각에 할당합니다. 조각을 사용할 수 없는 경우 Service Bus가 다음 단계로 이동합니다. 즉, 메시징 인프라에 일시적인 오류가 발생해도 메시지 송신 작업이 실패하지 않습니다.

Service Bus 메시지 큐 또는 토픽을 분할할지 여부 또는 분할하는 방법을 결정할 때 다음 사항을 고려하세요.

  • Service Bus 큐 및 항목은 Service Bus 네임스페이스 범위 내에서 만들어집니다. Service Bus는 현재 네임스페이스당 최대 100개의 분할된 큐 또는 항목을 허용합니다.

  • 각 Service Bus 네임스페이스는 사용할 수 있는 리소스에 할당량(예: 토픽당 구독 수, 초당 동시 전송 및 수신 요청 수, 설정 가능한 최대 동시 연결 수)을 적용합니다. 이러한 할당량은 Service Bus 할당량에 설명되어 있습니다. 해당 값을 초과할 것으로 예상되는 경우에는 자체 큐 및 항목을 사용하여 네임스페이스를 추가로 만들어 해당 네임스페이스에 작업을 분산합니다. 예를 들면, 전역 애플리케이션에서 각 지역에 별도의 네임스페이스를 만들고 애플리케이션 인스턴스에서 가장 가까운 네임스페이스에 있는 큐 및 항목을 사용하도록 구성합니다.

  • 트랜잭션의 일부로 전송되는 메시지는 파티션 키를 지정해야 합니다. 이는 SessionId, PartitionKey 또는 MessageId 속성이 될 수 있습니다. 동일한 트랜잭션의 일부로 전송되는 모든 메시지는 동일한 메시지 브로커 프로세스로 처리해야 하기 때문에 동일한 파티션 키를 지정해야 합니다. 동일한 트랜잭션에서 다른 큐 또는 항목으로 메시지를 보낼 수 없습니다.

  • 분할된 큐 및 토픽은 유휴 상태가 될 때 자동으로 삭제되도록 구성할 수 없습니다.

  • 플랫폼 간 또는 하이브리드 솔루션을 구축하는 경우 현재 분할된 큐 및 토픽을 AMQP(고급 메시지 큐 프로토콜)와 함께 사용할 수 없습니다.

Azure Cosmos DB 분할

Azure Cosmos DB for NoSQL은 JSON 문서를 저장하기 위한 NoSQL 데이터베이스입니다. Azure Cosmos DB 데이터베이스의 문서는 개체 또는 데이터의 다른 부분에 대한 JSON 직렬화 표현입니다. 모든 문서에 고유의 ID가 있어야 한다는 점 이외에는 고정 스키마가 적용되지 않습니다.

문서는 컬렉션으로 구성됩니다. 관련 문서를 한 컬렉션에 함께 그룹화할 수 있습니다. 예를 들어 블로그 게시물을 유지 관리하는 시스템에서 각 블로그 게시물 내용을 컬렉션에 문서로 저장할 수 있습니다. 또한 주체 종류별로 컬렉션을 만들 수도 있습니다. 또는 여러 저자가 자신의 블로그 게시물을 제어하고 관리하는 시스템과 같은 다중 테넌트 애플리케이션에서 저자에 따라 블로그를 분할하고 저자별로 별도의 컬렉션을 만들 수 있습니다. 컬렉션에 할당된 스토리지 공간은 탄력적이며 필요에 따라 줄이거나 늘릴 수 있습니다.

Azure Cosmos DB는 애플리케이션 정의 파티션 키에 따라 데이터의 자동 분할을 지원합니다. 논리 파티션은 단일 파티션 키 값에 대한 모든 데이터를 저장하는 파티션입니다. 파티션 키에 동일한 값을 공유하는 모든 문서는 동일한 논리 파티션 내에 배치됩니다. Azure Cosmos DB는 파티션 키의 해시에 따라 값을 배포합니다. 논리 파티션의 최대 크기는 20GB입니다. 따라서 파티션 키를 선택하는 것은 디자인 타임에서 중요한 사항입니다. 다양한 범위의 값 및 액세스 패턴을 가진 속성을 선택합니다. 자세한 내용은 Azure Cosmos DB의 파티션 및 규모 감축을 참조하세요.

참고

각 Azure Cosmos DB 데이터베이스에는 리소스의 양을 결정하는 성능 수준이 있습니다. 성능 수준은 RU(요청 단위) 비율 한도와 연관되어 있습니다. RU 비율 한도는 해당 컬렉션에 예약되어 배타적으로 사용할 수 있는 리소스 볼륨을 지정합니다. 컬렉션 비용은 해당 컬렉션에 대해 선택한 성능 수준에 따라 달라집니다. 성능 수준 및 RU 비율 한도가 높을수록 금액도 높아집니다. 컬렉션의 성능 수준은 Azure 포털을 사용하여 조정할 수 있습니다. 자세한 내용은 Azure Cosmos DB의 요청 단위를 참조하세요.

Azure Cosmos DB에서 제공하는 분할 메커니즘으로 충분하지 않은 경우 애플리케이션 수준에서 데이터를 분할해야 할 수 있습니다. 문서 컬렉션은 단일 데이터베이스 내에서 데이터를 분할하는 기본 메커니즘을 제공합니다. 분할을 구현하는 가장 간단한 방법은 분할된 데이터베이스별로 컬렉션을 만드는 것입니다. 컨테이너는 하나 이상의 서버에 걸쳐 있을 수 있는 논리적 리소스입니다. 고정 크기 컨테이너의 최대 제한은 20GB 및 10,000RU/s입니다. 무제한 컨테이너에는 최대 스토리지 크기가 적용되지 않지만 파티션 키를 지정해야 합니다. 클라이언트 애플리케이션은 애플리케이션 분할을 사용하여 요청을 적절한 분할된 데이터베이스로 직접 보내야 합니다. 이 작업은 일반적으로 분할 키를 정의하는 데이터의 일부 특성을 기반으로 고유한 매핑 메커니즘을 구현하여 수행됩니다.

모든 데이터베이스는 Azure Cosmos DB 데이터베이스 계정의 컨텍스트에서 만들어집니다. 단일 계정은 여러 개의 데이터베이스를 포함할 수 있으며, 데이터베이스를 만들 영역을 지정합니다. 각 계정에도 자체 액세스 제어가 적용됩니다. Azure Cosmos DB 계정을 사용하여 분할된 데이터베이스에 액세스해야 하는 사용자와 가까운 곳으로 분할된 데이터베이스(데이터베이스 내 컬렉션)의 지역을 지정하여 해당 사용자만 연결할 수 있도록 하는 제한을 적용할 수 있습니다.

Azure Cosmos DB for NoSQL을 사용하여 데이터를 분할하는 방법을 결정할 때 다음 사항을 고려합니다.

  • Azure Cosmos DB 데이터베이스에 사용할 수 있는 리소스에는 계정의 할당량 한도가 적용됩니다. 각 데이터베이스는 다수의 컬렉션을 보관할 수 있으며 각 컬렉션은 해당 컬렉션에 대한 RU 비율 한도(예약된 처리량)를 제어하는 성능 수준과 연관이 있습니다. 자세한 내용은 Azure 구독 및 서비스 제한, 할당량 및 제약 조건을 참조하세요.

  • 각 문서에는 해당 문서가 보관된 컬렉션 내에서 이 문서를 고유하게 식별하는 데 사용할 수 있는 특성이 있어야 합니다. 이 특성은 문서를 보관하는 컬렉션을 정의하는 분할 키와는 다릅니다. 컬렉션에는 수많은 문서가 포함될 수 있습니다. 이론적으로 문서 ID의 최대 길이만으로 제한할 수 있습니다. 문서 ID는 255자 이하여야 합니다.

  • 문서에 대한 모든 작업은 트랜잭션 컨텍스트 내에서 수행됩니다. 트랜잭션은 이 문서가 포함된 컬렉션으로 범위가 지정됩니다. 하나의 작업이 실패하면 이미 수행된 작업이 롤백됩니다. 문서는 작업 대상인 반면, 모든 변경 내용은 스냅샷 수준 격리가 적용됩니다. 예를 들어 이 메커니즘은 새 문서를 만드는 요청이 실패하면 동시에 데이터베이스를 쿼리하는 다른 사용자에게 문서의 일부가 표시되지 않으며 해당 문서를 제거하도록 합니다.

  • 데이터베이스 쿼리도 컬렉션 수준으로 범위가 지정됩니다. 단일 쿼리는 하나의 컬렉션에서만 데이터를 검색할 수 있습니다. 여러 컬렉션에서 데이터를 검색해야 하는 경우 각 컬렉션을 개별적으로 쿼리하고 애플리케이션 코드에서 결과를 병합해야 합니다.

  • Azure Cosmos DB는 문서와 함께 모두 컬렉션에 저장할 수 있는 프로그래밍 가능 항목을 지원합니다. 여기에는 저장 프로시저, 사용자 정의 함수, 트리거(JavaScript로 작성)가 포함됩니다. 해당 항목은 동일한 컬렉션 내의 모든 문서에 액세스할 수 있습니다. 또한 이러한 항목은 앰비언트 트랜잭션 범위 내에서 실행되거나(문서에 수행된 만들기, 삭제 또는 바꾸기 작업의 결과로 발생하는 트리거의 경우), 새 트랜잭션을 시작하여(명시적 클라이언트 요청의 결과로 실행되는 저장 프로시저의 경우) 실행됩니다. 프로그래밍 가능 항목의 코드에서 예외가 발생하면 트랜잭션이 롤백됩니다. 문서 간 무결성 및 일관성을 유지하기 위해 저장 프로시저 및 트리거를 사용할 수 있지만 해당 문서가 모두 동일한 컬렉션에 포함되어야 합니다.

  • 데이터베이스에 보관하려는 컬렉션이 컬렉션 성능 수준에 따라 정의된 처리량 한도를 초과할 가능성이 없도록 해야 합니다. 자세한 내용은 Azure Cosmos DB의 요청 단위를 참조하세요. 이러한 한도에 도달할 것으로 예상되는 경우 계정이 다른 여러 데이터베이스에 컬렉션을 분할하여 컬렉션당 부하를 줄이는 것이 좋습니다.

데이터를 검색할 수 있는 기능은 흔히 다양한 웹 애플리케이션에서 제공하는 기본 탐색 메서드입니다. 이를 통해 검색 조건 조합 기반의 리소스(예: 전자 상거래 애플리케이션의 제품)를 신속하게 찾을 수 있습니다. Azure Search 서비스는 웹 콘텐츠에 대해 전체 텍스트 검색 기능을 제공하며, 자동 완성, 근사한 쿼리 제안 및 패싯 탐색과 같은 기능이 포함됩니다. 자세한 내용은 Azure Search란?을 참조하세요.

Azure Search는 검색 가능 콘텐츠를 JSON 문서로 데이터베이스에 저장합니다. 해당 문서에서 검색 가능한 필드를 지정하고 Azure Search에 이러한 정의를 제공하는 인덱스를 정의합니다. 사용자가 검색 요청을 제출하면 Azure Search에서 적절한 인덱스를 사용하여 일치하는 항목을 찾습니다.

경합을 줄이기 위해 Azure Search에 사용되는 스토리지를 최대 1, 2, 3, 4, 6 또는 12개의 파티션으로 나눌 수 있으며 각 파티션은 최대 6번 복제할 수 있습니다. 파티션 수를 복제본 수로 곱한 결과를 SU(검색 단위)라고 합니다. Azure Search의 단일 인스턴스에는 최대 36개의 SU를 포함할 수 있습니다(12개의 파티션이 있는 데이터베이스는 최대 3개의 복제본만 지원).

해당 서비스에 할당되는 SU별로 청구됩니다. 검색 가능 콘텐츠의 볼륨이 증가하거나 검색 요청 비율이 늘어나면 기존의 Azure Search 인스턴스에 SU를 추가하여 추가된 부하를 처리할 수 있습니다. Azure Search 자체에서 문서를 여러 파티션에 균등하게 분산합니다. 수동 분할 전략은 현재 지원되지 않습니다.

각 파티션은 최대 1,500만 개의 문서를 포함하거나 300GB의 스토리지 공간을 차지할 수 있습니다(더 낮은 쪽). 최대 50개의 인덱스를 만들 수 있습니다. 서비스 성능은 문서의 복잡성, 사용 가능한 인덱스, 네트워크 대기 시간이 미치는 영향에 따라 달라집니다. 단일 복제본(1SU)은 평균적으로 초당 15개의 쿼리를 처리할 수 있지만, 처리량을 더 정밀하게 측정하려면 자체 데이터를 사용하여 벤치마킹을 수행하는 것이 좋습니다. 자세한 내용은 Azure Search의 서비스 제한 사항 을 참조하세요.

참고

제한된 데이터 형식 집합을 검색 가능 문서로 저장할 수 있으며, 문자열, 부울, 숫자 데이터, 날짜/시간 데이터 및 일부 지리적 데이터가 여기에 포함됩니다. 자세한 내용은 Microsoft 웹 사이트에서 지원되는 데이터 형식(Azure Search) 페이지를 참조하세요.

Azure Search에서 서비스의 각 인스턴스에 데이터를 분할하는 방법은 제한적으로만 제어할 수 있습니다. 그러나 전역 환경에서 다음 전략 중 하나를 사용하여 서비스 자체를 분할하면 성능을 개선하고 대기 시간 및 경합을 추가로 줄일 수 있습니다.

  • 각 지역에서 Azure Search의 인스턴스를 만들고 클라이언트 애플리케이션이 사용 가능한 가장 가까운 인스턴스로 연결되도록 합니다. 이 전략에서는 모든 서비스 인스턴스에서 검색 가능 콘텐츠에 대한 모든 업데이트를 적시에 복제해야 합니다.

  • 2계층 Azure Search를 만듭니다.

    • 해당 지역에서 사용자가 가장 자주 액세스하는 데이터가 있는 각 지역의 로컬 서비스. 사용자가 빠르지만 제한된 결과를 위해 로컬 서비스로 직접 요청을 보낼 수 있습니다.
    • 모든 데이터를 포함하는 글로벌 서비스. 사용자가 느리지만 더 완전한 결과를 위해 글로벌 서비스로 직접 요청을 보낼 수 있습니다.

이 방법은 검색 중인 데이터의 지역별 편차가 큰 경우 가장 적합합니다.

Azure Cache for Redis 분할

Azure Cache for Redis는 Redis 키-값 데이터 저장소를 기반으로 하는 클라우드에서 공유 캐싱 서비스를 제공합니다. 이름에서 알 수 있듯이 Azure Cache for Redis는 캐싱 솔루션으로 사용됩니다. 영구적 데이터 저장소가 아니라 데이터를 일시적으로 보관하는 용도로만 사용합니다. Azure Cache for Redis를 사용하는 애플리케이션은 캐시를 사용할 수 없는 경우 계속 작동할 수 있어야 합니다. Azure Cache for Redis는 고가용성을 제공하기 위해 기본/보조 복제를 지원하지만 현재 최대 캐시 크기를 53GB로 제한합니다. 이보다 더 많은 공간이 필요한 경우 캐시를 추가로 만들어야 합니다. 자세한 내용은 Azure Cache for Redis를 참조하세요.

Redis 데이터 저장소를 분할하려면 데이터를 Redis 서비스의 여러 인스턴스에 분할해야 합니다. 각 인스턴스는 단일 파티션으로 구성됩니다. Azure Cache for Redis는 façade 뒤에 있는 Redis 서비스를 추상화하고 직접 노출하지 않습니다. 분할을 구현하는 가장 간단한 방법은 여러 Azure Cache for Redis 인스턴스를 만들고 데이터를 분산하는 것입니다.

각 데이터 항목은 저장할 캐시를 지정하는 식별자(파티션 키)와 연결할 수 있습니다. 클라이언트 애플리케이션 논리에 이 식별자를 사용하여 요청을 적절한 파티션으로 라우트할 수 있습니다. 이 체계는 매우 간단하지만 분할 체계가 변경되는 경우(예: Azure Cache for Redis 인스턴스가 추가로 만들어지는 경우) 클라이언트 애플리케이션을 재구성해야 할 수 있습니다.

네이티브 Redis(Azure Cache for Redis 아님)는 Redis 클러스터링을 기반으로 하는 서버 쪽 분할을 지원합니다. 이 방법에서 해싱 메커니즘을 사용하여 데이터를 여러 서버에 균등하게 나눌 수 있습니다. 각 Redis 서버는 파티션에서 보관하는 해시 키 범위를 설명하는 메타데이터를 저장하고 다른 서버의 파티션에 있는 해시 키에 대한 정보도 포함합니다.

클라이언트 애플리케이션은 단순히 참여하는 Redis 서버(대부분 가장 가까운 서버) 중 하나로 요청을 보냅니다. Redis 서버는 클라이언트 요청을 검사합니다. 로컬로 해결할 수 있는 경우 요청된 작업을 수행합니다. 그렇지 않으면 요청을 적절한 서버로 전송합니다.

이 모델은 Redis 클러스터링을 사용하여 구현되며, Redis 웹 사이트의 Redis 클러스터 자습서 페이지에 설명되어 있습니다. Redis 클러스터링은 클라이언트 애플리케이션에 대해 투명합니다. 클라이언트를 다시 구성하지 않고도 Redis 서버를 클러스터 및 다시 분할될 수 있는 데이터에 추가할 수 있습니다.

중요

Azure Cache for Redis는 현재 프리미엄 계층에서만 Redis 클러스터링을 지원합니다.

Redis 웹 사이트의 분할: 여러 Redis 인스턴스 간에 데이터를 분할하는 방법 페이지는 Redis와 분할을 구현하는 자세한 정보를 제공합니다. 이 섹션의 나머지 부분에서는 클라이언트 쪽 또는 프록시 기반 분할을 구현하는 것으로 가정합니다.

Azure Cache for Redis를 사용하여 데이터를 분할하는 방법을 결정할 때 다음 사항을 고려합니다.

  • Azure Cache for Redis는 영구 데이터 저장소 역할을 하지 않으므로 구현하는 분할 체계가 무엇이든 애플리케이션 코드는 캐시가 아닌 위치에서 데이터를 검색할 수 있어야 합니다.

  • 자주 액세스되는 데이터는 동일한 파티션에서 함께 보관해야 합니다. Redis는 데이터 구조화를 위해 고도로 최적화된 다양한 메커니즘을 제공하는 강력한 키-값 저장소입니다. 이러한 메커니즘은 다음 중 하나일 수 있습니다.

    • 간단한 문자열(길이 512MB 이하의 이진 데이터)
    • 목록(큐 및 스택의 역할을 할 수 있음)과 같은 집계 형식
    • 집합(정렬 및 정렬되지 않음)
    • 해시(관련 필드(예: 개체의 필드를 나타내는 항목)를 함께 그룹화할 수 있음)
  • 집계 형식을 사용하면 키가 동일한 다수의 관련 값을 연결할 수 있습니다. Redis 키는 포함된 데이터 항목이 아닌 목록, 집합 또는 해시를 식별합니다. 이러한 유형은 모두 Azure Cache for Redis에서 사용할 수 있으며 Redis 웹 사이트의 데이터 형식 페이지에 설명되어 있습니다. 예를 들어 고객의 주문을 추적하는 전자 상거래 시스템 일부에서 고객 ID를 사용하여 키가 지정된 Redis 해시에 각 고객의 세부 정보를 저장할 수 있습니다. 각 해시에는 고객의 주문 ID 컬렉션이 보관될 수 있습니다. 별도의 Redis 집합은 주문 ID를 사용하여 키가 지정되고 해시로 다시 구조화된 주문을 보관할 수 있습니다. 그림 8에서는 이러한 구조를 보여줍니다. Redi는 어떤 형태의 참조 무결성도 구현하지 않으므로, 고객과 주문 간 관계를 유지 관리하는 것은 개발자의 책임입니다.

Suggested structure in Redis storage for recording customer orders and their details

그림 8. 고객 주문 및 세부 정보를 기록하기 위해 제안된 Redis 스토리지의 구조.

참고

Redis의 모든 키는 이진 데이터 값(예: Redis 문자열)이며 최대 512MB의 데이터를 포함할 수 있습니다. 이론적으로 하나의 키가 거의 모든 정보를 포함할 수 있습니다. 그러나 데이터 형식을 설명하고 엔터티를 식별하면서도 지나치게 길지 않은 일관된 명명 규칙을 키에 채택하는 것이 좋습니다. 일반적인 방법은 "entity_type:ID" 형식의 키를 사용하는 것입니다. 예를 들어 "customer:99"는 ID가 99인 고객에 대한 키를 나타내는 데 사용할 수 있습니다.

  • 동일한 데이터베이스의 다양한 집계에 대한 관련 정보를 저장하여 수직 분할을 구현할 수 있습니다. 예를 들어 전자 상거래 애플리케이션에서 자주 액세스하는 제품 정보를 하나의 Redis 해시에 저장하고 덜 자주 사용하는 세부 정보를 다른 해시에 저장할 수 있습니다. 두 해시 모두 동일한 제품 ID를 키의 일부로 사용할 수 있습니다. 예를 들어 제품 정보에 대해서는 "product: nn"(여기서 nn은 제품 ID) 및 세부 데이터에 대해서는 "product_details: nn"을 사용할 수 있습니다. 이 전략은 대부분의 쿼리에서 검색할 가능성이 있는 데이터의 볼륨을 줄이는 데 도움이 됩니다.

  • Redis 데이터 저장소를 다시 분할할 수 있지만 복잡하고 시간이 많이 걸리는 작업입니다. Redis 클러스터링은 데이터를 자동으로 다시 분할할 수 있지만 Azure Cache for Redis에서는 이 기능을 사용할 수 없습니다. 따라서 파티션 구성표를 디자인할 때 시간이 지남에 따라 예상되는 데이터 증가를 허용할 수 있도록 각 파티션에 충분한 여유 공간을 남기려고 합니다. 그러나 Azure Cache for Redis는 데이터를 일시적으로 캐시하기 위한 것이며 캐시에 보관된 데이터는 TTL(Time-to-Live) 값으로 지정된 제한된 수명을 가질 수 있습니다. 상대적으로 일시적인 데이터는 TTL이 짧을 수 있지만 정적 데이터는 TTL이 훨씬 더 길 수 있습니다. 데이터의 볼륨이 캐시를 채울 가능성이 높은 경우 수명이 긴 데이터를 캐시에 많이 저장하지 마세요. 공간이 부족한 경우 Azure Cache for Redis가 데이터를 제거하도록 하는 제거 정책을 지정할 수 있습니다.

    참고

    Azure Cache for Redis를 사용하는 경우 적절한 가격 책정 계층을 선택하여 캐시의 최대 크기(250MB~53GB)를 지정합니다. 그러나 Azure Cache for Redis를 만든 후에는 크기를 늘리거나 줄일 수 없습니다.

  • Redis 배치 및 트랜잭션은 여러 연결에 걸쳐 있을 수 없으므로 배치 또는 트랜잭션의 영향을 받는 모든 데이터를 동일한 데이터베이스(분할된 데이터베이스)에 보관해야 합니다.

    참고

    Redis 트랜잭션의 작업 시퀀스는 원자성이 없어도 됩니다. 트랜잭션을 작성하는 명령은 실행하기 전에 확인하고 큐에서 대기합니다. 이 단계에서 오류가 발생하면 전체 큐가 삭제됩니다. 그러나 트랜잭션을 성공적으로 제출한 후 큐에 대기 중인 명령이 순서대로 실행됩니다. 실패한 명령이 있으면 해당 명령만 실행을 중지합니다. 큐에 있는 이전 및 이후의 모든 명령은 수행됩니다. 자세한 내용은 Redis 웹 사이트의 트랜잭션 페이지를 참조하세요.

  • Redis는 제한된 수의 원자성 작업을 지원합니다. 다중 키 및 값을 지원하는 이 유형의 작업에는 MGET 및 MSET 작업만 해당합니다. MGET 작업은 지정된 키 목록의 값 컬렉션을 반환하고 MSET 작업은 지정된 키 목록의 값 컬렉션을 저장합니다. 이러한 작업을 사용해야 하는 경우 MSET 및 MGET 명령을 사용하여 참조하는 키/값 쌍을 동일한 데이터베이스에 저장해야 합니다.

Azure Service Fabric 분할

Azure Service Fabric은 클라우드에서 배포 애플리케이션에 대해 런타임을 제공하는 마이크로 서비스 플랫폼입니다. Service Fabric은 .Net 게스트 실행 파일, 상태 저장 및 상태 비저장 서비스, 컨테이너를 지원합니다. 상태 저장 서비스는 Service Fabric 클러스터 내의 키/값 컬렉션에 데이터를 영구적으로 저장하기 위한 신뢰할 수 있는 컬렉션을 제공합니다. 신뢰할 수 있는 컬렉션에서 키 분할 전략에 대한 자세한 내용은 Azure Service Fabric에서 신뢰할 수 있는 컬렉션에 대한 지침 및 권장 사항을 참조하세요.

다음 단계

Azure Event Hubs 분할

Azure Event Hubs는 대규모로 데이터 스트리밍을 수행할 수 있게 디자인되었으며, 수평적 크기 조정을 위해 서비스에 분할 기능이 기본적으로 제공됩니다. 각 소비자는 메시지 스트림의 특정 파티션만 읽습니다.

이벤트 게시자는 이벤트를 게시하는 파티션이 아니라 파티션 키만 인식합니다. 이렇게 키와 파티션을 분리하면 발신자가 다운스트림 처리에 대해 너무 많이 알 필요가 없습니다. (이벤트를 지정된 파티션에 직접 전송할 수도 있지만 일반적으로는 권장되지 않습니다.)

파티션 수를 선택할 때는 장기적인 크기 조정을 고려하세요. 이벤트 허브를 만든 후에는 파티션 수를 변경할 수 없습니다.

다음 단계

Event Hubs에서 파티션을 사용하는 방법에 대한 자세한 내용은 Event Hubs란?을 참조하세요.

가용성과 일관성 간의 절충에 대한 고려 사항은 Event Hubs의 가용성 및 일관성을 참조하세요.