Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[NDC18] 야생의 땅 듀랑고의 데이터 엔지니어링 이야기: 로그 시스템 구축 경험 공유

[NDC18] 야생의 땅 듀랑고의 데이터 엔지니어링 이야기: 로그 시스템 구축 경험 공유

NDC18에서 발표하였습니다.

자막 포함 슬라이드 -> https://hyojun.me/~ndc18-caption

Slideshare에서 보기 -> https://www.slideshare.net/ssuser380e9c/ndc18-95524337

Hyojun Jeon

April 24, 2018
Tweet

More Decks by Hyojun Jeon

Other Decks in Programming

Transcript

  1. 327

  2. 듀랑고의 로그 시스템 • 로그를 버리지 않고 적재 • 실시간

    로그 조회 및 검색 • 분석 및 시각화 • 관리부담 최소화
  3. 듀랑고의 로그 시스템 • 로그를 버리지 않고 적재 • 실시간

    로그 조회 및 검색 • 분석 및 시각화 • 관리부담 최소화 → 론칭 이후 3개월간 약 110TB
  4. 듀랑고의 로그 시스템 • 로그를 버리지 않고 적재 • 실시간

    로그 조회 및 검색 • 분석 및 시각화 • 관리부담 최소화 → 론칭 이후 3개월간 약 110TB → 5초 안에 조회 + 검색
  5. 듀랑고의 로그 시스템 • 로그를 버리지 않고 적재 • 실시간

    로그 조회 및 검색 • 분석 및 시각화 • 관리부담 최소화 → 론칭 이후 3개월간 약 110TB → 5초 안에 조회 + 검색 → 대규모 로그도 빠르게 분석하고 시각화까지
  6. 듀랑고의 로그 시스템 • 로그를 버리지 않고 적재 • 실시간

    로그 조회 및 검색 • 분석 및 시각화 • 관리부담 최소화 → 론칭 이후 3개월간 약 110TB → 5초 안에 조회 + 검색 → 대규모 로그도 빠르게 분석하고 시각화까지 → 혼자서도 여유롭게
  7. #1 로그는 쌓아서 뭐하나 #2 로그 시스템의 목표 #3 로그

    시스템 아키텍처 #4 ‘잘’ 사용하기 #5 개선할 점
  8. 서비스 운영을 위한 로그 조회 아이템이 없어졌어요! ” “ 실제

    이력을 확인해보아야 한다. 실제 아이템 획득 여부, 제작 재료 소비 여부 등
  9. 주요 지표 추출 • 월/일 별 활성 유저수 • 재방문율,

    플레이 시간 • 각종 통계 추출 • 등등 ...
  10. 데이터 기반의 의사결정 → 섬 인구수 별 재방문율 지표 •

    적정 인구수 산정 • 업데이트 방향 설정 • 초반 가이드 개선 • 등등 ...
  11. 데이터 기반의 의사결정 → 섬 인구수 별 재방문율 지표 →

    플레이 유형 클러스터링 • 적정 인구수 산정 • 업데이트 방향 설정 • 초반 가이드 개선 • 등등 ...
  12. 데이터 기반의 의사결정 → 섬 인구수 별 재방문율 지표 →

    플레이 유형 클러스터링 → 이탈구간 분석, 레벨별 활성 유저수 • 적정 인구수 산정 • 업데이트 방향 설정 • 초반 가이드 개선 • 등등 ...
  13. 데이터 기반의 의사결정 → 섬 인구수 별 재방문율 지표 →

    이탈구간 분석, 레벨별 활성 유저수 • 적정 인구수 산정 • (광영님 분석사례 추가) • 초반 가이드 개선 • 등등 ... 낯선 게임인데 익숙해야 하고, 알려줄 게 많은데 재미있어야 한다고요? - <야생의 땅: 듀랑고> 초반 플레이 변천사 강임성 님 / 4월 26일 오전 11시
  14. A섬에서 채집할 때 오류가 자꾸 난대요! 로그를 못 찾겠어요 ㅠㅠ

    (호스트마다 SSH 접속해서 로그파일들 열어보다가…)
  15. A섬에서 채집할 때 오류가 자꾸 난대요! 로그를 못 찾겠어요 ㅠㅠ

    (호스트마다 SSH 접속해서 로그파일들 열어보다가…)
  16. • 많은 수의 게임 서버로부터 시스템 로그를 모두 수집 •

    어떤 서버에서 어떤 에러가 발생했는 지 • 코드가 어떤 경로로 호출되었는지 Traceback 을 남김 • 오류코드는 해당 시점의 서버 로그를 찾기 위한 단서 시스템 로그 조회
  17. 게임플레이 로그 • 서비스 운영 • 의사결정을 위한 분석 •

    주요 지표 추출 시스템 로그 • 개발자 생산성 확대 • 빠른 이슈 대응
  18. 로그 시스템의 요구사항 • 복잡한 게임 시스템 → 복잡한 로그

    스키마 • 게임 플레이로그 + 시스템 로그 → 대규모 로그 발생 • 대규모 분석 • 빠른 조회 및 검색
  19. 별도의 RDB를 사용하기도 … • 스키마의 변동이 없는 로그 ex)

    플레이어 접속 로그 • 높은 신뢰도가 요구되는 로그 ex) 결제로그
  20. 로그 조회가 안 돼요! 로그가 없어요! • 시스템이 죽으면 로그는

    유실됨 높은 가용성 → 높은 가용성이 보장되어야
  21. 실시간 조회 • 빠른 조회는 곧 생산성 향상과 직결 •

    • 검색이 가능해야 한다. 빠르고 쉽게 조회 가능해야한다.
  22. 실시간 조회 • 빠른 조회는 곧 생산성 향상과 직결 •

    • 검색이 가능해야 한다. 빠르고 쉽게 조회 가능해야한다.
  23. 실시간 조회 • 빠른 조회는 곧 생산성 향상과 직결 •

    • 검색이 가능해야 한다. 빠르고 쉽게 조회 가능해야한다. 로그 발생 조회 5초 이내
  24. 실시간 조회 • 빠른 조회는 곧 생산성 향상과 직결 •

    • 검색이 가능해야 한다. 빠르고 쉽게 조회 가능해야한다. 로그 발생 조회 5초 이내
  25. 분석 및 시각화 • 예) 지난 3개월 간 유저들이 획득/소비한

    티스톤의 양 • 대규모 로그도 빠르게 분석 • SQL 사용 가능 • 그래프도 알아서 그려줬으면
  26. 분석 및 시각화 • 예) 지난 3개월 간 유저들이 획득/소비한

    티스톤의 양 • 대규모 로그도 빠르게 분석 • SQL 사용 가능 • 그래프도 알아서 그려줬으면
  27. • 오픈소스 데이터 수집기 • C + Ruby • 다양한

    플러그인 • 간편한 설정 Fluentd Fluentd
  28. • 오픈소스 데이터 수집기 • C + Ruby • 다양한

    플러그인 • 간편한 설정 빠르고 가볍다 Fluentd Fluentd
  29. • 오픈소스 데이터 수집기 • C + Ruby • 다양한

    플러그인 • 간편한 설정 빠르고 가볍다 Kinesis 플러그인 지원 Fluentd Fluentd
  30. • 하나의 호스트에는 여러 개의 노드가 실행 • 노드들의 로그를

    수집하는 하나의 Fluentd Fluentd 호스트 노드 노드 노드 호스트 = 머신 노드 = 프로세스
  31. • 하나의 호스트에는 여러 개의 노드가 실행 • 노드들의 로그를

    수집하는 하나의 Fluentd 로그 수집 에이전트의 역할 Fluentd 호스트 노드 노드 노드 호스트 = 머신 노드 = 프로세스
  32. • AWS의 관리형 서비스 • 스트리밍 데이터를 저장하는 큐 역할

    • 최대 7일동안 데이터 보존 • 데이터 유입량에 따라 무중단 확장 및 축소가능 AWS Kinesis Data Stream Kinesis
  33. • AWS의 관리형 서비스 • 스트리밍 데이터를 저장하는 큐 역할

    • 최대 7일동안 데이터 보존 • 데이터 유입량에 따라 무중단 확장 및 축소가능 AWS Kinesis Data Stream → 높은 가용성 Kinesis
  34. • AWS의 관리형 서비스 • 스트리밍 데이터를 저장하는 큐 역할

    • 최대 7일동안 데이터 보존 • 데이터 유입량에 따라 무중단 확장 및 축소가능 AWS Kinesis Data Stream → 높은 가용성 Kinesis
  35. • AWS의 관리형 서비스 • 스트리밍 데이터를 저장하는 큐 역할

    • 최대 7일동안 데이터 보존 • 데이터 유입량에 따라 무중단 확장 및 축소가능 AWS Kinesis Data Stream → 높은 가용성 → 언제든 복구가능 Kinesis
  36. • AWS의 관리형 서비스 • 스트리밍 데이터를 저장하는 큐 역할

    • 최대 7일동안 데이터 보존 • 데이터 유입량에 따라 무중단 확장 및 축소가능 AWS Kinesis Data Stream → 높은 가용성 → 언제든 복구가능 Kinesis
  37. → 로그 유입량에 따라 유연하게 대응가능 • AWS의 관리형 서비스

    • 스트리밍 데이터를 저장하는 큐 역할 • 최대 7일동안 데이터 보존 • 데이터 유입량에 따라 무중단 확장 및 축소가능 AWS Kinesis Data Stream → 높은 가용성 → 언제든 복구가능 Kinesis
  38. • AWS의 관리형 서비스 • 스트리밍 데이터를 저장하는 큐 역할

    • 최대 7일동안 데이터 보존 • 데이터 유입량에 따라 무중단 확장 및 축소가능 AWS Kinesis Data Stream → 높은 가용성 → 언제든 복구가능 Kinesis → 로그 유입량에 따라 유연하게 대응가능
  39. • 서버리스 컴퓨팅 서비스 • 자동으로 확장 및 축소 •

    • 데이터를 처리하는 단계 AWS Lambda Lambda Kinesis stream 트리거 가능
  40. • 서버리스 컴퓨팅 서비스 • 자동으로 확장 및 축소 •

    • 데이터를 처리하는 단계 AWS Lambda → 인프라 관리 불필요 Lambda Kinesis stream 트리거 가능
  41. • 서버리스 컴퓨팅 서비스 • 자동으로 확장 및 축소 •

    • 데이터를 처리하는 단계 AWS Lambda → 인프라 관리 불필요 Lambda Kinesis stream 트리거 가능
  42. • 무한 용량 • 같은 리전의 EC2에서 높은 전송속도 •

    높은 요청 빈도에 대하여 자동확장 • 같은 리전에서 데이터 전송 비용 무료 • 99.99% 가용성 / 99.999999999% 내구성 AWS S3 S3
  43. • 무한 용량 • 같은 리전의 EC2에서 높은 전송속도 •

    높은 요청 빈도에 대하여 자동확장 • 같은 리전에서 데이터 전송 비용 무료 • 99.99% 가용성 / 99.999999999% 내구성 AWS S3 S3
  44. • 무한 용량 • 같은 리전의 EC2에서 높은 전송속도 •

    높은 요청 빈도에 대하여 자동확장 • 같은 리전에서 데이터 전송 비용 무료 • 99.99% 가용성 / 99.999999999% 내구성 AWS S3 S3
  45. S3 Lambda ES Lambda Kinesis 최대 5개의 읽기 트랜잭션 제한

    =최대 5개의 Lambda 트리거 가능 (+ 읽기 처리량도 고려해야함)
  46. • Lucene 기반의 분산 검색엔진 • 역인덱스를 이용한 빠른 검색가능

    • • AWS Elasticsearch Service Elasticsearch ES Kibana 시각화 도구 제공
  47. • Lucene 기반의 분산 검색엔진 • 역인덱스를 이용한 빠른 검색가능

    • • AWS Elasticsearch Service Elasticsearch ES Kibana 시각화 도구 제공
  48. • Lucene 기반의 분산 검색엔진 • 역인덱스를 이용한 빠른 검색가능

    • • AWS Elasticsearch Service Elasticsearch ES 완전관리형 서비스 = 가용성, 확장성 등 Kibana 시각화 도구 제공
  49. ES 로그가 늘어날 수록 유지비용 증가 → 최근 3개월의 로그만

    저장 (그 이후는 S3에 저장된 로그를 사용)
  50. • 클러스터 컴퓨팅 엔진 • • Python, Scala, R, Java

    언어지원 • 다양한 모듈 지원 (SparkSQL, MLlib 등) Apache Spark Spark 인 메모리 데이터 처리
  51. • 클러스터 컴퓨팅 엔진 • • Python, Scala, R, Java

    언어지원 • 다양한 모듈 지원 (SparkSQL, MLlib 등) Apache Spark Spark 인 메모리 데이터 처리 → 빠르다!
  52. • 클러스터 컴퓨팅 엔진 • • Python, Scala, R, Java

    언어지원 • 다양한 모듈 지원 (SparkSQL, MLlib 등) Apache Spark Spark 인 메모리 데이터 처리 → 빠르다!
  53. • • 다양한 인터프리터 사용가능 • 쉬운 시각화 Apache Zeppelin

    Zeppelin 대화식 분석이 가능한 웹 기반 노트북
  54. • • 다양한 인터프리터 사용가능 • 쉬운 시각화 Apache Zeppelin

    Zeppelin 대화식 분석이 가능한 웹 기반 노트북
  55. • • 다양한 인터프리터 사용가능 • 쉬운 시각화 Apache Zeppelin

    → Spark! Zeppelin 대화식 분석이 가능한 웹 기반 노트북
  56. • Spark 클러스터를 손쉽게 구성 • 스팟 인스턴스 사용가능 •

    쉬운 확장 및 축소 AWS EMR EMR + Zeppelin 10개 인스턴스로 5분 1개 인스턴스로 50분
  57. • Spark 클러스터를 손쉽게 구성 • 스팟 인스턴스 사용가능 •

    쉬운 확장 및 축소 AWS EMR EMR + Zeppelin 10개 인스턴스로 5분 1개 인스턴스로 50분 비용
  58. • Spark 클러스터를 손쉽게 구성 • 스팟 인스턴스 사용가능 •

    쉬운 확장 및 축소 AWS EMR EMR + Zeppelin 10개 인스턴스로 5분 1개 인스턴스로 50분 비용
  59. Zeppelin의 노트북 스케줄 기능 ? 실패 시 자동 재시도 완료

    시 클러스터 반납 Ad-hoc 분석용으로만 사용
  60. S3 Lambda Zeppelin Spark AWS EMR DataPipeline 게임 서버 Fluentd

    Lambda Kinesis ES 5초 이내 1. 로그를 확인하기 까지
  61. S3 Lambda Lambda ES Zeppelin Spark AWS EMR DataPipeline 게임

    서버 Fluentd 2. 로그 유입량이 증가하면? Kinesis 확장 포인트
  62. • 도쿄 리전 기준 • 초당 1000개 로그 유입, 각

    로그는 2KB(월 5TB 정도) • Kinesis 샤드 2개 + 데이터 PUT 비용 • Lambda (처리시간 1초) → 약 $90 → 약 $20 3. Kinesis + Lambda 월 유지비용 → 월 $110 정도로 유지 비용(저장비용 제외)
  63. 게임 서버 Fluentd S3 Lambda Lambda Kinesis ES DataPipeline 4.

    빠르게 분석하고 싶을 때 확장 포인트 Zeppelin Spark AWS EMR
  64. 5. 대규모 분석 비용 • 모든 로그에 대하여 • r4.8xlarge

    X 10 스팟 인스턴스, 도쿄 리전 기준 • 생성된 모든 섬의 개수 • 가장 많이 채집된 자원(10위까지) • 모든 섬의 날짜별 일일 활성 유저수 → 5분 = $1 미만 → 10분 = 약$1 → 15분 = 약 $ 1.3 프로비저닝 시간 제외, 2018년 4월 24일 기준
  65. 게임 서버 Fluentd S3 Lambda Lambda ES Zeppelin Spark AWS

    EMR DataPipeline Kinesis 확장 포인트 Kinesis 샤드 개수는 어떻게 결정하나요?
  66. Lambda Iterator age 증가하면 안됨 가장 최근에 처리한 레코드가 Kinesis에

    기록된 시간과 Lambda가 레코드를 받은 시간차이
  67. Shard 1 Kinesis Lambda Shard 2 Shard 3 1초 마다

    배치 처리 샤드 개수 증가 Lambda 동시실행
  68. Kinesis – Lambda 처리속도를 높이는 방법 1. Kinesis stream의 샤드

    개수를 증가시킨다. 2. Lambda의 가용 메모리를 증가시킨다. (Lambda는 가용 메모리 크기에 따라 CPU 성능이 조절됨)
  69. 로그파일 포맷: JSON • 복잡한 게임 시스템 → 복잡한 로그

    스키마 • Lambda는 최대 1000개의 로그를 하나의 파일로 저장 (Kinesis 샤드의 초당 최대 쓰기 개수)
  70. 엄청나게 많은 파일 개수 → 네트워크 오버헤드 로그파일 포맷: JSON

    • 복잡한 게임 시스템 → 복잡한 로그 스키마 • Lambda는 최대 1000개의 로그를 하나의 파일로 저장 (Kinesis 샤드의 초당 최대 쓰기 개수)
  71. Parquet • 스키마를 가진 컬럼형 저장 포맷 • 복잡한 중첩

    데이터 구조도 지원 • 기본적으로 Snappy 압축 • Column projection • Predicate pushdown
  72. Parquet → 네트워크 트래픽 감소 • 스키마를 가진 컬럼형 저장

    포맷 • 복잡한 중첩 데이터 구조도 지원 • 기본적으로 Snappy 압축 • Column projection • Predicate pushdown
  73. Column projection 4월 1일에 접속한 레벨 60의 플레이어 수 SELECT

    COUNT(DISTINCT(player_entity_id)) FROM PlayerEntered_asia_a WHERE __date="2018-04-01" AND player_level=60
  74. Table Partitioning → 네트워크 트래픽 감소 • 데이터 스캔 범위를

    제한가능 • 저장경로에 '<key>=<value>' 형태로 분리
  75. SELECT COUNT(DISTINCT(player_entity_id)) FROM PlayerEntered_asia_a WHERE __date="2018-04-01" AND player_level=60 실제 컬럼처럼

    사용가능 Table Partitioning WHERE __date="2018-04-01" s3://<bucket>/<schema>/__date=<yyyy-mm-dd>/<filename>
  76. SELECT COUNT(DISTINCT(player_entity_id)) FROM PlayerEntered_asia_a WHERE __date="2018-04-01" AND player_level=60 쿼리 플랜에서

    동작을 확인할 수 있다. Table Partitioning PartitionFilters: [isnotnull(__date#53), (cast(__date#53as string)=2018-04-01)]
  77. 로그 스키마 관리 • 로그는 다양한 스키마를 가진다. • 접속로그,

    채집로그, 구매로그 등 • 새로운 스키마는 언제든지 추가될 수 있어야 한다. • 스키마 변경 시 적재된 로그를 모두 마이그레이션할 수 없다.
  78. 로그 스키마 관리 • 로그는 다양한 스키마를 가진다. • 접속로그,

    채집로그, 구매로그 등 • 새로운 스키마는 언제든지 추가될 수 있어야 한다. • 스키마 변경 시 적재된 로그를 모두 마이그레이션할 수 없다. → 컬럼 추가만 가능! 하위호환성을 유지하여야 한다.
  79. 로그 스키마 업데이트 1. 스키마 별 Class 추가 또는 업데이트

    2. 배포 시 Spark StructType JSON 포맷으로 추출 3. AWS S3에 저장 4. Parquet 변환 배치잡에서 매번 스키마 정보를 읽고 수행
  80. 로그 스키마 업데이트 1. 스키마 별 Class 추가 또는 업데이트

    2. 배포 시 Spark StructType JSON 포맷으로 추출 3. AWS S3에 저장 4. Parquet 변환 배치잡에서 매번 스키마 정보를 읽고 수행
  81. 로그 스키마 업데이트 schema = StructType.fromJson(schema_json) Parquet 변환 시 로드

    1. 스키마 별 Class 추가 또는 업데이트 2. 배포 시 Spark StructType JSON 포맷으로 추출 3. AWS S3에 저장 4. Parquet 변환 배치잡에서 매번 스키마 정보를 읽고 수행 PySpark
  82. EMR Spark 클러스터 스펙 • 메모리가 중요하므로 r4 타입을 선호

    • 작은 인스턴스 4개 보다 큰 인스턴스 1개로 • 좋은 인스턴스가 네트워크 속도도 더 빠르다 • EMR이 YARN 컨테이너에 할당하는 메모리 비율이 더 크다
  83. EMR Spark 클러스터 스펙 • 메모리가 중요하므로 r4 타입을 선호

    • 작은 인스턴스 4개 보다 큰 인스턴스 1개로 • 좋은 인스턴스가 네트워크 속도도 더 빠르다 • EMR이 YARN 컨테이너에 할당하는 메모리 비율이 더 크다
  84. EMR Spark 클러스터 스펙 • 메모리가 중요하므로 r4 타입을 선호

    • 작은 인스턴스 4개 보다 큰 인스턴스 1개로 • 좋은 인스턴스가 네트워크 속도도 더 빠르다 • EMR이 YARN 컨테이너에 할당하는 메모리 비율이 더 크다
  85. EMR Spark 클러스터 스펙 • 메모리가 중요하므로 r4 타입을 선호

    • 작은 인스턴스 4개 보다 큰 인스턴스 1개로 • 좋은 인스턴스가 네트워크 속도도 더 빠르다 • EMR이 YARN 컨테이너에 할당하는 메모리 비율이 더 크다
  86. EMR Spark 클러스터 스펙 • 메모리가 중요하므로 r4 타입을 선호

    • 작은 인스턴스 4개 보다 큰 인스턴스 1개로 • 좋은 인스턴스가 네트워크 속도도 더 빠르다 • EMR이 YARN 컨테이너에 할당하는 메모리 비율이 더 크다
  87. • 분석가는 언제나 부족 • 비 개발자도 분석하기도 쉬웠으면 •

    SQL은 과연 쉬운가…? • 사실상 대중화 실패 • 하는 사람만 한다. 분석의 대중화
  88. “이 컬럼은 정확히 뭘 의미하나요?” • 100개가 넘는 스키마, 모두

    기억하지 못함 • 문서가 없기 때문에 발생하는 현상
  89. “이 컬럼은 정확히 뭘 의미하나요?” • 100개가 넘는 스키마, 모두

    기억하지 못함 • 문서가 없기 때문에 발생하는 현상 → Docstring을 이용한 스키마 문서화?
  90. 만들고 붓고 부수고 - 〈야생의 땅: 듀랑고〉 서버 관리 배포

    이야기 김찬웅 님 / 4월 25일 오후 4시 30분 〈야생의 땅: 듀랑고〉 서버 아키텍처 Vol. 3 이흥섭 님 / 4월 25일 오후 3시 20분 〈야생의 땅: 듀랑고〉 NoSQL 위에서 MMORPG 개발하기 최호영 님 / 4월 26일 오전 11시