2019년 9월 21일에 [데브루키 521회](https://cafe.naver.com/devrookie/9621)에서 발표한 자료입니다. <!--more--> ## 거대한 단일 MMORPG 서버 [marsettler.com](https://marsettler.com) --- ## 이야기할 내용 1. 거대한 단일 MMORPG 서버 2. 기획 고려사항 3. 서버 고려사항과 해법 4. 데이터베이스 고려사항과 해법 5. 마무리하며 --- ## 1. 거대한 단일 MMORPG 서버 는 정확히 무엇을 말하는 건가요? --- ### MMORPG를 먼저 정의해 봅시다 #### <span class="fragment">대규모 다중 사용자 온라인 롤플레잉 게임</span> <span class="fragment">World of Warcraft,</span> <span class="fragment">EVE Online,</span> <span class="fragment">듀랑고,</span> <span class="fragment">검은사막,</span> <span class="fragment">...</span> --- ### 엔지니어링 측면에서 MMORPG 서버 <span class="fragment">한 지역 내에서 X명의 유저가 상호작용</span> <span class="fragment">X가 어느 정도이면 MMORPG 일까요?</span> <span class="fragment">이 발표는 수백에서 수천명으로 가정합니다</span> --- ### 그러면 거대한 단일 MMORPG 서버란? 일반적인 서버와 가장 큰 차이는 서버들 사이에 있는 <span class="fragment" style="color:LightSkyBlue">물리적인 격리</span> --- ### 일반적인 MMORPG는 성능한계 해소를 위해 물리적으로 격리된 서버를 운영 <span class="fragment" style="color:LightSkyBlue">서로 다른 서버의 유저는 상호작용할 수 없음</span> --- ### 거대한 단일 MMORPG 서버는 이런 상호작용의 한계를 극복한 서버 --- ## 잠깐 용어 정리 - 월드: 게임이 구현한 세상 전체 - 노드: 단일 물리서버 - 클러스터: 노드의 모음 - 지역: 노드 안에 있는 일정 지역 --- ### 사례 1. - 동시에 한 노드에서 플레이 가능한 유저 수: 10,000여명 - 노드간 데이터를 공유하여 언제든지 옮겨 다닐 수 있음 --- ### 사례 2. - 동시에 한 지역에서 플레이 가능한 유저 수: 100명 - 이벤트가 발생할 때마다 100명의 유저를 모아줌 - 가까운 관계의 유저는 이벤트 발생 시 같은 지역을 선택 가능 --- ### 사례 3. - 동시에 한 노드에서 플레이 가능한 유저 수: 거의 무한대? - 좁은 지역에 많은 유저가 모이면 해당 지역의 시간이 느리게 감 --- ### 사례 4. - 한 노드에서 플레이 가능한 유저 수: 100여 명 - 유저가 늘어나면 노드가 늘어나고 노드간 이동이 어느정도 자유로움 --- ### 이 사례 모두를 #### 거대한 단일 MMORPG 서버로 정의하고 #### 일반적인 <span style="color:LightSkyBlue">고려사항</span>과 #### 그 <span style="color:LightSkyBlue">해결법</span>들을 알아보겠습니다. --- ## 2. 기획 고려사항 --- ### 늘어나는 유저에 따른 인구밀도 증가 - 채널 방식 - 다수의 게임이 쉽게 채용하고 있는 방식 - 한 지역을 유저들이 직접 상호작용할 수 없는 여러 채널로 분리 - 절차적 지역 생성 - 지역을 정해진 규칙에 따라 절차적으로 생성 --- ### 특정 자산(부동산, 랭킹 등)의 희소성이 <span style="color:LightSkyBlue">너무 높아짐</span> --- ### 기존의 운영 노하우 적용 불가 <span class="fragment">신규유저의 격차를 줄이기 위한 신서버 오픈 등</span> --- ### 기획 고려사항은 기본만 알아보고 넘어갑니다 --- ## 3. 서버 고려사항과 해법 --- ### 매우 단순화된 서버 구조 클라이언트 🤝 서버 🤝 데이터베이스 --- ### 서버를 확장할 때 선택지 - 스케일 업<span class="fragment"> (단일장비 성능 개선 / 물리적 한계 명확)</span> - 스케일 아웃<span class="fragment" style="color:LightSkyBlue"> (여러 장비를 사용해서 부하분산)</span> --- ### 거대한 단일 MMORPG 서버는 궁극적으로 <span style="color:LightSkyBlue">스케일 아웃</span>을 필요로 함 --- #### HTTP 기반의 서비스들은 게임에 매우 자연스럽게 #### 스케일 아웃을 합니다. <span style="color:LightSkyBlue">왜 그럴까요?</span> --- #### HTTP 기반의 서버는 기본적으로 #### <span style="color:LightSkyBlue">스테이트리스(상태가 없음)</span> ##### <span class="fragment" data-fragment-index="1">엄밀히 따지면 다른 무언가에게 위임</span> ##### <span class="fragment" data-fragment-index="1">(데이터베이스, 캐시 등)</span> --- ### TCP 기반의 MMORPG 서버도 ### <span style="color:LightSkyBlue">스테이트리스</span>하게 만들 순 없을까요? <span class="fragment">상태를 매우 자주 변경하기 때문에 쉽지 않음</span> --- ### 그렇다면 상태변경이 자주 일어나는 부분과 ### 그렇지 않은 부분을 분리하면 어떨까요? --- ### 상태변경이 자주 일어나는 부분 - <span class="fragment">현재 HP</span> - <span class="fragment">지역 내에서 이동중인 발사체</span> - <span class="fragment">남은 총알의 수</span> - <span class="fragment">등등등...</span> --- ### 상태변경이 자주 일어나지 않는 부분 - <span class="fragment">나의 모든 아이템 목록</span> - <span class="fragment">나의 모든 퀘스트 목록</span> - <span class="fragment">하루에 한 번 변경되는 이벤트 목록</span> - <span class="fragment">등등등...</span> --- ### 사실 우리는 근 몇 년간의 개발에서 ### 이미 많은 경험을 쌓음 #### <span class="fragment" style="color:LightSkyBlue">인게임</span> #### <span class="fragment" style="color:LightSkyBlue">아웃게임</span> --- ### 그렇다면 스테이이트풀한 부분(지역)은 ### 어떻게 관리할까요 #### 지역이 다르면 <span style="color:LightSkyBlue">물리적으로 분산된 장비</span>에서 동작 --- ### 지구 지역에서 화성 지역으로의 이동은 ### 어떻게 처리할까요? --- ### 게임의 특성에 따라 달라지지만 ### 일반적으로 둘 중 하나를 선택해야 함 1. 특정 서버가 다운되면 유저 플레이 불가 2. 한 유저가 동시에 두 지역에 있는 것을 허용 --- ### 월드의 구성 - 심리스가 아닌 월드 - 심리스 월드 --- ### 심리스가 아닌 월드 - 지역 간 이동시 멈춤과 로딩이 발생 - 다른 지역 유저끼리 직접적인 상호작용 불가능 --- ### 심리스 월드 - 지역 간 이동시 멈춤과 로딩이 없음 - 다른 지역 유저끼리 직접적인 상호작용 가능 --- ### 심리스 월드 사례를 찾아보면 <span style="color:LightSkyBlue">단일 물리장비</span>에서 여러 코어를 효율적으로 사용하는 것에 초점 <span class="fragment" style="color:LightSkyBlue" data-fragment-index="1">여러 물리장비</span><span class="fragment" data-fragment-index="1">를 이용한 심리스 월드 구현?</span> --- ### 적용범위를 물리엔진으로 ### 한정해서 고민 --- ### 물리엔진 동작(매우 간략화한) 1. 오브젝트를 수집<span class="fragment" style="color:LightSkyBlue">(이 부분만 공유하면?)</span> 2. 물리 데이터를 계산 3. 데이터 기반으로 오브젝트를 업데이트 --- ### 데모 https://github.com/hueypark/marsettler/tree/0.1 --- ### 예상되는 고려사항 - 네트워크 부하 - 멀티쓰레드 환경에서 발생하는 이슈의 극대화 --- ## 4. 데이터베이스 ## 고려사항과 해법 --- ### 데이터베이스의 스케일아웃의 경우 이미 여러 도메인에서 많은 연구가 진행됨 --- ### 많이 사용되는 옵션은 크게 두 가지 - RDBMS 사용하며 스케일아웃(샤딩)과, 분산 트랜잭션 직접 처리 - NoSQL 사용(이벤츄얼 컨시스턴시 고려 필요) --- ### RDBMS의 사용하며 스케일아웃(샤딩)과, 분산 트랜잭션 직접 처리 --- #### 샤딩은 같은 테이블 스키마를 가진 데이터를 #### 다수의 데이터베이스에 분산하여 저장하는 방법 --- ### 고려사항 - 유저의 데이터를 어떤 데이터베이스에 저장? - 특정 데이터베이스에 부하가 몰리지 않게 하는 방법? - 등등... --- ### 그래도 스케일아웃의 경우 ### 범용적인 해법이 어느정도 정해져 있음 <span class="fragment">스케일인이 필요한 상황?</span> <span class="fragment" style="color:LightSkyBlue">(빠르게 도주합니다.)</span> --- ### 분산 트랜잭션 트랜잭션은 <span style="color:LightSkyBlue">논리적 묶여진 단위작업</span>으로 데이터베이스가 제공하는 기능이지만, 2개 이상의 물리장비에서는 직접 구현 필요 --- ### 예: 유저간 거래 1. A 유저 아이템 지급 <span class="fragment" style="color:LightSkyBlue">(직후에 장애가 발생하면?)</span> 2. B 유저 아이템 제거 3. A 유저 돈 감소 4. B 유저 돈 증가 --- ### 이런 방법은 어떨까요? 1. BEGIN: 작업시작 2. END: 작업종료 3. PREPARE: 준비 4. COMMIT: 커밋 --- ### 예: 유저간 거래 2 1. BEGIN - A 유저 아이템 지급하고 비활성화 - A 유저 아이템 활성화 로그 추가 - B 유저 아이템 비활성화 - B 유저 아이템 삭제 로그 추가 - A 유저 돈 감소용 로그 추가 - B 유저 돈 증가용 로그 추가 2. END 3. PREPARE - 로그가 정상적으로 기록되었는지 확인 4. COMMIT - 관련 데이터를 락하고 적용 - 중도에 실패시 로그 기반으로 모두 롤백 --- ### 동작할까요? <span class="fragment">실제 서비스에는 더 많은 예외상황이 있음</span> <span class="fragment">개발 난이도 급상승</span> --- ### NoSQL 사용 - NoSQL을 한 마디로 정의하긴 어려움 - 일반적인 특징으로 수평 확장이 가능하지만 <span style="color:LightSkyBlue">이벤츄얼 컨시스턴시</span>에 대한 고려가 필요 --- ### 이벤츄얼 컨시스턴시? #### 한국어로는 최종 일관성이나, #### 궁극적 일관성으로 불리기도 함 #### 뭔가 멋져보이는 이름이지만 사람 잡는 동작방식 --- ### 극단적인 예 1. 보유 골드 1000 - 1번 서버의 사냥으로 골드 100을 획득 1100 - 2번 서버의 유저에게서 100원짜리 검 구매 900 2. 음? --- #### 이처럼 단순한 예는 프로그래머가 통제할 수 있겠지만 #### MMORPG는 매우 다양한 컨텐츠를 가지고 있음 --- [이벤츄얼 컨시스턴시 풍자](https://www.reddit.com/r/Database/comments/avz1xk/eventual_consistency/) --- ### 어떤 방식을 사용하던 ### 이 문제들을 모두 해결해야 함 #### <span class="fragment">누가?</span> <span class="fragment">프로그래머가!</span> #### <span class="fragment" style="color:LightSkyBlue"> 그러면 기능은 누가?</span> --- ### 또 다른 해법 --- ### 카크로치디비! #### 오픈소스로 작성된, 클라우드 기반의 SQL 데이터베이스 #### 스케일 아웃, ACID 트랜잭션의 강한 일관성, SQL 제공 https://github.com/cockroachdb/cockroach --- ### NewSQL이라고 불리는 ### 유사한 제품이 여러 개 있음 <span class="fragment" style="color:LightSkyBlue">선택은 당신의 몫</span> <span class="fragment" style="color:LightSkyBlue">NoSQL이라고 불리는 데이터베이스들이 얼마나 서로 다른지 고려해보기 바랍니다.</span> --- ### 마무리하며 1. 거대한 단일 MMORPG 서버 2. 기획 고려사항 3. 서버 고려사항과 해법 4. 데이터베이스 고려사항과 해법 --- ### 누구나 그럴싸한 계획을 가지고 있다. 얼굴에 한방 쳐맞기 전까지는. --- ## 감사합니다. [marsettler.com](https://marsettler.com)