MMORPG는 데이터를 어떻게 저장합니까?


22

server.exe에서 sql 데이터베이스를 사용하고 싶습니다.

온라인으로 1000 명의 사용자를 말합니다. 플레이어는 게임을 할 때 데이터를 변경합니다. 그리고 서버는 이러한 업데이트를 저장해야합니다.

그러나 어떻게?

나는 두 가지 방법이 있다고 생각합니다.

1) 서버는 런타임에 램에 저장되며 때로는 또는 매시간 서버가 램에서 SQL 데이터베이스에 데이터 (업데이트)를 씁니다. 그러나 전기가 흐르거나 서버가 종료되면 업데이트가 저장되지 않습니다. 물론 나는 업데이트를 잃고 싶지 않습니다.

2) 서버는 런타임에 데이터베이스에 업데이트를 저장합니다. 그러나 속도는 어떻게 될까요? 나는 방법을 생각했다. 이미지와 함께 아래에 보여 드리겠습니다. 이 방법으로 1000 명의 온라인 플레이어에게 충분한 속도를 얻을 수 있습니까? 여기에 이미지 설명을 입력하십시오


11
벤치 마크를 했습니까? 데이터베이스 운영이 게임에 문제가된다고 생각하는 이유는 무엇입니까?
congusbongus

3
게임 상태가 실제로 관계가 있다면? SQL 데이터베이스를 원하십니까?
모니카

6
또한 해시를 사용하여 비밀번호를 처리하는 방법을 읽으십시오. 또는 최소한 비밀번호가 일반 텍스트로 저장되고 있음을 사용자에게 알리므로 다른 보안 비밀번호를 사용하지 않아야합니다.
TomTsagk

24
참고로, 상용 MMO 를 구축하고 이와 같은 질문을한다면 더 작은 것으로 시작해야합니다. MMO는 제대로 수행하기는 어렵지만 전혀하기가 매우 어렵습니다. 비즈니스 관점에서는 그리 훌륭하지 않습니다. 이것이 개인적인 일이고 많은 플레이어 수를 원한다면 64 플레이어와 같은 것으로 시작한 다음 길을 따라 가십시오. 경험없이 "완벽한"아키텍처를 처음부터 디자인하는 것보다 훨씬 쉽습니다. 참조 .
자금 모니카의 소송

1
스토리지와 무관 한 일반 API를 작성할 수 있습니다. 그런 다음 지연된 저장을 위해 RAM에 데이터를 캐시하는 어댑터를 작성하십시오. 또는 SQL DB에서 데이터를 플러시하기 전에 임시 파일에 데이터를 캐시하는 어댑터를 작성할 수 있습니다. 이렇게하면 캐싱을 켜고 끄면 어느 것이 가장 적합한 지 알 수 있습니다. 아키텍처가 올바르게 구축 된 경우 너무 많은 코드를 추가로 작성할 필요가 없습니다.
0xC0DEGURU

답변:


37

내가 작업했거나 사용한 첫 번째 방법 인 대부분의 MMO (또는 유사한 아키텍처를 사용하는 프로젝트) : 게임 서버는 주로 서버 프로세스를 실행하는 컴퓨터의 RAM과 작동하며 관련 게임 데이터를 SQL 데이터베이스에 주기적으로 직렬화합니다. 보관 용 (하나만 사용 된 경우)

정전과 관련하여주의해야 할 문제는 유효하지만 프로세스 충돌과 같은 문제보다 적습니다 (가동 시간 안정성은 일반적으로 데이터 센터에 지불하는 것 중 하나입니다). 그러나 여전히. 저장 간격 조정 (실패는 최대 몇 분의 진행 시간 만 소요됨), 여러 시스템에 저장 큐 분배, 저장해야하는 데이터의 양을 적극적으로 범위 지정 및 재시작 가능한 저장 구현과 같은 문제를 통해 이러한 문제를 완화합니다. 대기열.

일반적으로 SQL 서버 자체를 주 메모리로 사용하는 것은 불쾌하게 느리고 번거로울 것입니다. 나는 당신의 제안서에서 1000 명 정도의 플레이어에게만 효과가 있을지 확실하게 말할 수있을 정도로 충분히 자세한 내용을 보지 못했을 것입니다. 아마 괜찮을 것입니다. 하지만 적극적으로 확장 할 수 있다고 생각하지 않습니다.

또한 문제를 해결하지 못합니다. 같은 종류의 다시 시작 가능한 저장 대기열을 구현하는 작업을 수행하지 않으면 저장 프로세스 중 정전이 계속 발생하여 데이터가 손실되거나 손상됩니다. .

첫 번째 접근 방식을 사용하는 것이 좋습니다.


10
"저장 간격 조정"과 관련하여 마지막으로 작업 한 MMO에는 활성 플레이어 수에 따라 저장 간격이있었습니다. 병목 현상없이 눈에 띄는 초당 X 플레이어 데이터 저장을 처리 할 수 ​​있다는 것을 알고 있었기 때문에 우리는 초당 X 플레이어 미만의 비트를 순환 적으로 저장했습니다. 일반적으로 바쁜 날에는 2 분마다, 그리고 느린 시간에는 1 분에 2 번씩 각 플레이어의 비용이 절약됩니다.
평균 비트

4
"다시 시작 가능한 저장 큐"는 많은 파일 시스템과 데이터베이스 엔진에 의해 구현 된 저널처럼 들립니까?
grawity

6
이러한 문제는 MMO 게임, 심지어 비디오 게임, 고유하지 않은 전혀 . 존재하는 거의 모든 ORM은 일종의 캐싱 / 배칭 메커니즘을 제공합니다. 자체 솔루션을 굴릴 필요가 없습니다.
BlueRaja-대니 Pflughoeft

3
일정 간격으로 디스크에 저장하면 사람들이 드문 드롭 / 다이 등을받을 때 즉시 저장이 가능한 시스템을 설계하는 것이 좋습니다. 이렇게하면 서버 충돌이나 무언가가 발생하면 큰 성과를 거둔 사람들은 화를 내지 않을 것입니다.
Jon

5
@Jon, 그러면 사람들이 객체를 복제 할 수있는 문제가 발생합니다. 이상적으로는 전체 게임 상태를 주기적으로 단일 트랜잭션으로 저장합니다. 조각 단위로 저장을 시작하면 충돌로 인해 데이터가 일치하지 않는 상황이 발생합니다. 요청시 충돌을 유발하거나 충돌이 발생할 가능성을 예측할 수있는 플레이어는이를 활용할 수 있습니다.
마크

15

1000 명의 플레이어가 문제가 될 수도 있고 아닐 수도 있습니다. 데이터베이스를 얼마나 자주 업데이트해야하는지에 따라 다릅니다. 그러나 간단한 해결책이 있습니다. 데이터베이스를 자체 서버에 두십시오.


나는 사람들이 MMO-Lite라고 부르는 게임이 데이터베이스 시스템에서 어떻게 작동하는지 엿 보았다 – 나는 이것을 공개하지 않을 것이다.

  • 개인 문자 정보 (인벤토리, 장비 등)를 위해 문서 기반 "No-SQL"데이터베이스를 사용합니다.
  • 그들은 거의 업데이트되지 않는 공개 캐릭터 정보 (이름, 성과 등)와 통계를 위해보다 전통적인 관계형 데이터베이스를 사용합니다.

이 경우 문서 기반 데이터베이스를 사용하는 것이 좋습니다. 조인 및 집계를 수행하기에는 좋지 않더라도 데이터에 액세스하는 것이 좋지만 거기에있는 데이터로는 그렇게하지 않습니다.

반면, 모든 사람을 위해 다른 객체로 객체를 변경하는 것과 같은 일을해야 할 때 문자별로 이동하고 하나씩 업데이트하는 백그라운드 스크립트를 실행해야 할 때 눈에 띄는 시간이 걸립니다.


캐릭터의 데이터는 클라이언트와 서버 모두에 존재하며 시스템은 양쪽에서 동일한 작업을 수행하여 동기화 상태를 유지하도록 설계되었습니다.

이제 플레이어가 시스템과 거래를 할 때 (예 : NPC 등을 통해 다른 아이템으로 아이템 교환)이 단계는 다음과 같습니다.

  • 클라이언트는 작업이 유효한지 확인
  • 클라이언트가 작업을 서버로 보냅니다 (비동기 작업)
  • 클라이언트는 RAM에서 모델을 업데이트합니다
  • 서버는 작업이 유효한지 확인합니다
  • 서버는 RAM에서 모델을 업데이트합니다
  • 서버가 데이터베이스를 업데이트합니다 (비동기 작업)
  • 서버는 클라이언트에게 변경이 발생했음을 알려줍니다

참고 사항 :

  • 데이터베이스 업데이트는 비동기 적이지만 즉시 수행됩니다. 어떤 이유로 든 게임 서버가 다운되면 많이 손실되지 않습니다.
  • 데이터베이스를 자체 서버에 배치하면 성능이 크게 저하되지 않습니다.

플레이어 간의 거래는 다른 플레이어가 사기를 방지하기위한 추가 규칙과 거래를 취소해야하는 경우 추가적인 추적 성을 통해 유사하게 처리됩니다. 나는 누군가가 불평 할 때 문제를 해결하기 위해 한동안 보관 된 모든 거래에 대한 특별한 로그가 있다고 들었습니다. 그 부분이 어떻게 작동하는지 더 잘 모르겠습니다.


때때로 문제가 발생하면 두 가지 가능한 결과가 나타납니다.

  • 오류가 즉시 발생하면 서버는 클라이언트에게 작업을 되 돌리며 클라이언트는 작업을 취소합니다 (플레이어는 작업이 실행 취소됨).
  • UI에 플레이어에 항목이 있지만 서버가 동의하지 않는다고 말합니다. 사용자가 사용하려고하면 서버에 요청하여 실패하여 가짜 개체를 사용할 수 없게됩니다. 인벤토리를 다시로드하면 모델이 동기화 될 수있는 기회로 사용되는 잘못된 개체가 사라집니다.

두 경우 모두 클라이언트는 오류를 인식하고 플레이어가 수행 한 모든 작업과 함께 오류를 기록합니다. 클라이언트 측 로깅이 항상 발생합니다. 그런 다음 로그 아웃시 오류가 발생하면 클라이언트가 로그를 서버로 보냅니다.


이 게임은 대부분의 MMORPG에있는 전통적인 일일 또는 주별 유지 보수 중단 시간을 사용하지 않습니다. 예약 된 유지 관리는 종종 카운터, 타이머를 재설정하고 데이터베이스 절차를 실행하는 데 사용됩니다. 또한 업데이트를 위해 서버 버전을 교체 할 수도 있습니다.


고맙지 만, 예를 들어 플레이어가 현재 위치에서 이동하는 경우 플레이어의 움직임은 어떻습니까? x:10,y:10,z:10To x:11,y:11,z:11, 데이터베이스에 즉시 저장해야합니까? 플레이어가 계속 달리면 1 초 이하로 현재 위치를 저장하고 수천 명의 플레이어가있는 경우 이는 초당 DB에 대한 수백만 건의 쿼리입니다. 이것이 어떻게 작동합니까?
dwix

2
플레이어의 위치는 데이터베이스에 거의 저장되지 않아야합니다. 메뉴 열기, 캠프 파이어 시작, 휴식 등 특별한 상황에서만 게임을 할 수 있습니다. 게임에 따라 세부 정보가 저장되지 않을 수도 있습니다. 일부 게임은 항상 가장 가까운 도시 등에서 스폰하므로 위치를 저장하는 번거 로움을 덜어줍니다. 그러나 그것은 의견에 기반을 둔다.
니코

1
내가 이야기하는 게임의 경우 @dwix, 플레이어의 위치는 저장되지 않습니다. 로그 아웃했다가 로그인하거나 서버가 다운되면 플레이어는 안전한 알려진 위치에 다시 배치됩니다 (편집 : 개인 인스턴스, 원한다면 "집"이지만 모두에게 동일합니다). 그러나 일부 게임은 실수로 연결이 끊긴 경우에도 플레이어의 정확한 위치를 유지합니다. 이를 위해 일반적인 정보는 정보를 덜 자주 저장하는 것입니다. 어쨌든, 서버에서 데이터베이스를 기다리는 것은 아닙니다.
Theraot

1
@dwix 아바타의 위치에 대해 이야기 할 때, 당신은 실제로 역사적 가치에 신경 쓰지 않습니까? 데이터베이스가 병목이라면 데이터를 조절하십시오. 각 서버 틱을 저장하는 대신 덜 자주 저장하십시오. 이는 데이터베이스에 최신 값이 없지만 성능에 큰 영향을 미치지는 않습니다. 한편 서버는 여전히 업데이트 값을 RAM으로 유지하며 이것이 작동합니다. 부록 : 솔직히 저는 포지션을 저장하는 것에 대해 조언을하지만 일부 게임은 그렇게합니다.
Theraot


7

두 가지 방법 모두 MMORPG와 함께 사용됩니다. 모든 것을 메모리에 유지하고 주기적으로 디스크를 가리키는 지 확인하는 것은 적어도 오래된 게임에서 가장 인기있는 옵션 인 것 같습니다. 구현 및 확장이 상당히 간단하다는 장점이 있지만, 신뢰할 수있게 만드는 것은 개발자의 몫입니다. SQL 데이터베이스는 신뢰성을 향상시키는 ACID 속성 을 제공 하지만 전체적으로 구현하기가 더 복잡하고 확장에 문제가있을 수 있습니다.

EVE Online은 모든 것이 SQL 데이터베이스에 저장되는 MMO의 예입니다. 필자는 약 60,000 명의 동시 사용자에서 최고조에 달했으며로드에 맞추기 위해 수년에 걸쳐 고가의 하드웨어를 데이터베이스 서버에 바쳐야한다고 생각합니다. 그러나 EVE는 대부분의 MMORPG보다 사용자 당 더 많은 데이터를 저장하며 훨씬 더 빈번하고 다양한 트랜잭션이 있습니다. 데이터베이스의 ACID 속성을 사용하면 대규모의 복잡한 데이터베이스 전체를 항상 일관된 상태로 유지할 수 있습니다.

예를 들어, 누군가가 다른 플레이어에게 아이템을주는 경우를 고려하십시오. EVE의 데이터베이스는 충돌이나 정전이 발생하더라도 해당 아이템이 한 명의 플레이어의 인벤토리에서만 끝나는 것을 보장합니다. 즉, 한 플레이어의 인벤토리에서 항목을 제거하고 다른 플레이어의 항목에 추가하는 데이터베이스 트랜잭션은 원 자성입니다. 트랜잭션이 완전히 완료되거나 전혀 발생하지 않습니다. 아이템이 플레이어의 인벤토리 또는 둘 다에 존재하지 않는 상태가 될 수 없습니다.

플레이어 데이터를 메모리에 유지하고 주기적으로이 원 자성 자체를 구현해야하는 체크 포인트를 유지하는 MMORPG. 이를 수행하는 한 가지 방법은 모든 플레이어의 데이터를 동시에 검사 점으로하여 가장 최근의 검사 점으로 간주되기 전에 새로운 검사 점이 디스크에 완전히 커밋되도록하는 것입니다. 이 게임은 또한 체크 포인트가 진행되는 동안 플레이어 데이터가 변경되지 않도록해야합니다. 활동적인 플레이어가 많을 경우, 플레이어가 알아 차릴 수있을만큼 지연 시간을 발생시키지 않으면 서이 모든 작업을 수행해야합니다.

일관성이 얼마나 중요한지 과소 평가하지 마십시오. 게임을 개발할 때 많은 충돌이 발생합니다. 문제가 관련되지 않은 버그로 인해 게임이 좋지 않은 시간에 충돌하는 경우가 아니라 항목이 사라지거나 복제되는 이유를 추적하고 싶지는 않습니다. 또한 게임이 시작되면 예상보다 많이 충돌합니다. 테스트 중에 완벽하게 작동하는 서버는 갑자기 전체 부하 상태에서 수많은 버그를 노출 시키며 플레이어는 예상치 못한 일을합니다.

대부분의 MMORPG는 실제 게임 데이터가 아닌 경우에도 계정 관련 정보로 SQL 데이터베이스를 사용합니다. 게임 상태를 일관성있는 상태로 유지하는 것보다 더 중요한 것은 청구 상태를 일관성있게 유지하는 것입니다. 게임 데이터베이스가 손상된 경우 최악의 경우 매일 백업에서 데이터베이스를 복원해야합니다. 계정 데이터베이스가 손상되는 최악의 사례는 모든 지불 거절로 인해 파산하는 것입니다.

프로젝트의 경우 어느 쪽이든 갈 수 있습니다. 동시 사용자 수가 1000 명인 경우 SQL 서버가 요즘 상용 PC에서 처리 할 수있는 기능의 한계를 극복하지는 못하지만 트랜잭션의 특성에 따라 크게 달라집니다. SQL 및 관계형 데이터베이스 디자인에 익숙하다면 이것이 도움이 될 수 있습니다. 플레이어의 현재 적중률과 같은 통계는 반드시 일관성이 필요하지 않기 때문에 거래를 데이터베이스에 저장하고 싶을 수도 있습니다. (PvP 게임에서는 ...) 몬스터 HP와 같은 것을 데이터베이스에 전혀 저장하지 마십시오. 대부분의 게임에서는 플레이어 관련 데이터 만 영구적입니다.

반면에 SQL 마법사가 아닌 경우 모든 데이터를 메모리에 더 단순하게 유지하여 안정적으로 작업 할 수 있습니다. SQL 데이터베이스는 일관성과 신뢰성을 향상 시키지만 자동은 아닙니다. 잘못 설계된 데이터베이스는 성능이 저하되고 불일치가 발생할 수 있습니다. 그렇게하지 않으면 거래는 원 자성이되지 않습니다. 종교적으로 매개 변수화 된 문장을 사용하지 않으면 SQL 인젝션 공격에 노출됩니다.


0

다양한 게임은 다른 방식으로 물건을 저장합니다. 종종 게임 회사는이를 수행 할 수있는 방법을 만들고 대부분의 게임은 같은 방식을 사용합니다. 물론 다른 스튜디오에서는 종종 다른 방식을 사용합니다. SQL은 확실히 게임에 사용됩니다. 예를 들어 CCP (EVE)는 SQL 서버의 네트워크를 가지고 있거나 적어도 가지고 있습니다. 지금 어떻게하는지 모르겠습니다. 다른 많은 파일 만 사용하십시오.

어쩌면 다양한 게임 데이터 트랜잭션을 처리하기 위해 불가지론적인 "데이터 브로커 메커니즘"을 생성하는 것으로 시작 하시겠습니까? 어쨌든 테스트 중이므로 게임 자체의 관점에서 스토리지에 대해 너무 신경 쓰지 않아도되는 메커니즘을 만듭니다. 즉, 호스트 응용 프로그램에서이를 처리하는 방법에 집중하십시오.

개인적으로 게임과 브로커 자체를 다시 쓰지 않고도 실제 매장을 바꿀 수 있다면 큰 자산이 될 것이라고 생각합니다. 브로커와 대화하기 위해 동일한 인터페이스를 가진 다른 모듈로 전환하면됩니다.

데이터 자체를 저장하는 것 자체는 문제가되지 않을 것입니다. 호스트와 모든 클라이언트간에 데이터를 효율적으로 제공하는 것은 해당 매장으로 /로부터 해당 매장으로 /로부터 배송하는 것이 더 까다로울 수 있습니다. 전체 플레이어 데이터 세트를 배송하거나 일부로 나눌 경우 어떤 세분화를 기준으로 분할하기로 선택합니까? 어떤 상황에서 어떤 리소스를 더 많이 사용하는지 등

데이터를 제공하는 한 가지 형식은 XML 일 수 있습니다. 그렇게하면 청크 수있는 방법이 더 동적이 될 수 있습니다. 하나의 문자 대 여러 문자 또는 하나의 항목 대 항목 모음 등. 그런 다음 XML을 XML로 "저장"하거나 (SQL에서) XML을보다 트랜잭션 방식으로 XML로 배포 할 수 있습니다. 데이터를 실제로 저장하는 방법

또 다른 방법은 운송 측면에서 더 효율적이지만 다른 상황에서는 더 많은 비용이 발생할 수있는 이진입니다.

1,000 개의 클라이언트를 사용하면 클라이언트 당 10MB를 시작하고 쉽게 저장할 수 있으며 10GB의 유효 RAM 만 사용하고 해당 데이터를 관리하기 위해 일부 시스템 관리 RAM을 추가합니다 (예 : 다른 GB 또는 2GB). 이미 데이터 구조에있는 호스트의 RAM에 사용할 준비가 된 상태로 유지할 수 있습니다. 온라인 상태에 따라 활동 등에 따라 다양한 빈도로 동적으로로드 / 저장

각 클라이언트의 정보를 별도의 파일 등에 저장할 수도 있습니다.


0

* 온라인 * 플레이어를 램에두고 로그 아웃 할 때 데이터베이스 (SQLite? MySQL?)로 em을 푸시하십시오. 로그 아웃 중 IO 정지에 대해 걱정하는 경우 각 로그 아웃에 자체 스레드를 제공하고 기본 / 게임 스레드에서 수행하지 마십시오 (실제로 모든 온라인 플레이어에 대한 전용 플레이어 스레드를 유지하므로 네트워킹 코드가 훨씬 쉬워졌습니다) 비동기 네트워크 io 접근 방식보다)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.