초당 20 번의 업데이트 속도로 데이터가 변경되는 500여 명의 오픈 월드 플레이어를 상상해보십시오. 마지막으로 비슷한 MMORPG에서 일할 때 SQL을 사용했기 때문에 DB를 항상 쿼리 할 수 없었습니다. 대신, DB에서 모든 플레이어를 C ++ 객체로 메모리에로드하여 사용했습니다. 즉, 세로로 확장됩니다. 대신 서버를 수평 확장 가능하게 만들 수 있습니까? 해당 양의 업데이트를 동시에 지원하도록 설계된 데이터베이스가 있습니까?
초당 20 번의 업데이트 속도로 데이터가 변경되는 500여 명의 오픈 월드 플레이어를 상상해보십시오. 마지막으로 비슷한 MMORPG에서 일할 때 SQL을 사용했기 때문에 DB를 항상 쿼리 할 수 없었습니다. 대신, DB에서 모든 플레이어를 C ++ 객체로 메모리에로드하여 사용했습니다. 즉, 세로로 확장됩니다. 대신 서버를 수평 확장 가능하게 만들 수 있습니까? 해당 양의 업데이트를 동시에 지원하도록 설계된 데이터베이스가 있습니까?
답변:
500 명의 플레이어가 모두 의사 소통하는 테스트 사례, 즉 20Hz에서 250K 스트림의 정보가 전송됩니다. 이를위한 내부 대역폭은 각 메시지가 100 바이트 인 것으로 가정하면 약 500MB / 초입니다. 야심 찬 소리. 특히 프로세스 간.
플레이어를 100 개의 그룹으로 분리하면 20MB / 초 등으로 줄어 듭니다. 그렇기 때문에 MMO에 영역이 있고 해당 영역에서 대역폭이 합리해질 때까지 영향을 거의받지 않는 이유가 있습니다.
원래 문제 는 10 명 모두 실시간 정보를 공유하지만 500 명 모두 공유를 원하는 경우 통신 링크가 기하 급수적으로 증가하고이를 해결할 수있는 방법이라고 할 수 있습니다 . 내가 들었던 마법의 총알이 마법의 기하학적 진행을 마술처럼 만들지 못할 까봐 두렵습니다.
데이터베이스를 사용하여 통신하지 마십시오. 이것이 바로 메시징입니다. 데이터베이스를 사용하여 플레이어가 잃고 싶지 않은 거래 및 상점 정보를 시행하십시오. 내가 익숙한 대부분의 MMO는 1-10 분마다 또는 영역 전환이나 디자인의 "안전한"영역으로 들어가는 편리한 지점에서만 동적 플레이어 정보로 데이터베이스를 업데이트합니다.
멀리 떨어져 있더라도 모든 플레이어의 배낭 내용을 실시간으로 업데이트하려면 모든 플레이어에 대한 게임의 요구 를 다시 설계해야 할 수도 있습니다 .
또한 거리를 기준으로 업데이트 패턴을 20Hz에서 속도로 변경하십시오 .1 마일 떨어진 사람은 정확히 230.6 초에 1 발을 움직 인 다음 231.4 초에 다른 발을 움직일 필요가 없습니다. 초.
관심 영역 필터링을 사용하십시오. 세계가 3 대의 서버로 분리되어 있고 서버 1의 영역이 서버 3의 영역 근처에 없으면 엔티티에 대한 정보를 전혀 공유 할 이유가 없습니다.
마찬가지로 단일 서버에서는 관련 정보 만 클라이언트에게 보냅니다. 플레이어 A가 플레이어 B에서 맵의 반대편에 있다면 B에 대한 업데이트를 A에게 보내거나 그 반대의 이유가 없습니다.
연속 세계에 여러 서버가있는 경우 서버 2의 에지 근처에 서버 1의 엔터티에 가까운 엔터티가 있습니다. 엔터티에 대한 "권한"서버에서 다른 서버로 업데이트를 보낼 수 있습니다 (적절한 경우). 메시지를 권한있는 서버에 적절하게 전달하십시오.
예,이 경우 특정 엔터티에 대해 하나의 서버가 약간 오래된 것입니다. 그것을 해결하려고하지 마십시오. 그냥 처리하십시오. 엔터티가 약간 오래된 것으로 가정합니다. 엔티티를 정식으로 소유하는 서버에서만 최신 정보가 필요한 로직을 수행하십시오. 엔터티가 다른 엔터티에 영향을 주면 메시지를 보내고 엔터티가 처리되고보기가 업데이트되기 전에 여러 게임 로직 틱이 필요할 수 있다고 가정합니다.
이 설계는 단일 서버를 훨씬 쉽게 스레드 할 수있게합니다. 엔터티는 다른 엔터티를 직접 수정하거나 메시지 만 보내지 않아야하며 로컬 서버 / 스레드 별 프록시 캐시는 약간 오래된 것으로 가정해야합니다.
예를 들어, 엔티티 A가 엔티티 B를 공격하는 경우 B의 수명을 확인하지 않고 0에 도달하면 사망 메시지를 보내십시오. "손상된"메시지를 보내고 B의 권한있는 서버가 처리 한 다음 처리하십시오. 엔티티 A가 그것에 대해 신경 쓰면 나중에 서버 B가 보낸 "엔티티 사망"메시지
크고 확장 가능한 게임 이외의 모든 응용 프로그램에도 동일하게 적용됩니다. 중앙 데이터베이스는 마법의 인스턴트 공유 기술이 아닙니다. 높은 처리량을 유지하려면 두 서버가 메시지와 비동기식으로 메시지와 통신해야합니다. 따라서 AMPQ와 같은 기술의 인기가 있습니다. 데이터베이스는 저장 용이며, 동기화 또는 통신용이 아니기 때문에 통신용으로 사용할 수 있도록 동기화가 필요합니다.
Gamasutra 에 대한 이 기사에 관심이있을 것입니다 . Eve Online 개발자는 하나의 SQL 데이터베이스에서 4 억 명의 활성 플레이어와 게임을 성공적으로 실행하는 방법에 대해 논의합니다.
데이터베이스를 모든 종류의 실시간 공유 세계 모델로 생각하지 마십시오. 알다시피 작동하지 않을 수도 있습니다.
대신 데이터베이스를 자동으로 업데이트 된 저장 파일처럼 취급하십시오. 플레이어가 로그인하거나 로그 아웃하거나 한 영역에서 다른 영역으로 이동할 때 또는 원하지 않는 중요한 일이 발생할 때와 같이 가끔씩 데이터베이스를 업데이트합니다. 서버 충돌시 손실됩니다.
실제 실시간 세계 상태는 원래 예제에서와 같이 게임 서버가 메모리에 보관해야합니다. 이제 수평 적 확장의 요령은 모든 서버가 모든 순간에 모든 것을 알 필요 는 없다는 것 입니다. 플레이어 A는 서버 A에 영역 A를 재생하는 경우 예를 들어, 영역 B를 실행하는 서버 B는 일반적으로 알 필요가 없다 어떤 플레이어 A가 자신의 배낭에 - 그리고,이 경우 않는 말 (어떤 이유로 알 필요를, 영역 B의 플레이어 B는 A)에 일종의 원격 스파이 주문을 캐스팅하기 때문에 다른 서버에 해당 정보를 요청할 수 있습니다 .
서버 B가 플레이어 A의 배낭에 대해 알고 싶을 때 서버에 권한 정보가있는 서버를 알 수 있도록 서버에 명확한 책임을 할당해야합니다. 예를 들어 서버 B가 서버 A에게 " 플레이어 A를 감시하는 사람이 있고 달리 말할 때까지 그들이하는 모든 일에 대해 계속 업데이트하도록 할 수 있도록"일종의 업데이트 구독 메커니즘을 포함하고 싶을 것입니다. 또한 플레이어가 어디에 있든지 플레이어가 알아야 할 중요한 글로벌 이벤트를 위해 일종의 글로벌 방송 시스템을 포함하고 싶습니다. 물론 이러한 이벤트도 데이터베이스에 기록해야하지만 모든 서버에 적극적으로 브로드 캐스트한다는 것은 서버가 업데이트를 위해 데이터베이스를 계속 폴링 할 필요가 없음을 의미합니다.
다른 응답은 데이터베이스를 사용하고 통신에 데이터베이스를 사용하지 않는 방법을 지적하는 훌륭한 작업을 수행했습니다. 살펴볼 수있는 또 다른 측면은 정보를 다른 엔터티와 통신하는 방법에 따라 업데이트를 분류하는 것입니다. 서버와의 통신 범위를 지정하는 대신 메시징을 분배하고 엔티티 간 업데이트 통신을 위해 pubsub 메커니즘을 사용할 수 있습니다. 예를 들어, 가까운 사람에 따라 위치를 다르게 취급 할 수 있습니다.
반경 2 * R (또는 엔티티의 업데이트 속도 및 최대 속도를 기반으로하는 것의 몇 배) 내에있는 엔티티를 주기적으로 스캔하고 엔티티를 다른 엔티티의 정확하거나 부정확 한 위치 피드에 등록하여 엔티티의 위치 정보를 전달할 수 있습니다.
서로 다른 유형의 정보에 대해 서로 다른 전략을 가지거나, 공통 사항을 동일한 메시지 큐로 그룹화하거나, 다른 엔티티로 이동해야하는 메시지에 대해 다른 큐를 가질 수 있습니다. '유용하지 않습니다).