想定外な規模へと成長し続けるサービスを 支えるサーバ開発・運用の軌跡 ~ DBの縦横分割スケーリング ~ / History of a large-scale Web API service development and operation with vertical and horizontal database partitioning.

Ed0a6b7b37643af6c2342423574bc1e2?s=47 walkure
March 07, 2019

想定外な規模へと成長し続けるサービスを 支えるサーバ開発・運用の軌跡 ~ DBの縦横分割スケーリング ~ / History of a large-scale Web API service development and operation with vertical and horizontal database partitioning.

TECH Night #1 by DELiGHTWORKS 〜FGO・モンストから学ぶ大規模ゲーム運用のためのサーバ・インフラの話〜( https://techplay.jp/event/717816 ) にて発表したスライドです。

Ed0a6b7b37643af6c2342423574bc1e2?s=128

walkure

March 07, 2019
Tweet

Transcript

  1. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 想定外な規模へと成長し続けるサービスを 支えるサーバ開発・運用の軌跡 ~

    DBの縦横分割スケーリング ~ 高屋俊康<toshiyasu.takaya.at.delightworks.co.jp> 2019年3月7日発表 0
  2. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 自己紹介 高屋俊康 (Toshiyasu

    TAKAYA) 2016年2月入社 以来ゲームサーバのお守りを中心に色々と 最近は新規案件の開発がメイン 趣味はおでかけ 1 Cherry blossoms of Kamogawa (Sakyo,Kyoto) 6 Apr. 2008 Photo by Toshiyasu TAKAYA
  3. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. Table of Contents

    Fate/Grand Orderについて ロンチから垂直分割まで 垂直分割から水平分割への切り替え 水平分割の結果 二度の分割を終えて 2
  4. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. Table of Contents

    Fate/Grand Orderについて ロンチから垂直分割まで 垂直分割から水平分割への切り替えまで 水平分割の結果 二度の分割を終えて 3
  5. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. Fate/Grand Order(FGO) について

    総監督:奈須きのこ(TYPE-MOON) 販売:アニプレックス 開発・運営:DELiGHTWORKS ※三社で開発しています 4
  6. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. FGO is a

    web service FGOはスマートフォン向けのゲームですが、Webサービスでもあります 「スマホゲームのゲームサーバ開発運用」について話をしますが、なにか 「WebサービスのAPIサーバ開発運用」にもお役立ちがあると願って 二度のデータベース分割を主なトピックに、ロンチ以来今日に至るまでを お話します ユーザ体験の大部分を占めるスマホ側の話は殆ど出てきません 5
  7. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. Webサービスとしての概要(1/4) ASP.NET MVC

    4で構築されたAPIサーバとUnityで構築されたクライアント で構成されたシステム APIサーバはWindows Server+IISでホスト。ロードバランサはClassic Load Balancer データベースはMySQL 当初は仮想マシン上のmysqld 2016年2月25日(*1) にmysqld on Amazon EC2からAmazon RDSへ移行 2016年9月26日(*2) にAmazon Auroraに移行 KVSとしてRedisを主に、一部memcachedを使用 構造としてはシンプルなサーバ・クライアントモデル MVCにおけるDBアクセスModelはADO.NET(+MySQLコネクタ)を呼び出す内製実装 6
  8. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. Webサービスとしての概要(2/4) クライアントが状態を持っている クライアントは単なるMVC

    Viewではなく、MVC Controller要素を持つ ViewデータだけでなくControllerとして処理をするための情報も送る必要がある 各ユーザが固有の状態を持つので、ユーザデータはキャッシュしにくい 基本的にはマスタデータぐらいしかキャッシュできない 最終ログインなど、一部の状態はRedisにキャッシュしています APIサーバでキャッシュするとスケールアウトが難しくなる 7
  9. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. Webサービスとしての概要(3/4) ユーザの状態はAPIをコールするごとに変わる データベースに対して読み込み(SELECT)のみならず書き込み(UPDATE/INSERT)が走る

    状態更新の例(ほんの一部です) 戦闘に出ることによりAP(体力)を消費し、戦闘した回数を記録 初めて出会ったサーヴァント(キャラクタ)がいればその事実を記録 ガチャを回すと、アイテムを消費し、結果を1件 or 10件書き込む 中でも、クエストで得られたアイテムを用いて呼び出すボックスガチャAPIの呼ばれる速度は 他のガチャAPIと比べて有意に大きいことが観測されている 8
  10. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. Webサービスとしての概要(4/4) ユーザの挙動が他のユーザ状態に対してほとんど影響を及ぼさない 「FGOとは,自分自身との戦いを楽しむゲームである」(CEDEC2018塩川)(*3)

    他ユーザの状態を更新するのは以下の例 別ユーザのサーヴァント(持ちキャラ)と一緒に出撃する(サポート機能) このとき、連れて行ったサーヴァントのマスターに点数(フレンドポイント)が加算 同時に、出撃したユーザにも点数が入ります フレンド申請の認否状態が更新されたとき 9
  11. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 10 参照文献一覧 *1)

    定期メンテナンス終了のお知らせ(2/25 AM1:00実施) https://news.fate-go.jp/2016/ztb6th/ 2016年2月25日 *2) 臨時メンテナンス終了のお知らせ(9/26 AM1:00実施) https://news.fate-go.jp/2016/4vmnsj/ 2016年9月26日 *3)[CEDEC 2018]FGOにまつわる3つの物語。「ディライトワークス, FGO PROJECTをプロデュースする。~ Fate/Grand Order 成長の軌跡 2015-2018 ~」レポート https://www.4gamer.net/games/266/G026651/20180824038/ 2018年8月24日 14時39分
  12. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. Table of Contents

    Fate/Grand Orderについて ロンチから垂直分割まで 2015年7月30日→2016年5月3日(88日間) 垂直分割から水平分割への切り替えまで 水平分割の結果 二度の分割を終えて 11
  13. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. ロンチ前後の動き サービスは2015年7月30日 (*4)

    に提供開始しました 企画は2013年末 (*5) から立ち上がり、制作発表は2014年7月28日 (*6) に行われました ダウンロード数は非線形増加(次項にて図示) 2015年8月26日 (*7) (ロンチから27日後)に300万ダウンロード 2015年9月28日 (*8) (ロンチから2ヶ月弱)には400万ダウンロード 2016年2月3日 (*9) (ロンチからほぼ半年)には500万ダウンロード 2016年6月29日 (*10) (ロンチから11ヶ月弱)には600万ダウンロード 12
  14. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. ロンチ後のダウンロード数推移 ※ダウンロード数達成キャンペーン開始日基準 13

  15. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. ロンチ前の状況はどうだったか? 事前登録(2014年12月28日 (*11)

    開始)者数は、ロンチ日(2015年7月30日)まで の7ヶ月と2日で70万人越え (*12) 。つまり増分は10万人/月ぐらい 事前予約からのインストール転換率は平均36%というデータがあります アプリマーケティング研究(3) 事前予約サービス経由のユーザのインストール転換率 や翌日継続率について (森山 晃義/株式会社AppBroadCast 2014年02月26日) https://gamebiz.jp/?p=127440 これを参考にすると、インストール数は多めに見積もって30万 14
  16. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. フタを開けると、ロンチ一ヶ月弱(27日後の8月26日)で300万DL越え オーダーがひとけた大きい サービスが広がる速度や程度を、事前に見積もる難しさを痛感

    過大に見積もればお金や時間が浪費されるが、過少に見積もるとこのような事態になる 負荷対応だけでなく、コンテンツに係る実装もやらないといけない… で始まってみるとどうか 15
  17. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 想定外の規模へ拡大 ロンチ後、想定より数桁大きい規模へ一気に成長 botアクセスも大量に来ました

    設計時想定を大幅に上回る入力量をシステムに与えると溢れます E.g.) Replicationが数千秒遅れてマスタに書いたガチャ結果がスレーブから読めない →数時間単位で結果が反映されないのでスレーブ参照を暫定的にやめる スレーブ参照はAurora移行まで復活できませんでした 当初設計を大幅に越えたアクセスにより、サービス提供が断続的に中断 16
  18. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. サービス断続的中断の要因(1/4) ユーザが増えることにより、色々なことが起きます APIサーバ:リクエスト・レスポンス数の増加…

    CDN:トラヒックの増加… データベース:時間あたりクエリ数が増加・テーブル内レコード数が増加… 基本的に、リソースの消費速度が増大する 消費速度を越える供給を行わないと、枯渇 17
  19. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. サービス断続的中断の要因(2/4) これらへの対応例 APIサーバ・データベース

    スケールアップ(1インスタンスあたりの能力を強くする) スケールアウト(インスタンス数を増やす) CDN トラヒックを買う データサイズを削減する APIサーバ:実装を改善してサーバへの負荷を下げる 18
  20. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. サービス断続的中断の要因(3/4) APIサーバはスケールアウト(増台)して対応しました インスタンス間の排他制御はRedis

    Mutex( https://redis.io/topics/distlock ) データベースサーバはスケールアップのみ想定していた ここが完全にボトルネック。台数を増やせないので、スケールアップの上限が限界値 データベースサーバにおいて想定される事態 レコード数の爆発:インデックスがメモリからあふれる クエリ数の爆発:処理キューがあふれる 19
  21. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. サービス断続的中断の要因(4/4) ユーザ数増加によりAPIコール数が増えてクエリ数が増加 新機能追加による1APIあたりのクエリ数が増加

    相乗効果でクエリ数が非線形増加し、データベースの処理速度を越えた クエリ消化が追いつかないので、APIサーバにてMySQLコネクタの接続 プールが枯渇 サービス障害 20
  22. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. クエリ数の非線形増加 2016年2月25日 (*13)

    開始のイベントの様子から、ミッション機能が有効だと ピーク時にデータベースが耐えきれない可能性が高いことが見えた ミッション機能はユーザの挙動を確認するためにクエリ数が多くなることが効いた 二ヶ月後にはミッション機能を使うイベント(2016年4月27日 (*14) )開催が迫る この間には、本編新章(2016年3月30日 (*15) 配信)とイベント (2016年4月11日 (*16) 開始)がある こちらの開発も行わないといけない 21
  23. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. クエリ数の非線形増加に対する初期対応(1/3) まずはクエリ処理速度の向上を試みた RDSパラメタやインデックスの調整、クエリ内容の精査

    staticパラメータ変更時にインスタンスを再起動するため、何度も臨時メンテ 1APIあたりのクエリ削減も試みたが、一方で機能追加は続く 減らすにも限度があり、一方で機能追加によるクエリ増加も不可避 レプリケーション遅延が解決しないうちはスレーブ参照を入れられない 22
  24. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. クエリ数の非線形増加に対する初期対応(2/3) 最終的にはスケールアウト(DB分割)をするしか無い 何らかの実装を追加して、誰かがオペレーションしないと分割できない

    深く考えずに水平分割すると、後に縮退することになったら大変だよね、という話も 時間を作るために、Auroraへ移行して時間を稼ぐ作戦をとった すでにRDSの最大インスタンスを使っているのでRDSのスケールアップはできない AuroraならReaderのレプリケーション遅延が数十桁秒小さいのでスレーブ参照が使える 要はRDSからAuroraに載せ替えてさらなるスケールアップ+αを狙った 23
  25. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. クエリ数の非線形増加に対する初期対応(3/3) 2016年4月24日 (*17)

    (イベント開始3日前)にAurora移行を決行 移行直後は比較的平和でした 二日後(4月26日)、binlogに関するAuroraのバグを踏み抜く (*18) 我々は2016年4月6日 (*19) リリースのv1.6で踏み抜いた このバグは2016年6月1日 (*20) リリースのv1.6.5(*21) で修正済み 原因追求を行っていたが時間がない(イベントは4月27日開始)ので切り戻す (*22) その後、2016年9月26日 (*23) に再度Auroraへの移行を行いました なんとかスケールアウト(DB分割)する以外の手がなくなる 24
  26. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 垂直分割の実装(2016年4月28日)と投入(5月3日 (*24) )

    余裕が全く無いので、簡単に(運用でなく)実装できる方を選んだ 変更行数は100行程度 ModelがDB接続先を選べる実装を入れました RDSのインスタンスを複製し、不要なtableをdropする形で分割 25
  27. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 垂直分割後 Fate/Grand Orderにおける、ディライトワークス流

    AWS 導入&活用術 https://speakerdeck.com/isoparametric/grand-orderniokeru-deiraitowakusuliu-aws-dao-ru-and-huo-yong-shu?slide=38 26 基本構成は現在もこのまま RDSからAuroraへ移行済 DBやKVS台数が増えました 最近c5インスタンスへ 2019年2月20日(*25) 実施
  28. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. データベース分割後のトランザクション データベースを分散した際には分散トランザクションを入れなければ、ト ランザクションのアトミック性はなくなります

    しかし、分散トランザクションを運用するためのノウハウや習熟する時間 がないので、今回は触れないことにした できるだけ事故発生時にユーザに不利な影響が起きないよう考えることに しました 27
  29. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 採用した対策 エラー発生時にDBクエリログを記録 手動で修正できるように

    エラーが多数起きたらサーバの処理を遮断する実装を入れ、修正量を多少は抑える インスタンス間のテーブル分配とコミット順を工夫 コミット中に失敗した際にできるだけユーザの不利益にならないように工夫しました E.g.) 霊基情報DBと霊基保管庫DBを同一DBに配置してトランザクションで守る コミット順を指定するので最初のRDBから最後のRDBまで、シーケンシャルにコミット 28
  30. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 垂直分割により起きた問題と、積み残した問題 新たな問題 トランザクションしていないので障害時のアクティブユーザが増えると修正が大変

    コミット順を指定してシーケンシャルにコミットしているので、全体の処理秒数は全 DBへのコミットの秒数だけ増加します アクセス増加によるDB増設によりレイテンシのさらなる悪化とコミット失敗率の上昇 積み残した問題 1テーブルが際限なく大きくなるので、対応が間に合わないと溢れる 29
  31. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 30 参照文献一覧(1/2) *4)

    事前登録者数70万人突破!「Fate/Grand Order」Android版先行配信スタート!/各種キャンペーン開催、プロモーション映像公開等について http://typemoon.com/news/2015/zkpep2 2015年7月30日 *5) 「Fate/Grand Order」成長の軌跡―ディライトワークスの代表らが語る3年間【CEDEC 2018】 https://www.gamer.ne.jp/news/201808240006/ 2018年8月24日 11時44分 *6) 制作スタッフ&出演キャストのトークも盛りだくさん! 「Fate Project 最新情報発表会」詳細レポート https://www.animatetimes.com/news/details.php?id=1411870481 2014年9月28日 12時00分 *7)【終了】人類最古の英雄王降臨!!「300万DL突破キャンペーン!!」 http://typemoon.com/news/2015/m1yimf 2015年8月26日 *8)【終了】「400万DL突破キャンペーン!」 https://news.fate-go.jp/2015/n5bwyg/ 2015年9月28日 *9)【終了】500万DL突破キャンペーン! https://news.fate-go.jp/2016/rayfpf/ 2016年2月3日 *10)【終了】「600万DL突破キャンペーン」! https://news.fate-go.jp/2016/m5fma6/ 2016年6月29日 *11)【事前登録】『Fate/Grand Order 』TVCMが解禁! 同時に事前登録がスタート https://app.famitsu.com/20141228_479478/ 2014年12月28日 00時35分 *12) 事前登録者数70万人突破!「Fate/Grand Order」Android版先行配信スタート!/各種キャンペーン開催、プロモーション映像公開等について http://typemoon.com/news/2015/zkpep2 2015年7月30日 *13) 【終了】コラボレーションイベント「空の境界/the Garden of Order」 https://news.fate-go.jp/2016/ybsjjo/ 2016年2月25日 *14)【終了】Fate/Zero×Fate/Grand Orderスペシャルイベント「Fate/Accel Zero Order」! https://news.fate-go.jp/2016/krhyob/ 2016年4月29日
  32. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 31 参照文献一覧(2/2) *15)「第五特異点

    北米神話大戦 イ・プルーリバス・ウナム」開幕! https://news.fate-go.jp/2016/qtsnc4/ 2016年3月30日 *16)【終了】期間限定イベント「ダ・ヴィンチと七人の贋作英霊」 https://news.fate-go.jp/2016/koolug/ 2016年4月15日 *17) 臨時メンテナンス終了のお知らせ(4/24 AM1:00実施) https://news.fate-go.jp/2016/vkozk6/ 2016年4月24日 *18) 48時間後… http://developer.delightworks.co.jp/entry/2016/07/11/181634 2016年7月11日 *19) Aurora MySQL データベースエンジンの更新: 2016-04-06 https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Updates.20160406.html 2016年4月6日 *20) Aurora MySQL データベースエンジンの更新: 2016-06-01 https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Updates.20160601.html 2016年6月1日 *21) Announcement: New Aurora Release 1.6.5 Now Available (Opt-in, no force patch) https://forums.aws.amazon.com/ann.jspa?annID=3793 2016年6月1日 13時3分 *22) 緊急メンテナンス終了のお知らせ(4/26 12:15実施) https://news.fate-go.jp/2016/uanvgf/ 2016年4月26日 *23) 臨時メンテナンス終了のお知らせ(9/26 AM1:00実施) https://news.fate-go.jp/2016/4vmnsj/ 2016年9月26日 *24) 臨時メンテナンス終了のお知らせ(5/3 AM1:00実施) https://news.fate-go.jp/2016/v3ypza/ 2016年5月3日 *25) メンテナンス終了のお知らせ(2/20 13:00実施) https://news.fate-go.jp/2019/0219laqin/ 2019年2月20日
  33. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. Table of Contents

    Fate/Grand Orderについて ロンチから垂直分割まで 垂直分割から水平分割への切り替えまで 2016年5月3日→2018年7月11日(2年と69日) 水平分割の結果 二度の分割を終えて 32
  34. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. ユーザ数の持続的な増加 2017年9月20日 (*26)

    には1000万DLを達成 2018年2月28日 (*27) には1200万DLまで到達し、垂直分割後の600万DLから見ると倍相当 データベースインスタンスも増加 4分割から5ヶ月後(2016年10月11日 (*28) )には5分割に増やし、10ヶ月後(2017年8月8日 (*29) ) には6分割にまで増加 この間に行った、データベースに関わる主な対応 2016年9月26日 (*30) にAuroraへ移行しました 2016年10月11日には歴史的経緯のみで一緒だったユーザ情報テーブルの分割も実施 履歴(課金情報や有償アイテム消費)テーブルの退避 33
  35. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. ユーザ数の持続的な増加 ※ダウンロード数達成キャンペーン開始日基準 34

  36. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 根本的な問題解決のために(1/3) 限界に当たる様子が見えてきた テーブルサイズの肥大化が大きな要因

    スケールアップによりAuroraの一番大きなインスタンスまで到達したので次はない イベント開催時、極度にレイテンシが悪化する場合が見受けられる(後述) ユーザデータを確実に守りたい トランザクションしていない問題の重みはユーザ数の増加とともに強くなる 分散トランザクションは茨の道 35
  37. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 根本的な問題解決のために(2/3) イベント終了直前(2018年1月20日 12時台)のレイテンシ

    大量のアクセスによりdbでmutex開放待ちspin lockが発生してレイテンシ悪化 巨大なテーブルに大量の更新クエリを流していることによる 36
  38. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 根本的な問題解決のために(3/3) データの操作は1ユーザで基本的に完結することが期待できる 「Webサービスとしての概要(4/4)」にて述べました

    ユーザIDでシャーディングする方針を固めました 1ユーザの情報が基本的にDB1台に乗り、シンプルなトランザクションで守れる 分散トランザクションを頑張るより、ユーザデータをDB1台に集約して自分たちでハン ドルできる範囲に持ってゆくほうが持続性が高い 三周年(2018年7月30日)に向けて安定した環境を作ろうと目標を立てた 37
  39. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 水平分割へ切り替えることにしました APIサーバの実装はがんばるしかない アンマネージドなシャーディングプロキシはSPOFになる上に運用が大変

    垂直分割したテーブルを水平分割に並べ替えるオペレーション AWSのDMS(Database Migration Service)を使うことで、レコード単位のデータ移動をマ ネージドに行う見通しが立ってきた https://aws.amazon.com/jp/dms/ インフラ周りは、2018年8月3日に行われた担当者(甲)による講演を参照 https://www.slideshare.net/hideakikabuto/db-108716671 38
  40. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. https://www.slideshare.net/hideakikabuto/db-108716671 これで怖くない!?大規模環境で体験するDB負荷対策~垂直から水平の彼方へ~ 39

  41. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 分割変更時のトラブル対策 垂直分割時より2年経過し、規模は更に拡大 ダウンロード数は倍以上になりました

    失敗の影響は格段に大きい上にオペレーションは複雑 テーブルの再構築など トラブル対策をいくつか用意しました 事前の負荷試験 複数の方法で切り戻し用の垂直分割DBを構築 40
  42. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 事前の負荷試験(1/2) 前述のように、クライアントは状態を持っています 負荷試験の際にアクセスを行うクライアントも、状態を持っていないと

    ユーザの挙動を再現できない Apache Benchでひたすらリクエスト投げる、ではだめ 詳細は時雨堂様の記事 (*31)(*32) を参照 Erlang/OTPで構築されたクライアント群がLuaで書かれたシナリオを読んでアクセス 41
  43. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. https://gist.github.com/voluntas/5c9e0f778e36c1e934e83611a94ffdfa 時雨堂 シナリオ負荷試験ツール

    Oribe 開発ログ 42
  44. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 事前の負荷試験(2/2) シャード数は20分割と決めましたが、これの妥当性も負荷試験で事前検証 正常系だけでなく、Auroraの障害挿入クエリ

    (*33) を用いたテストも行いました 思わぬレースコンディション等も事前に対応できました クラウドで負荷試験をする際にはベンダのポリシーを確認 EC2などは申請が必要です(cf. https://aws.amazon.com/jp/ec2/testing/ ) テスト内容如何では何らかの要件が発生する場合があります 43
  45. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 複数の方法で切り戻し用の垂直分割DBを構築 APIサーバ側と、インフラ側で構築する手段を取りました APIサーバ側:水平分割したシャードへ書き込むのと同時に、既存の垂直分

    割テーブルへもクエリを送る KPIログからの再現なども考えましたが、ログからクエリへ変換するより既に存在する クエリを流す実装を改造するほうが実装量が少ないと判断 インフラ側:DMSでシャードの書き込みを垂直分割DBへ転送 これにより構築・更新されるDBは現在もKPI集計などに使用 44
  46. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 水平分割の実装要点 シャーディングの仕掛けをゲームサーバのフレームワークに仕込みました ユーザIDから接続先DBを選ぶ

    複数DBアクセスの並列化 フレンドポイント付与処理の変更 データのシャーディングにおける例外 分散トランザクションについて 45
  47. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. ユーザIDから接続先DBを選ぶ 基本的にはモデル内で完結させるようにしました そうでないとゲームサーバの実装をまるっと書き換えることになって破滅

    内製モデルの生成実装を改造して、モデル定義にシャード用キーを指定できるように カラム情報からクエリを生成するあたりを作り直し Where文に条件をstringでべた書きしてる部分を確認し、モデルがユーザIDで確実に シャードを選べるように変更 運営オペレーションや集計用にクエリを自由に送れるモデルが存在してい たので駆逐 46
  48. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 複数DBアクセスの並列化 全シャードへのSELECTが発生する場合に備えました ユーザが出撃する際に連れてゆく仲間の候補を、定期的にDBから取ってきます

    全シャードへSELECTしないと真の最新ログインユーザ一覧は取れない 素直に実装するとレイテンシ20倍 各シャードへのアクセスをTask化した上でTask.WhenAllで一気に待機する 実装を入れました コネクタをMySQL Connector/Netからgithub.com/mysql-net/MySqlConnectorに変更 タスクが2つ以上失敗しても例外は一つしか取れないので、Task.Exceptionsをダンプす る実装を追加 47
  49. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. フレンドポイント付与処理の変更 1つのAPI呼び出し内で、2ユーザの状態更新が行われる場合 2ユーザに対して、ポイントの加算処理を行う

    加算処理のSELECT FOR UPDATEでロックを取るクエリを一気に送っていた 2ユーザがお互いに相手をサポートとして選択した∧両ユーザが別シャード にいた場合、デッドロックする 哲学者の食事問題 ユーザID順に加算処理を行うよう変更 https://commons.wikimedia.org/wiki/File:An_illustration_of_the_dining_philosophers_problem.png 48
  50. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. データのシャーディングにおける例外 実装上テーブルのUNIQUE制約に依存している部分があった E.g.)

    ユーザIDと1:1対応するフレンドコードの生成 これは1テーブルに収めたので、水平分割しても最大2DBへのコミットが発 生する状況 設計の大幅変更になってしまうので、これによるリスクは認容することに しました アカウント生成時に発生など、限定された条件下であることによる 49
  51. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 分散トランザクションについて TransactionScopeを使って実装してみた 障害テスト時、極稀にtrx_mysql_thread_id=0のトランザクションが残る

    どんなクエリが失敗したかはわからないままレコードがロックされるので、ロールバッ クして良いのか判断がつかない Auroraのベストプラクティス (*34) に使わないことをお勧めされている 移行中は別途DMSで水平分割DBから垂直分割DBへデータを転送している ダブルライト中の不整合発生を一番懸念していた 結局、分散トランザクションはやめました(2018年7月6日) 50
  52. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 水平分割の開発タイムライン AWS様とMSP(スカイアーチ様)には多大なる助力を賜りました プロジェクトスタートは2018年3月13日

    最初のコミットは2018年5月26日 実装は高屋を含めて3人が集中で担当 これが垂直の時は人手不足により出来なかった インフラ側は甲を中心に2人(+MSP)で担当 51
  53. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 水平分割の投入 投入は2018年7月11日 (*35)

    初回コミットから46日、プロジェクト開始から4ヶ月弱 インフラ側の準備として、FastDDL(*36) によるシャードIDカラム追加など APIサーバ側の準備としてシャードIDカラム更新実装などを事前に実施 ダブルライトは7/20まで行いました DMSによる集約データとの比較を行って差異がなかったため、無事終了 52
  54. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 53 参照文献一覧 *26)

    【終了】「1000万DL突破キャンペーン」開催! https://news.fate-go.jp/2017/1000man/ 2017年9月20日 *27) 【終了】「1200万DL突破キャンペーン」開催! https://news.fate-go.jp/2018/1200man/ 2018年2月28日 *28) 臨時メンテナンス終了のお知らせ(10/11 AM0:00実施) https://news.fate-go.jp/2016/rmrjhc/ 2016年10月11日 *29) 臨時メンテナンス終了のお知らせ(8/8 AM1:00実施) https://news.fate-go.jp/2017/0804itwdh/ 2017年8月8日 *30) 臨時メンテナンス終了のお知らせ(9/26 AM1:00実施) https://news.fate-go.jp/2016/4vmnsj/ 2016年9月26日 *31) FGO を支える負荷試験ツール https://medium.com/shiguredo/fgo-%E3%81%AB%E6%8E%A1%E7%94%A8%E3%81%95%E3%82%8C%E3%81%9F%E8%B2%A0%E8%8D%B7%E8%A9%A6%E9%A8%93%E3%83%84%E3%83%BC%E3%83%AB-2fa3de337e20 2018年7月11日 *32) 時雨堂 シナリオ負荷試験ツール Oribe 開発ログ https://gist.github.com/voluntas/5c9e0f778e36c1e934e83611a94ffdfa 2018年8月5日 *33) 障害挿入クエリを使用した Amazon Aurora のテスト https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Managing.FaultInjectionQueries.html *34) Amazon Aurora MySQL での XA トランザクションの使用 - Amazon Aurora MySQL を使用する際のベストプラクティス https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.BestPractices.html#AuroraMySQL.BestPractices.XA *35) 臨時メンテナンス終了のお知らせ(7/11 AM0:00実施) https://news.fate-go.jp/2018/0625infmt/ 2018年7月11日 *36) 高速 DDL を使用して Amazon Aurora でテーブルを変更する https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Managing.FastDDL.html
  55. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. Table of Contents

    Fate/Grand Orderについて ロンチから垂直分割まで 垂直分割から水平分割への切り替えまで 水平分割の結果 レイテンシについて評価します 二度の分割を終えて 54
  56. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 水平分割により期待される改善 レイテンシ削減 データベースへの書き込みが最大6台から最大2台に減った

    テーブルサイズが小さくなったので、参照するインデックスも小さくなった 複数テーブルへ分割されたのでmutex待機可能性も減少 データ処理の堅牢化 ユーザデータ読み書きが基本的に1トランザクションに収まる 前者の成果が出ているか、APIサーバのログをもとに検証 IISログのtime-takenカラムを集計して毎分ごとの代表値で比較 55
  57. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 代表値の選定について(1/2) 2018年7月12日の22時台でレイテンシを集計した例で説明します 56

  58. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 代表値の選定について(2/2) 最頻値が10msで、殆どのリクエストはすぐ返事を返せている しかし、最大値が60000ms(60秒)近くになっている

    これにより平均値も上ブレ、中央値は猛烈に上ブレしている よって、最頻値を代表値として見ることにしました 57
  59. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 2つ事例を選んで検証しました 水平分割の移行直前とダブルライト終了(7月20日)した後 2018年7月10日と、曜日が同じ火曜日の7月24日の22時台

    全APIリクエストを検証しました データベースへの書き込み負荷が高いボックスガチャイベントの最終日 2017年と2018年の秋に開催された、同一内容のイベントにおいて23時台 ボックスガチャAPIのみに絞って検証しました 58
  60. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 水平分割前後 レイテンシが半分ぐらいになりました 59

  61. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 2017年と2018年のボックスガチャAPI呼び出し ここでも、レイテンシが半減しました 60

  62. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. Table of Contents

    Fate/Grand Orderについて ロンチから垂直分割まで 垂直分割から水平分割への切り替えまで 水平分割の結果 二度の分割を終えて 感想など 61
  63. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 二度の分割を終えて やっと年越しを平和に過ごすことが出来ました ユーザ・サービス提供側双方にとって良い結果で、本当に良かった

    データベースのスケーリングを後から追加・変更するのはコストが高い 最初から考えておかないといけない 大きな変更時は、別観点から構築された策を2つ以上持とう 一点突破は転んだ際のリカバリが大変 62
  64. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved. 今後の課題+α サーバ側に問題がなくなったわけではありません E.g.

    ) メンテ明け直後のアクセスが猛烈に遅くなる問題 コスト最適化もやらねばならないが、サービスを安定して提供するのがまず大前提 「段取り八分」 時間がかかりそうな段取りは、しんどくても事前に済ませておきましょう 63
  65. Copyright 2019 DELiGHTWORKS Inc. All Rights Reserved.