비관계형 순위표 참조 아키텍처
소규모의 간단한 순위표
아키텍처 다이어그램
구현 세부 정보
이 소스 코드가 포함된 전체 자습서에서 데이터 처리량을 개선하고 데이터베이스 로드를 줄이기 위해 다른 데이터베이스와 함께 Azure Cache for Redis를 사용하는 순위표를 구현하는 방법을 배울 수 있습니다.
이 자습서는 영구 데이터베이스 백엔드용 캐시 레이어로 Azure Cache for Redis를 사용하는 cache-aside 패턴을 활용합니다. 데이터를 쓸 때마다 영구 데이터베이스와 Azure Cache for Redis 모두에 데이터가 기록됩니다. 데이터를 읽을 때마다 먼저 캐시에서 데이터를 읽고 누락(데이터가 일정 시간 후 만료되므로 더 이상 캐시에 존재하지 않음)이 발생하는 경우 영구 데이터베이스에서 데이터를 읽고 곧바로 캐시에 기록합니다. 캐시 적중일 경우 캐시에서 데이터를 읽습니다.
이 샘플에서는 .NET 추상화 계층 Entity Framework를 사용하여 데이터 개체 간 관계를 모델링하고 표현합니다. 모델 프로그래밍 관점에서 간단히 말하면 개발자는 이를 사용하여 다양한 개체를 가져오고 이러한 개체에 속성을 설정하고, 그러면 Entity Framework가 모든 작업을 SQL 작업에 매핑합니다.
단계별 설명
- 디바이스 클라이언트는 위의 아키텍처 다이어그램에 표시된 것처럼 Azure 웹앱(웹 서비스)에 연결하여 새 플레이어의 레코드를 업로드합니다. 또는 이 웹 서비스 대신 예를 들어 각각 특정 작업을 수행하는 Azure Functions를 사용하거나 가상 컴퓨터과 함께 부하 분산 장치를 사용할 수 있습니다.
- Azure 웹앱은 새 레코드를 업로드하는 작업을 수신하고 cache-aside 패턴을 따라 영구 데이터베이스, 이 경우 Azure SQL Database에 기록합니다.
- 이후 cache-aside 패턴을 지속하여 동일한 레코드가 Azure Cache for Redis 데이터베이스에 저장됩니다.
- 다른 플레이어가 특정 순위표를 보려고 하므로 Azure 웹앱(웹 서비스)에 연결됩니다.
- Azure 웹앱은 특정 순위표에서 레코드를 검색하는 작업을 수신합니다. 먼저 Azure Cache for Redis에서 읽으려고 시도합니다. 캐시에서 레코드를 찾으면(적중) 디바이스 클라이언트에 정보를 반환합니다.
- Azure Cache for Redis에서 레코드를 읽으려는 시도에서 누락(데이터가 일정 시간 후 만료되므로 더 이상 캐시에 존재하지 않음)이 발생하는 경우 Azure 웹앱은 영구 데이터베이스, 이 경우 Azure SQL Database에서 레코드를 읽습니다.
- 그런 다음 영구 데이터베이스에서 검색된 레코드가 Azure Cache for Redis에 저장되고 최종적으로 디바이스 클라이언트로 전송됩니다.
대안
Azure SQL Database 대신, 예를 들어 Azure Database for MySQL 같은 다른 데이터베이스를 사용할 수도 있습니다.
대규모의 고급 순위표
아키텍처 다이어그램
아키텍처 서비스
이 구현에서는 Azure Cosmos DB SDK 대신 Azure 함수를 사용하여 데이터를 씁니다. 더 정밀한 제어 및 디버깅을 원하는 경우 앱 서비스 및 변경 프로세서 SDK를 활용할 수 있습니다.
아키텍처 고려 사항
게임에 대한 순위표를 설계할 때 다양한 디자인 고려 사항과 선택 사항이 있습니다.
마스터 컬렉션, 파티션 및 파티션 키
더 진행하기 전에 Azure Cosmos DB 기본 사항 몇 가지를 설명하겠습니다.
분할은 Azure Cosmos DB에서 데이터베이스의 개별 컨테이너를 확장하는 데 사용되는 방법입니다. 컨테이너의 항목은 논리 파티션이라는 별개의 하위 집합으로 나뉩니다.
논리 파티션은 각 항목과 연결된 파티션 키 속성의 값을 기반으로 만들어지며, 컨테이너에 있는 항목의 고유한 하위 집합입니다.
논리 파티션의 항목은 해당 논리 파티션의 모든 항목에서 공유하는 파티션 키 값으로 식별됩니다. 예를 들어, 문서를 저장하는 컨테이너와 각 문서에 UserID 속성이 있는 경우를 생각해 볼 수 있습니다. UserID가 컨테이너의 항목에 대한 파티션 키로 사용되는 경우 1,000개의 고유한 UserID 값이 있는 경우 해당 컨테이너에 대해 1,000개의 논리 파티션이 생성됩니다.
컨테이너의 각 항목에는 항목 논리 파티션을 결정하는 파티션 키가 있으며 각 항목에는 논리 파티션 내에서 고유한 항목 ID도 있습니다. 항목의 인덱스는 이를 고유하게 식별하며 파티션 키와 항목 ID를 결합하여 구성됩니다.
파티션 키를 정의할 때 고려해야 하는 세 가지 주요 사항은 다음과 같습니다.
- 각 컬렉션에는 많은 파티션 키가 있을 수 있지만 파티션 키당 최대 10GB 제한이 있습니다.
- 파티션 키는 업데이트할 수 없습니다. A_B_C 같은 파티션 키를 만드는 경우 나중에 A_B_C_D로 업데이트할 수 없습니다. 그러나 새 키를 만들고 데이터를 마이그레이션할 수 있습니다.
- 목표는 워크로드를 모든 파티션에 고르게 분산하고 핫 스폿을 피하는 것입니다.
순위표 파티션 키를 선택하는 방법에 대한 자세한 내용은 파티션 키 선택을 참조하세요.
이 순위표 참조 아키텍처 구현은 전체 순위표 일반 컬렉션(즉 모든 항목을 저장하는 마스터 컬렉션)과 각 조합의 값에 대한 파티션 키를 활용합니다.
이 사용 사례에서 플레이어의 점수는 두 가지 변수, 즉 플랫폼 및 레벨에 따라 순위가 결정됩니다 **. 여기서 사용되는 파티션 키는 **level_system
입니다.
구체적인 예로, 이 참조 아키텍처 및 구현을 활용하는 게임이 Xbox 및 PlayStation 플랫폼 모두에서 출시되고 레벨(1 및 2)이 2개라면 Azure Cosmos DB에 다음 컬렉션 및 파티션이 생성될 것입니다.
- 마스터 컬렉션
- 파티션 1(all_all)
- 파티션 2(xbox_all)
- 파티션 3(ps4_all)
- 파티션 4(all_level1)
- 파티션 5(all_level2)
- 파티션 6(xbox_level1)
- 파티션 7(ps4_level1)
- 파티션 8(xbox_level2)
- 파티션 9(ps4_level2)
스키마는 다음과 같습니다.
{
"id": "1",
"platform": "Xbox Live",
"level": 3,
"character": "Damian",
"name": "Brian", //platform gamertag
"xp": 12345, // stat 1
"quests": 12 //stat 2
}
명확한 설명을 위해, 레벨(Laguna Seca 및 Monza), 선택(고속 클래스 및 저속 클래스), 통계(최단 랩 및 파워업 선택) 등 변수가 3개인 레이스 게임의 보다 복잡한 시나리오를 예로 들어 보겠습니다. 사용되는 파티션 키 구조 level_choice_stat
이며, 사용자가 레코드를 업로드할 때 다음 조합을 생성합니다.
- 마스터 컬렉션
- 파티션 1(lagunaseca_fastclass_fastestlap) [000]
- 파티션 2(lagunaseca_fastclass_powerupspicked) [001]
- 파티션 3(lagunaseca_slowclass_fastestlap) [010]
- 파티션 4(lagunaseca_slowclass_powerupspicked) [011]
- 파티션 5(monza_fastclass_fastestlap) [100]
- 파티션 6(monza_fastclass_powerupspicked) [101]
- 파티션 7(monza_slowclass_fastestlap) [110]
- 파티션 8(monza_slowclass_powerupspicked) [111]
이 시나리오에서 첫 번째 플레이어가 고속 클래스(선택)에 속하는 자동차를 사용하여 Monza 트랙(수준)에서 운전하는 경우 Azure Cosmos DB에 저장된 정보는 다음과 같습니다.
전체 순위표 컬렉션(leaderboards_all_data) | { userID: "XYZ", stat: "fastestlap", choice: "fastclass", level: "monza", value: "123" } { userID: "XYZ", stat: "powerupspicked", choice: "fastclass", level: "monza", value: "1" } |
파티션 5(monza_fastclass_fastestlap) | { userID: "XYZ", stat: "fastestlap", choice: "fastclass", level: "monza", value: "123" } |
파티션 6(monza_fastclass_powerupspicked) | { userID: "XYZ", stat: "powerupspicked", choice: "fastclass", level: "monza", value: "1" } |
계단식 배열 쓰기 패턴
마스터 컬렉션 및 하나 이상의 하위 테이블에 정보를 써야 하기 때문에 특히, 관련된 변수가 있는 경우(예: iOS, Android 및 모바일. 모바일이 iOS 및 Android 사용자 모두의 레코드를 표시하는 필터인 경우) 모범 사례는 쓰기 작업을 한 번만 수행하는 대신 Azure Cosmos DB 변경 피드가 낙수 효과를 통해 작업을 수행하도록 하여 실제로 쓰기 중 하나만 완료된 경우 발생할 수 있는 불일치를 피하는 것입니다.
파티션 키 업데이트
앞서 언급했듯이 기존 파티션 키를 업데이트 하는 것은 불가능하지만 새 키를 추가할 수는 있습니다.
twp 변수 예에 편승하여, 사용자가 플레이하는 난이도 설정(쉬움, 보통, 어려움)에 따라 데이터를 분할할 수 있도록 키를 하나 추가한다고 가정하겠습니다. 이를 구현하기 위해 이전 파티션 키 level_system
에서 level_system_difficulty
로 업그레이드해야 합니다. 기존 파티션 키를 업데이트할 수 없는 제한을 해결하기 위해 다음 단계를 따르는 마이그레이션 도구가 제공됩니다.
- 변경 피드를 사용하여 전체 컬렉션을 드레이닝.
- 다른 파티션 키를 사용하여 데이터를 다시 주입.
초당 Azure Cosmos DB 요청 단위
Azure Cosmos DB 컬렉션이 청구되는 방식, 요청 단위 수를 추적하는 방법 및 요청 단위를 요청하는 경험 법칙을 알아보려면 일반 지침 설명서를 참조하세요.
배포 템플릿
Azure 서비스에 대한 명명 규칙 및 제한 사항을 요약하는 문서가 포함된 일반 지침 문서를 참조하세요.
최적화 고려 사항
다음은 Cosmos DB 비용 최적화와 관련된 몇 가지 유용한 리소스입니다.
- 가격 책정 모델
- Azure Cosmos DB에서 개발 및 테스트 최적화
- TCO(총 소유 비용)
- 청구서 이해
- 프로비전된 처리량 비용 최적화
- 쿼리 비용 최적화
- 스토리지 비용 최적화
- 읽기 및 쓰기 비용 최적화
- 다중 지역 비용 최적화
- 개발/테스트 워크로드 최적화
- 예약된 용량으로 최적화
가능한 추가 기능
푸시 알림 지원 추가
플레이어가 사용하는 플랫폼에 따라 개발자는 예를 들어 플레이어가 친구에게 순위를 추월당할 경우 알릴 수 있습니다. Azure Cosmos DB 변경 피드 및 Azure Notification Hubs 서비스를 사용하면 이를 구현할 수 있습니다.
추가 리소스 및 샘플
MongoDB API를 통한 함수 및 Cosmos DB
게임 순위표(점수)를 저장하고 HTTP(s) 메서드/작업을 통해 이를 노출하는, Azure Functions에서 호스트되고 Azure Cosmos DB 및 Mongo API를 통해 백업되는 게임 순위표 API를 설치합니다. 게임에서 이 API 서비스를 사용하여 새 점수를 게시하고, 최고 점수를 가져오고, 최신 점수를 검색하는 등의 작업을 수행합니다.
가격
Azure 구독이 없는 경우 무료 계정을 만들어 12개월 무료 서비스를 시작합니다. 이러한 서비스의 제한을 초과하지 않는 한 Azure 무료 계정에서 무료로 제공하는 서비스에 대해서는 요금이 부과되지 않습니다. Azure Portal을 통해 또는 사용량 파일을 통해 사용량을 확인하는 방법을 알아보세요.
이러한 참조 아키텍처를 실행하는 동안 사용되는 Azure 서비스의 비용은 사용자가 부담하며, 전체 비용은 분석 파이프라인을 통해 실행되는 이벤트 수에 따라 달라집니다. 참조 아키텍처에 사용된 각 서비스에 대한 가격 웹 페이지를 참조하세요.
Azure 가격 계산기를 사용하여 사용하려는 Azure 서비스에 대한 비용을 구성하고 예측할 수도 있습니다.