[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기강 민우
펄어비스의 MMORPG, 검은사막에 적용되어있는 AI 네비게이션 기능은 VOXEL 기반으로 자체 개발한 엔진을 이용해 구현되어 있습니다. 기존의 대다수 상용 라이브러리들이 네비 메쉬라고 하는 이동가능한 평면을 표현하는 폴리곤 기반의 데이터를 이용해 길찾기를 수행해주는 것에 비해 근간이 다릅니다. 이 강연에서는 검은사막의 네비게이션 엔진을 구현하고, 서버 / 클라이언트에 적용하면서 얻게된 노하우와 적용된 결과물들을 소개합니다.
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기강 민우
펄어비스의 MMORPG, 검은사막에 적용되어있는 AI 네비게이션 기능은 VOXEL 기반으로 자체 개발한 엔진을 이용해 구현되어 있습니다. 기존의 대다수 상용 라이브러리들이 네비 메쉬라고 하는 이동가능한 평면을 표현하는 폴리곤 기반의 데이터를 이용해 길찾기를 수행해주는 것에 비해 근간이 다릅니다. 이 강연에서는 검은사막의 네비게이션 엔진을 구현하고, 서버 / 클라이언트에 적용하면서 얻게된 노하우와 적용된 결과물들을 소개합니다.
NHN NEXT 게임 서버 프로그래밍 강의 자료입니다. 최소한의 필요한 이론 내용은 질문 위주로 구성되어 있고 (답은 학생들 개별로 고민해와서 피드백 받는 방식) 해당 내용에 맞는 실습(구현) 과제가 포함되어 있습니다.
참고로, 서버 아키텍처에 관한 과목은 따로 있어서 본 강의에는 포함되어 있지 않습니다.
NHN NEXT 게임 서버 프로그래밍 강의 자료입니다. 최소한의 필요한 이론 내용은 질문 위주로 구성되어 있고 (답은 학생들 개별로 고민해와서 피드백 받는 방식) 해당 내용에 맞는 실습(구현) 과제가 포함되어 있습니다.
참고로, 서버 아키텍처에 관한 과목은 따로 있어서 본 강의에는 포함되어 있지 않습니다.
Klaytn 성능 향상 대장정 - 1000만 account 극복기
블록체인은 네트워크 상에서 상태가 합의를 이루고 복제되어야하는 제한 조건 때문에 전통적인 데이터베이스에 비해 떨어지는 성능을 보인다. 또한 Klaytn에서는 각 어카운트의 정보를 저장하기 위해 Merkle Partricia Trie를 사용하는데, Merkle Partricia Trie의 성능은 전체 어카운트 개수가 늘어날수록 떨어진다. 1000만개 이상의 어카운트가 존재할 때에도 성능 저하를 최소화 하기 위해 1) 일반적인 성능 향상과 더불어 2) 어카운트 개수 증가에 의한 성능 저하를 최소화하는 작업을 동시에 진행하였다. 본 세션에서는 블록체인의 성능 병목 구간에 대한 설명과 더불어 1) Consensus Layer, 2) In-memory Layer, 3) Persistent Layer 의 각 레이어 별로 적용한 최적화 기법들, 그리고 그 사이에 마주친 문제들에 대해 공유하는 시간을 갖는다.
13. 트랜잭션
명사
• 1. [C] ~ (between A and B) 거래, 매매
– financial transactions between companies
기업들 간의 금융 거래
– commercial transactions
상업적인 거래
• 2. [U] ~ of sth (격식) 처리 (과정)
– the transaction of government business
정부 사업 처리
출처:OxfordAdvancedLearner'sEnglish-KoreanDictionary
14. 트랜잭션 – 예: 계좌 이체
태민이 종현에게 계좌 이체를 할 때
• 태민 계좌만 줄어들면 안되고
종현 계좌만 늘어나도 안되고 [원자성]
• 태민의 계좌 잔고 < 0 이 되어도 안되고 [일관성]
마이너스 통장도 한도가 있음..
• 이체 중에 통장을 해지할 수 없어야 하고 [고립성]
• 계좌 이체가 일단 성공하고 나면
돈이 맘대로 되돌아가거나 하면 안됨 [지속성]
15. 트랜잭션
• 원자성 (Atomicity)
• 일관성 (Consistency)
• 고립성 (Isolation)
• 지속성 (Durability)
From 위키백과 ‘ACID’
원자성 + 고립성 위주로 봅시다
16. 트랜잭션 - 원자성
트랜잭션과 관련된 작업들이
모두 수행되든지 아예 아무것도 실행이 안됨을
보장하는 능력
원자성이 위배된 예:
보석으로 골드를 샀는데
보석만 줄어들고 골드는 안 늘어났다
17. 트랜잭션 - 고립성
트랜잭션을 수행 중
다른 트랜잭션의 연산 작업이 끼어들지 못하도록
보장하는 것
고립성이 위배된 예:
부스터를 뜯는(카드 5장을 추가하는) 트랜잭션 동안
첫번째 카드를 팔아버리는 트랜잭션이 치고 들어와서 실행되었다.
부뜯 트랜잭션을 롤백할 수가 없어진다..
19. 분산 데이터베이스 트랜잭션
네트워크로 물린 여러 데이터베이스가 참여
태민의 카드 데이터는 이 DB에 있고
종현의 카드 데이터는 저 DB에 있다면
카드를 거래하면서 카드가 없어지거나 복사되지 않는다는 보장을
어떻게 하나?
20. 분산 데이터베이스 트랜잭션
DBMS가 안 해주나요? 21세기인데? → 해줍니다
XA라는 것이 있다
• 커밋할 준비(무결성 확인)와 실제 커밋(디스크에 쓰기)을 분리
• DB가 여럿일 때에도 고립성을 확보해주지만
• 장애 상황(서버가 꺼졌다!)에서 원자성을 보장하지는 않는다
• 그리고 매우 느리다고 함
DB#1에서 카드 제거하는 트랜잭션이 커밋됐으나
DB#2에서 카드 생성하는 트랜잭션은 커밋되지 않을 수 있다
21. 그럼 어떡함?
• 우리가 직접 만들면 된다
애플리케이션 레벨 분산 트랜잭션
• 어떻게 만드나요?
그걸 지금부터 설명합니다
22. 잠깐 기초 용어
• 커밋: 최종 확정하기. 도장 꽝꽝
• 롤백: 없던 일로 하기.
트랜잭션은 커밋 혹은 롤백으로 끝난다
28. 두 가지 접근
1. 작업하는 동안 다른 동작을 못하게 한다
= 비관적 동기화 (락 기반 동기화)
2. 일단 진행하고, 문제가 생기면 롤백한다
= 낙관적 동기화 (예: 트랜잭셔널 메모리)
29. 비관적 동기화의 문제
“작업하는 동안 다른 동작을 못하게 한다”
• 모든 DB 변경에서 락을 잡아야 한다
• 못하게 할 수 없는 현상(DB/게임서버 다운)이 있다
일반적으로 락 경합에 따른 성능 저하를 이야기하지만
락을 유저당 하나씩 있는 것으로 설정하면
이 경우 거래중인 유저들은 거래 말고 다른 동작을 시도하지는 않으므로
딱히 성능이 떨어지지는 않을 것이다
30. 두 가지 접근
1. 작업하는 동안 다른 동작을 못하게 한다
= 비관적 동기화 (락 기반 동기화)
2. 일단 진행하고, 문제가 생기면 롤백한다
= 낙관적 동기화 (예: 트랜잭셔널 메모리)
31. 두 가지 접근
1. 작업하는 동안 다른 동작을 못하게 한다
= 비관적 동기화 (락 기반 동기화)
2. 일단 진행하고, 문제가 생기면 롤백한다
= 낙관적 동기화 (예: 트랜잭셔널 메모리)
32. 낙관적 동기화의 문제
“문제가 생기면 롤백한다”
• 애플리케이션 레벨에서 롤백을 구현해야 한다
• 일반적인 롤백 구현이 가능하긴 한가?
→ 문제 영역을 쪼개보자
33. 두 단계로 나눠보자
• 퍼스트 로컬 트랜잭션(퍼스트 LT)
– 실패할 가능성이 있는 것
– 안전하게 롤백할 수 있어야 함
– 예: 아이템 제거, 골드 감소
• 세컨드 로컬 트랜잭션(세컨드 LT)
– 실패할 가능성이 없는 것
– 안전하게 롤백할 수 없어도 된다
– 예: 아이템 추가, 골드 증가
34. 대강의 절차
1. 모든 참여자(DB)들에게 퍼스트 LT를 실행
2. 모든 퍼스트 LT가 성공하고 나면
세컨드 LT를 실행한다
3. 퍼스트 LT가 하나라도 실패하면
전부 롤백한다
36. 현실 거래에 비유
1. 모든 참여자(DB)들에게 퍼스트 LT를 실행
= 거래 대상이 되는 재산을 가압류한다
2. 모든 퍼스트 LT가 성공하고 나면
세컨드 LT를 실행한다
= 모든 참여자들의 재산을 가압류 성공하면 거래를 마저 진행할 수 있는 것이다
3. 퍼스트 LT가 하나라도 실패하면
전부 롤백한다
= 가압류를 풀어주고 없던 일로 한다
40. 아이디어
롤백할 때 해야 할 일과 세컨드 LT할 때 해야 할 일을
SQL 쿼리 텍스트로 만들어서
각 DB의 퍼스트 LT 시점에 기록한다
41. 왜 SQL 쿼리 텍스트로…?
• 어떤 응용에서도 변하지 않는 부분 = 시스템 코드
예) 퍼스트 LT 중 하나라도 실패하면 롤백하는 규칙,
중단된 분산 트랜잭션이 있으면 이어서 실행해주는 코드, …
• 응용에 따라 변하는 부분 = 로직 코드
예) 카드 거래, 쿠폰 사용, …
42. 1. 빼앗아야 할 자원을 제거한다 = 퍼스트 LT
2. 퍼스트 LT를 롤백할 때 해야 할 일을
SQL쿼리로 기록해둔다
3. 세컨드 LT를 해야 할 때 해야 할 일을
SQL쿼리로 기록해둔다
로컬트랜잭션으로묶어서실행
로직 코드: 각각의 DB에 대해,
43. 1. 빼앗아야 할 자원을 제거한다 = 퍼스트 LT
2. 퍼스트 LT를 롤백할 때 해야 할 일을
SQL쿼리로 기록해둔다
3. 세컨드 LT를 해야 할 때 해야 할 일을
SQL쿼리로 기록해둔다
로컬트랜잭션으로묶어서실행
로직 코드: 각각의 DB에 대해,
= 넘겨주기로 한 재산을 가압류하는 셈
거래가 취소되면 가압류를 풀면 된다 = 롤백 쿼리 실행
거래중에는 내가 함부로 처분못한다 = 실제 행을 지워버렸으므로
44. 1. 빼앗아야 할 자원을 제거한다 = 퍼스트 LT
2. 퍼스트 LT를 롤백할 때 해야 할 일을
SQL쿼리로 기록해둔다
3. 세컨드 LT를 해야 할 때 해야 할 일을
SQL쿼리로 기록해둔다
로컬트랜잭션으로묶어서실행
로직 코드: 각각의 DB에 대해,
= 넘겨받아야 할 재산을 계약서에 명시하는 셈
아직 내 소유인 것은 아니다 (실제 행이 추가되지 않았다)
계약서에 쓰인 대로 실행하면 재산이 내 소유가 된다
45. 시스템 코드 A: 실행 파트
1. GET_LOCK("dt_lock" + dt_id)
2. 각각의 DB에 로직 코드를 호출해서 퍼스트 LT를 실행한다
3-1. 하나라도 실패하면,
모든 DB에 대해 롤백을 실행한다
3-2. 퍼스트 LT 모두 성공하면,
모든 DB에 대해 세컨드 LT를 실행한다
4. RELEASE_LOCK("dt_lock" + dt_id)
매 스텝마다 현재 dt_id, 진행상태, 참여하는 DB를 기록한다
→ dt_catalog 테이블
46. 시스템 코드 B: 복구 파트
1. 끝나지 않은 분산 트랜잭션이 있는지 dt_catalog를 계속 감시
(진행하던 게임서버가 오류로 죽어버린 상황을 위해서)
2. 있으면 GET_LOCK을 시도해본다
3-1. 성공하면 이어서 마무리한다
(모두 롤백 혹은 모두 세컨드 LT)
3-2. 실패하면 그냥 넘어간다
(누군가 하고 있다는 뜻이니)
47. 중간 정리
• 로컬 트랜잭션을 여러 번 사용해서
애플리케이션 레벨 분산 트랜잭션을 구현함
• 퍼스트 LT: 재산을 압류해서 SQL 텍스트로 바꿈
• 퍼스트 LT 하나라도 실패하면 롤백
• 모든 참여 DB에 퍼스트 LT가 성공하고 나면
세컨드 LT를 실행하여 재산을 재부여
61. 상황
• 타이트한 일정, 시행착오 여유 없음
• MariaDB+애플리케이션 레벨 샤딩 먼저 결정
• 거래는 나중에 구현
62. 마비노기 듀얼의 분산 트랜잭션
• 로컬 트랜잭션을 여러 번 사용해서
애플리케이션 레벨 분산 트랜잭션을 구현함
• 퍼스트 LT: 재산을 압류해서 SQL 텍스트로 바꿈
• 퍼스트 LT 하나라도 실패하면 롤백
• 모든 참여 DB에 퍼스트 LT가 성공하고 나면
세컨드 LT를 실행
63. 이러면 뭐가 좋나
• 애플리케이션 레벨 분산 트랜잭션을
라이브러리로 구현
• 로직에서는 라이브러리의 가이드라인 따라 작성
– 퍼스트 LT 코드만 짜면 되고
– 세컨드 LT, 롤백은 라이브러리가 실행
(SQL 텍스트로 저장되어 있으니까 로직에 무관)
• 만만하게 사용할 수 있는 것은 아니더라…
64. 성능 괜찮나?
• 아직 라이브를 겪어보지 못함
• 유저간 거래가 그렇게까지 빈번할 거 같지 않다