MySQL용 Cloud SQL 2세대를 모바일 게임 백엔드 데이터베이스로 사용

Last reviewed 2022-10-28 UTC

온라인 게임 백엔드 빌드를 위해 효과적으로 테스트된 패턴은 MySQL과 같은 관계형 데이터베이스를 사용합니다. 이 데이터베이스는 게임 세계 상태와 필수 지속성 데이터를 저장합니다. 기본적인 세션 기반 게임에서는 최종 결과보다 더 복잡한 데이터가 데이터베이스에 저장되지 않습니다. 대규모의 지속적 환경에서 진행되는 대규모 멀티플레이어 온라인(MMO) 게임은 상당히 복잡한 상호 연관된 테이블 세트에 플레이어의 진행 상태와 인벤토리가 저장될 수 있습니다. 백엔드 데이터베이스 계층의 쿼리 속도는 게임 클라이언트의 반응과 관련한 사용자 경험에 직접적으로 영향을 미칩니다.

이러한 패턴이 일반적이지만 대부분의 게임 개발팀에는 전담 데이터베이스 관리자가 없으며, 데이터베이스의 크기가 커지고 데이터베이스가 모델링하는 관계가 복잡해짐에 따라 많은 팀들은 데이터베이스 관리를 외부에 위임하기를 선호합니다. 중소 규모의 비동기 턴 기반 모바일 게임에는 Google Cloud SQL 같은 데이터베이스가 훌륭한 선택입니다. MySQL용 Cloud SQL 2세대는 완벽하게 호스팅되고 관리되는 MySQL 인스턴스를 충실한 성능, 최소한의 작업, 자동화된 백업으로 제공합니다.

서비스 지향적 데이터베이스 패턴 설계

데이터베이스 아키텍처의 개요

마이크로서비스 패러다임은 모바일 게임 데이터베이스 백엔드에 유용합니다. 일반적인 설계는 데이터베이스 서비스를 통해 데이터베이스를 처리하도록 하는 것이며, 이러한 데이터베이스 서비스는 게임 프런트엔드에서 쿼리 요청을 받는 작업자 프로세스 풀로 구성되고, 데이터베이스에 대하여 이러한 쿼리를 실행하고, 결과를 반환합니다.

서비스 지향적 데이터베이스 패턴의 장점

게임 서버 대신 중개 서비스가 데이터베이스를 쿼리하도록 하면 몇 가지 이점이 있습니다.

  • 가용성 향상 — 데이터베이스는 종종 동시 연결의 수를 제한합니다. 서비스를 사용하면 데이터베이스에 대한 요청을 생성할 수 있는 게임 서버의 수가 허용되는 최대 연결 수에서 감소합니다.
  • 내결함성 — 데이터베이스에 문제가 발생하면 임시로 요청을 처리하기 위한 데이터베이스 서비스를 만들 수 있습니다.
  • 요청 최적화 — 데이터베이스 서비스는 다음을 제공하여 데이터베이스 요청을 최적화할 수 있습니다.
    • 쿼리 유효성 검사
    • 쿼리 우선순위 지정
    • 쿼리 속도 흐름 제어
    • 인메모리, 리드스루 캐싱
  • 데이터베이스 추상화서비스 계약이 이행되는 한, 프런트엔드 게임 서버를 수정하지 않고 데이터베이스 서비스와 이를 지원하는 데이터베이스를 대체할 수 있습니다. 이러한 설계를 사용하면 개발 또는 QA 환경에서 다른 데이터베이스를 사용하거나 프로덕션에서 다른 데이터베이스 기술로 이전할 수 있습니다.

게임을 위한 서비스 지향적 데이터베이스 패턴

다음 다이어그램은 Google Cloud Platform 서비스를 사용하여 강력한 서비스 지향적 데이터베이스 패턴을 만드는 방법을 보여줍니다.

Google Cloud Platform을 사용하는 데이터베이스 패턴

다음 구성요소를 사용하여 강력한 서비스 지향적 데이터베이스 패턴을 만들 수 있습니다.

  • 전용 게임 서버/프런트엔드 — 게임 클라이언트 애플리케이션이 게임 서버에 바로 연결되어 프런트엔드 서비스가 됩니다. 전용 게임 서버는 일반적으로 Google Compute Engine VM과 같은 가상화된 하드웨어에서 실행해야 하는 게임 엔진으로 빌드된 커스텀 실행 파일입니다. 온라인 상호작용을 HTTP 스타일의 요청/응답 시맨틱스로 모델링할 수 있는 게임을 개발하려면 Google App Engine도 적합합니다.

  • 데이터베이스 서비스와의 게임 서버 통신 — 종종 작성, 읽기, 업데이트, 삭제(CRUD) 액세스 스타일을 사용하여 모델링되므로 Compute Engine에서 REST API 또는 gRPC 엔드포인트를 만드는 것이 좋습니다.

  • 데이터베이스 작업자 풀에 대한 API/RPC 엔드포인트 통신 — 큐의 전형적인 사례이며, 자체 관리형, 오픈소스, RabbitMQ 또는 ZeroMQ와 같은 큐 미들웨어가 많이 사용됩니다. Cloud Platform에서는 안전하고 지속적이며 가용성이 높은 Google Cloud Pub/Sub를 사용할 수 있습니다. 이는 서버를 관리할 필요가 없는 관리형 큐 솔루션을 제공합니다.

  • Cloud SQL 2세대에 연결된 데이터베이스 작업자 — 데이터베이스 작업자는 최신 MySQL 액세스 방법을 제공하는 모든 언어로 작성될 수 있습니다. 이러한 작업자는 Compute Engine에서 수동으로 관리하거나, Google Kubernetes Engine에서 Kubernetes DSL을 사용하여 손쉽게 관리할 수 있도록 Docker 컨테이너로 패키징할 수 있습니다.

Cloud SQL 2세대를 사용할 때 고려해야 할 몇 가지 제한사항이 있습니다.

  • 데이터베이스 크기 제한은 10TB입니다.
  • 연결이 4.000개의 동시 연결로 제한됩니다.
  • 복제본이 지원되지만 NDB(분할) 지원이 없습니다.

이러한 문제를 해결하려면 다음 안내를 따르세요.

  • 저장된 데이터의 양을 최적화하는 데이터 모델을 선택하세요.

  • 거의 액세스하지 않는 데이터를 기본 데이터베이스 밖으로 이전하고 Google BigQuery와 같은 데이터 웨어하우스 안으로 이전하는 프로세스를 통합하세요.

  • 게임 서버가 마이크로 서비스를 통해 데이터베이스에 액세스하는 패턴을 사용하세요. 게임 서버가 데이터베이스에 직접 액세스할 수 있을 정도로 플레이어 수가 적더라도, 데이터베이스 계층을 게임 서버에서 분리하면 대기열, 쿼리 속도 평준화, 연결 실패 허용과 같은 많은 이점이 있습니다. 또한 게임 사용자가 늘어난 후에 별도의 데이터베이스 액세스 계층을 추가하려고 시도하면 다운타임과 수익 손실이 발생할 수 있습니다.

  • 게임 분석 및 플레이어 원격 측정을 데이터베이스의 읽기 전용 복제본에 대하여 실행하세요. 이렇게 하면 분석이 데이터베이스의 응답성에 영향을 미치지 않습니다. MySQL용 Cloud SQL 2세대를 사용하면 MySQL 복제가 가능하며, 분석 쿼리를 위해 두 번째 인스턴스의 크기를 적절하게 조정하여 비용을 최소 수준으로 유지할 수 있습니다.

샘플 설계: 대규모 싱글 플레이어 소셜(MASS) 게임

지난 10년 동안 부상한 게임 패러다임은 엄청난 수의 싱글 플레이어가 온라인에서 동시에 세션을 플레이하는 형태로, 플레이어 간의 유일한 접점은 유닛 대여, 유닛 거래, 리더보드와 같은 소셜 수단입니다. MASS 게임의 예시로는 Puzzle and Dragons™와 Monster Strike™가 있습니다. MASS 모바일 게임은 클라이언트/서버 통신을 통해 경제적으로 빌드됩니다. 이렇게 하면 연결이 제한되거나 산발적인 경우에도 사용자가 게임을 즐길 수 있습니다. 이러한 게임의 데이터 모델은 거의 모든 영구 상태 저장소가 메타게임(유닛 수집과 플레이어 화폐 유지)과 관련되어 있으며, 데이터베이스에 저장할 두 가지 기본 유형의 객체를 생성합니다. 이러한 객체는 CRUD 메커니즘을 사용하여 손쉽게 조작할 수 있습니다.

플레이어 객체는 다음을 추적합니다.

  • 게임 화폐와 실제 화폐
  • 유닛 인벤토리 슬롯의 총 개수
  • 스태미나
  • 경험

유닛 객체는 다음을 추적합니다.

  • 소유자(플레이어 ID)
  • 경험
  • 획득 비용
  • 유닛 인벤토리

플레이어 수가 100,000명 미만인 경우 이 데이터 모델은 Cloud SQL 2세대 같은 관계형 데이터베이스에 적합합니다.

Mimus

Mimus는 Puzzle and Dragons™ 또는 Monster Strike™ 스타일의 백엔드가 있는 모의 MASS 모바일 게임 애플리케이션입니다. 여기서는 각 플레이어가 한 번에 단 하나의 기기에서 로그인할 수 있고, 다른 동작을 시작하기 전에 이전의 동작을 완료해야 한다고 가정합니다 Mimus에서는 시뮬레이션된 워크로드를 실행하여 아키텍처의 최적 용량을 평가할 수 있습니다. 최적 용량은 일반적으로 동시 사용자 수(CCU)를 기반으로 합니다.

Mimus 소스 코드는 https://github.com/GoogleCloudPlatform/mimus-game-simulator에 있습니다.

Mimus 아키텍처의 개요

Mimus 서버 내의 Mimus 클라이언트 시뮬레이션

MASS 게임에서는 플레이어가 계속 진행하려면 애니메이션을 보고 게임 클라이언트와 상호 작용을 하도록 함으로써 게임 클라이언트가 데이터베이스 쿼리를 생성하는 속도를 게임 개발자가 제어할 수 있습니다. Mimus는 이와 같이 속도를 제한하는 전략을 sleep() 호출을 사용하여 시뮬레이션합니다. 이러한 방식으로 Mimus는 시뮬레이션된 플레이어와 같은 수의 프로세스를 실행하여 클라이언트당 데이터베이스 부하의 합리적인 추산을 시뮬레이션합니다. 이는 Kubernetes 클러스터에서 데이터베이스에 대해 쿼리를 생성하는 컨테이너화된 Mimus 클라이언트/서버 포드를 사용하여 효율적으로 조정됩니다.

Mimus 게임 클라이언트는 플레이어와 인벤토리의 상태를 기반으로 함수 호출을 선택하여 Mimus 서버 프로시저를 직접 호출하는 연속 루프를 사용해서 백엔드 서버와의 통신을 시뮬레이션합니다.

Mimus에 의해 시뮬레이션되는 플레이어 동작은 다음과 같습니다.

  • 게임 라운드 플레이
  • 화폐 구입
  • 화폐 소비
  • 유닛 레벨 설정 또는 진화

이러한 각 동작은 Mimus 서버에 대한 호출을 통해 클라이언트가 조작하는 플레이어 또는 유닛 객체와의 여러 CRUD 상호 작용으로 구현됩니다. Mimus 서버는 동기(차단) Mimus 데이터베이스 API를 사용하여 이러한 데이터베이스 요청을 만듭니다. 이 API는 Mimus 서버에서 가져온 Python 모듈이며 다른 데이터베이스 백엔드 구현을 테스트하도록 구성할 수 있습니다.

Mimus 데이터베이스 작업자 풀과의 Mimus 데이터베이스 API 통신

아래 다이어그램은 Mimus 서버와 데이터베이스 서비스 간의 통신을 보여줍니다.

Mimus의 통신 설계

Mimus 데이터베이스 API는 데이터베이스 쿼리의 일괄 처리를 수락하고 결과를 반환합니다. 이러한 일괄 처리를 Cloud Pub/Sub 메시지로 게시하고, 결과가 Redis를 통해 반환되기를 기다립니다. 메시지를 보내기 전에 데이터베이스 API는 데이터베이스에 기록되는 모든 값의 유효성을 검사하고 메시지에 고유한 트랜잭션 ID를 지정합니다. 그런 다음 메시지가 Cloud Pub/Sub의 Work 주제로 게시됩니다. 그런 다음 데이터베이스 API가 반복되면서 트랜잭션 ID가 Redis 키로 존재하는지를 폴링합니다. 그런 다음 키 값의 결과가 데이터베이스 API에 의해 검색되어 Mimus 서버로 반환되며, 여기에서 Mumus 클라이언트에게 제공됩니다.

통신 선택 고려 사항

사용자 작업에는 내구성과 안정적인 전송이 필요하기 때문에 Mimus는 보류 중인 쿼리 통신에 Cloud Pub/Sub를 사용합니다. Mimus는 내구성과 안정성이 덜 중요한 경우, 즉 결과를 전달하는 데는 Redis를 사용합니다. 애플리케이션 오류 또는 Redis 오류로 인해 결과가 손실되면 Mimus 클라이언트가 데이터베이스에서 최종 결과를 다시 쿼리합니다. 관계형 데이터베이스에서 트랜잭션을 사용하면 요청한 변경 사항이 모두 적용되거나 아무 것도 적용되지 않도록 보장됩니다. 드물게 Mimus가 두 번째 요청을 해야 하는 경우가 있는데 이는 Redis가 제공하는 검색의 단순성과 속도에 대한 허용 가능한 수준의 대가로 간주됩니다. Redis 사용량을 적절한 수준으로 유지하기 위해 요청 결과는 30초 후에 Redis에서 만료되도록 허용됩니다.

Mimus 데이터베이스 작업자 풀

Mimus 데이터베이스 작업자 풀에는 Kubernetes Engine에서 실행되는 여러 프로세스가 포함되어 있습니다. 실행 중인 각 컨테이너 인스턴스는 새 메시지의 무한 루프에서 Work Cloud Pub/Sub 항목을 폴링합니다. 그리고 메시지를 받으면 Python MySQLdb 모듈을 사용하여 메시지의 쿼리를 실행합니다. 단일 메시지는 관계형 트랜잭션을 나타내며 여러 개의 쿼리를 포함할 수 있습니다. 메시지의 모든 쿼리는 데이터베이스에 커밋되기 전에 완료되어야 합니다. 쿼리가 완료되면(또는 실패하면) 데이터베이스 작업자는 원본 메시지의 일부로 받은 트랜잭션 ID로 결과를 Redis에 게시합니다.

Mimus 데이터베이스

Mimus 데이터베이스 서비스를 지원하는 관계형 데이터베이스는 MySQL용 Cloud SQL 2세대 인스턴스입니다. 인스턴스를 생성할 때 머신 구성을 최대 32코어 및 208GB RAM, 디스크 크기는 최대 10TB로 선택할 수 있습니다. 복제본에 대한 지원 외에도 Cloud SQL 2세대 인스턴스는 기본적으로 정기적인 백업을 실행하도록 구성되어 있습니다. 추가로 MySQL 튜닝이 필요하면 Cloud SQL 인스턴스에 특정 MySQL 플래그를 지정할 수 있습니다. 구성에 대한 자세한 정보는 Cloud SQL 문서를 참조하세요.

Mimus를 사용하여 Cloud SQL을 테스트한 결론

Cloud SQL SG 머신 유형 권장하는 동시 사용자 수
n1-standard-4 15,000
n1-standard-8 30,000
n1-standard-16 60,000
n1-standard-32 120,000
n1-highmem-8 50,000
n1-highmem-16 100,000
n1-highmem-32 200,000

Mimus 테스트 장치를 사용하여 n1-highmem-16 Compute Engine 인스턴스에서 생성된 MySQL용 Cloud SQL 2세대 인스턴스에 대해 100,000명의 동시 사용자를 시뮬레이션할 때 쿼리 응답 시간은 테스트 내내 2초 미만으로 유지되었습니다.

MASS 모바일 게임을 빌드하고 수십만 명의 동시 플레이어를 지원해야 하는 경우 MySQL용 Cloud SQL 2세대를 기반으로 한 서비스 지향 데이터베이스 패턴이 필요한 성능을 제공할 수 있습니다. 게임 사용자가 늘어나면 추가 Cloud SQL 인스턴스를 분할된 인스턴스로 또는 복제 인스턴스로 도입하고, 데이터베이스 서비스 수준에서 Redis 또는 Memcached 캐싱 전략을 도입하여 성능을 허용 가능한 수준으로 유지할 수 있습니다.

예상되는 동시 사용자가 더 적은 게임은 더 작은 머신 유형을 사용하여 비용을 절감할 수 있습니다.

예상되는 동시 사용자(CCU) 수가 수백만 명인 게임은 강력한 확장성과 성능 특성을 갖춘 Google Cloud Datastore 또는 Google Cloud Bigtable과 같은 NoSQL 데이터베이스를 고려해야 합니다.

다음 단계

  • Google Cloud에 대한 참조 아키텍처, 다이어그램, 권장사항 살펴보기 Cloud 아키텍처 센터 살펴보기