2017/10/08 PHPカンファレンス2017
© Cygames, Inc.© Cygames, Inc. 1 / 120
View Slide
2 / 120
3 / 120自己紹介【自分の目指すところ】最速のシステムを作りたい
4 / 120Cygamesについて
5 / 120Cygamesについて【Cygamesのビジョン】最高のコンテンツを作る会社
6 / 120グランブルーファンタジーとは• 1700万ユーザーを超えたRPG• ブラウザゲーム• 30人が同時に戦うマルチバトル※※2017年10月8日現在
7 / 120グラブルの技術的特徴大量のアクセスがある!
8 / 120グラブルの技術的特徴サーバ攻撃ボタンやアビリティボタンを押下するたびにリクエスト(約3秒に1回)
9 / 120グラブルの技術的特徴大量のアクセス1日の総PV数10億PV強
10 / 120グラブルの技術的特徴騎空団(ギルド)同士のバトルイベント中PV数 :20億PV/日バトル数:1100万回/日※最大値
11 / 120大量アクセスをさばくシステム構成Web Server 1twemproxymemcached 1…ApplicationServersCacheServersDatabaseServersMasterMySQL MHA Cluster 1Apache + mod_phpNode Server 1Layer4 Load Balancer(BIG-IP)Client N…Web(HTTP) static data accessMemcached ServersClient (Apps or Web Browser) 1AkamaiCDN…Nginx 1…Application Load BalancersWebSocket(WS)Nginx NRedis 1…RedisServersRedis N10G Ethernet 10G EthernetNodeServer NWeb ServerN…WebSocket (WS)Web(HTTP)AccessLoadBalancer /ProxySharding (水平分割)… NNode.jstwemproxymemcached NSlave1Slave2MySQL MHA Cluster 2 MySQL MHA Cluster 3MasterSlave1Slave2MasterSlave1Slave2mysqliWeb Server 1twemproxyApache + mod_phpmysqlilocalmemcachedlocalredis
12 / 120大量アクセスをさばくシステム構成データベースがたくさんある!アクセスが多いテーブルは水平分割してる大量のアクセスをさばくためにDBを細かく分ける※DBサーバーは100セット以上
13 / 120グラブルは多くのユーザーがプレイトータル1日10億オーバーのPV
14 / 1201700万人を満足させるためのシステム改修• 今回の改修の目標• 改修するところを探す• 実際に改修してみた例
15 / 1201700万人を満足させるためのシステム改修• 今回の改修の目標• 改修するところを探す• 実際に改修してみた例
16 / 120今回の改修の目標グラブルのシステムをもっと早くする!!
17 / 120今回の改修の目標• グラブルはたくさんの人が遊んでいて、大量のアクセスがある「最高のコンテンツを作る会社」なので「サーバーサイドエンジニア」として「レスポンス改善」を目標にした
18 / 1201700万人を満足させるためのシステム改修• 今回の改修の目標• 改修するところを探す• 実際に改修してみた例
19 / 120改修するところを探す具体的にどうするのか検討するために下記の観点で調査した・APIの特定・処理の見直し・具体的な改修箇所
20 / 1201700万人を満足させるためのシステム改修• 今回の改修の目標• 改修するところを探す• APIの特定• 処理の見直し• 具体的な改修箇所• 実際に改修してみた例
21 / 120APIの特定• 重いAPIはどれだろうAPIの重さが相対的にわかるツールが必要New Relicで調査しました
22 / 120APIの特定【New Relicからわかったこと】バトル処理全般に対して下記の現象が判明しました・レスポンスタイムが高い・throughputが高い・most time consumingが上位
23 / 120New Relicとはサーバでの処理時間がリアルタイムでわかるツール
24 / 120レスポンスタイムが高いTransaction項目をみると各APIごとの平均レスポンスタイムのランキングが表示されている上位にバトルのAPIが入っていた
25 / 120throughputが高いthroughput項目を見るとほかの処理に比べて、バトルAPIはthroughputが高いので高頻度にたたかれる
26 / 120most time consumingが上位Most time consumingの観点でバトルのAPIが上位2位であった(全体の3割強)相対的にバトルソースがWebサーバに負荷を与えている
27 / 120APIの特定・バトルの処理回数が多い・バトルの処理時間が長い以上のことがわかったので、バトル処理全般を改修することにした
28 / 1201700万人を満足させるためのシステム改修• 今回の改修の目標• 改修するところを探す• APIの特定• 処理の見直し• 具体的な改修箇所• 実際に改修してみた例
29 / 120処理の見直し• バトルの中の処理はどうなっているんだろう実際に自分で処理を見直した
30 / 120処理の見直し特にバトル処理中のスキル計算処理の中で・多くのスキルを判定している・計算数が多い箇所がある
31 / 120処理の見直し特にバトル処理中のスキル計算処理の中で・多くのスキルを判定している・計算数が多い箇所がある具体的に数値で回数を見たいプロファイラを使って処理を分析
32 / 120処理の見直し今回はXHProfを使いましたXHProfとは、PHPのプロファイラ処理時間や関数のcall数、メモリ使用など詳細に数値で把握できる
33 / 120処理の見直し下記のことがわかりました・スキル計算処理がメモリを消費し、処理時間も長い・CSV取得処理のcall数が多く処理時間が長い
34 / 120スキル計算処理の負荷が高いスキルの評価部分が処理時間が長く、メモリ消費が激しかった
35 / 120CSV取得処理のcall数が多く処理時間が長いCSVを取得している処理のcall回数が多い処理に時間がかかっている
36 / 120処理の見直しプロファイラからわかったこと・スキル計算処理がメモリを消費し処理時間も長い・CSV取得処理のcall数が多く処理時間が長いスキル計算処理とCSV取得処理がネック
37 / 1201700万人を満足させるためのシステム改修• 今回の改修の目標• 改修するところを探す• APIの特定• 処理の見直し• 具体的な改修箇所• 実際に改修してみた例
38 / 120具体的な改修箇所• スキル計算処理がメモリを消費し処理時間も長いスキル計算処理のメモリ使用量を減らし、処理時間を短くする• CSV取得処理のcall数が多く処理時間が長いCSV取得処理のcall数を減らし、処理時間を短くする
39 / 120具体的な改修箇所「スキル計算の高速化」「CSVの取得処理の効率化」上記を改修箇所とした。
40 / 1201700万人を満足させるためのシステム改修• 今回の改修の目標• 改修するところを探す• 実際に改修してみた例
41 / 120実際に改修してみた例全項目より下記2点を改修箇所として定めた• スキル計算の高速化• CSVの取得処理を効率化
42 / 1201700万人を満足させるためのシステム改修• 今回の改修の目標• 改修するところを探す• 実際に改修してみた例• スキル計算の高速化• CSVの取得処理を効率化
43 / 120スキル計算の高速化スキルの高速化として下記の3項目を説明します• グラブルのスキル• 現状の把握• 改善方法
44 / 1201700万人を満足させるためのシステム改修• 実際に改修してみた例• スキル計算の高速化• グラブルのスキル• 現状の把握• 改善方法• CSVの取得処理を効率化
45 / 120グラブルのスキルグラブルのスキルは種類が多く、バトル内でも大量に判定されますバトルの編成の中でスキルに関連するもの・武器・召喚石・キャラ etc...
46 / 120武器1編成に付き10本1本あたり2種類のスキルを持つ
47 / 120武器この武器には以下のスキルが付いている1. 風属性キャラの攻撃力上昇(中)2. 風属性キャラのHPが少ないほど攻撃力が上昇(小)
48 / 120召喚石編成全体の能力に影響を与える(バトル中は自分とサポーターの2つ)
49 / 120召喚石この召喚石には以下のスキルが付いているスキル「嵐竜方陣」の効果を100%UP
50 / 120キャラクター1ターンに4人攻撃する1人3つのスキルを持っている
51 / 120キャラクターこのキャラクターには以下のスキルが付いている1.弱体耐性UP2.バトル開始時に自動復活効果3.被ダメージに稀にHP全回復
52 / 120グラブルのスキル多彩なスキルを組み合わせて、高いダメージを得たり、戦闘中に有利になる効果を得たりする
53 / 120グラブルのスキル• 判定するスキルの数は武器(10 × 2)+ 召喚石(2 × 1) + キャラクター(4 × 3) = 34バトル中に34回判定される。
54 / 120グラブルのスキル・武器スキル数は800以上・召喚石のスキルは250以上・キャラクター数は400キャラ以上組み合わせの数が膨大になる※10/8現在
55 / 1201700万人を満足させるためのシステム改修• 実際に改修してみた例• スキル計算の高速化• グラブルのスキル• 現状の把握• 改善方法• CSVの取得処理を効率化
56 / 120現状の把握• グラブルのスキルは数が多く、組み合わせ数も膨大実際に確認したところスキルの計算処理が膨大にあった。プロファイラで詳細分析
57 / 120現状の把握・スキル計算処理が処理時間も長い、メモリ使用量が高い
58 / 120現状の把握・実際の処理例foreach($character_party as $character){foreach($weapon_skill_ids as $skill_id){$skill_master = Master¥Skill::find($skill_id);Skill::calcurate_skill($character, $skill_master)}foreach($summon_skill_ids as $skill_id){$skill_master = Master¥Skill::find($skill_id);Skill::calcurate_skill($character, $skill_master)}…}様々なスキルをループ回しているたくさん計算している→処理が長い
59 / 120現状の把握スキル評価ロジックのメモリ使用量が高い
60 / 120現状の把握• スキルの組み合わせが多いので、膨大な計算処理がある計算処理を減らせれば軽くなる
61 / 1201700万人を満足させるためのシステム改修• 実際に改修してみた例• スキル計算の高速化• グラブルのスキル• 現状の把握• 改善方法• CSVの取得処理を効率化
62 / 120改善方法• スキルの組み合わせが多いので、膨大な計算処理がある計算処理を減らせれば軽くなる普段どのような負荷対策をしているか考えてみた
63 / 120改善方法PHP DBサーバーからDBに大量にアクセスがある
64 / 120改善方法KVS一度DBから取得したら、KVSに乗せるPHPDB
65 / 120改善方法一度計算した結果をKVSにのせると早くなるはず!PHP KVS
66 / 120改善方法キャラクタースキルの計算結果計算結果武器スキルの計算結果召喚石スキルの計算結果計算結果をKVSに載せると計算処理が省ける
67 / 120改善方法• 実際の処理例foreach($character_party as $character){foreach($weapon_skill_ids as $skill_id){$skill_master = Master¥Skill::find($skill_id);Skill::calcurate_skill($character, $skill_master)}foreach($summon_skill_ids as $skill_id){$skill_master = Master¥Skill::find($skill_id);Skill::calcurate_skill($character, $skill_master)}…}処理するスキルがたくさんあるスキルのロジックにアクセス
68 / 120【改修後処理】$identifier = $raid_id . $user_id;$skill = Memcache::instance()->get(raid_id);If (empty($skill)) {foreach($character_party as $character) {$array[キャラクター番号] = aforeach($weapon_skill_ids as $skill_id){$skill_master = Master¥Skill::find($skill_id);$skill[‘weapon_skill’][]=Skill::calcurate_skill($character,$skill_master);}foreach($summon_skill_ids as $skill_id){$skill_master = Master¥Skill::find($skill_id);$skill[‘summon_skill’][] = Skill::instance()->calcurate_skill($character, $skill_master);}foreach($support_skill_ids as $skill_id)…Memcache ::instance()->set_key($ identifier )->set($skill);}計算してあるスキル値をmemcachedから取得計算結果が入っている配列をmemcachedに詰める計算した値を配列に詰めておく
69 / 120実装上で気をつけたこと・キーの持ち方・データが取れないの挙動
70 / 120キーの持ち方正しい一意のキーで取得しないと別のデータがとれてしまい、障害原因となる。「バトルのID」と「ユーザーのID」を結合して一意のキーを保証した。
71 / 120データが取れないの挙動データが取れないときは、再度計算しmemcachedに載せる有効期限が切れた場合や、memcachedに異常が発生した場合でも、データが取れないので正しく計算されるよって安全性が担保される
72 / 1201700万人を満足させるためのシステム改修• 今回の改修の目標• 改修するところを探す• 実際に改修してみた例• スキル計算の高速化• CSVの取得処理を効率化
73 / 1201700万人を満足させるためのシステム改修• 実際に改修してみた例• スキル計算の高速化• CSVの取得処理を効率化• グラブルのマスタデータ• 改善ポイント• 改善方法
74 / 1201700万人を満足させるためのシステム改修• 実際に改修してみた例• スキル計算の高速化• CSVの取得処理を効率化• グラブルのマスタデータ• マスタデータとは• 現状のマスタデータの扱い方• グラブルのマスタデータの特徴• 改善ポイント• 改善方法
75 / 1201700万人を満足させるためのシステム改修• 実際に改修してみた例• スキル計算の高速化• CSVの取得処理を効率化• グラブルのマスタデータ• マスタデータとは• 現状のマスタデータの扱い方• グラブルのマスタデータの特徴• 改善ポイント• 改善方法
76 / 120マスタデータとはキャラクターや武器などのパラメータ情報マスタデータはCSVファイル
77 / 120マスタデータとは• 例【キャラの情報】性別身長体重【パラメータ】攻撃力HP防御力【アビリティ】スキルのデータスキル文言追加効果の情報【図鑑】キャラ紹介の文言
78 / 120マスタデータとはパラメータの情報をCSVで保持【キャラの情報】性別身長体重【キャラの情報】性別,身長,体重男,178,50
79 / 1201700万人を満足させるためのシステム改修• 実際に改修してみた例• スキル計算の高速化• CSVの取得処理を効率化• グラブルのマスタデータ• マスタデータとは• 現状のマスタデータの扱い方• グラブルのマスタデータの特徴• 改善ポイント• 改善方法
80 / 120現状のマスタデータの扱い方現状のマスタデータの保存方法はWebサーバ内のlocal redisを使用サーバlocalredis
81 / 120現状のマスタデータの扱い方実際に運用しながら試してみた順に紹介・KVSの場所について・local memcachedに保存・local redisに保存
82 / 1201700万人を満足させるためのシステム改修• 実際に改修してみた例• CSVの取得処理を効率化• グラブルのマスタデータ• マスタデータとは• 現状のマスタデータの扱い方・KVSの場所について・local memcachedに保存・local redisに保存• グラブルのマスタデータの特徴
83 / 120KVSの場所について・マスタデータは全てのユーザに対して同じデータglobalサーバにKVSを立ててデータを置くと全ユーザーがデータを取得するため、トラフィックが多いPHPPHPKVS
84 / 120KVSの場所について• 各Webサーバ内にKVSを立てて、アクセスするようにするとWebサーバの数だけアクセスが分散できるサーバlocalKVSサーバlocalKVSサーバlocalKVS
85 / 120システム構成図から見るglobal KVSとlocal KVSWeb Server 1twemproxymemcached 1…ApplicationServersCacheServersDatabaseServersMasterMySQL MHA Cluster 1Apache + mod_php Node Server 1Layer4 Load Balancer(BIG-IP)Client N…Web(HTTP) static data accessMemcached ServersClient (Apps or Web Browser) 1AkamaiCDN…Nginx 1…Application Load BalancersWebSocket(WS)Nginx NRedis 1…RedisServersRedis N10G Ethernet 10G EthernetNodeServer NWeb ServerN…WebSocket (WS)Web(HTTP)AccessLoadBalancer /ProxySharding (水平分割)… NNode.jstwemproxymemcached NSlave1Slave2MySQL MHA Cluster 2 MySQL MHA Cluster 3MasterSlave1Slave2MasterSlave1Slave2mysqlilocalmemcachedlocalredisWebサーバにあるlocal redislocal memcachedglobalにあるredismemcahced
86 / 1201700万人を満足させるためのシステム改修• 実際に改修してみた例• CSVの取得処理を効率化• グラブルのマスタデータ• マスタデータとは• 現状のマスタデータの扱い方・KVSの場所について・local memcachedに保存・local redisに保存• グラブルのマスタデータの特徴
87 / 120local memcachedに保存PHPからCSVファイルにアクセスしたとき、一番最初のアクセスで全行をlocal memcachedに保存localmemcachedPHPCSVファイル
88 / 120local memcachedの問題点CSVファイルのレコード数が増えたため、CSVファイルのデータをlocal memcachedに保存する際にWebサーバに負荷がかかるようになった。
89 / 1201700万人を満足させるためのシステム改修• 実際に改修してみた例• CSVの取得処理を効率化• グラブルのマスタデータ• マスタデータとは• 現状のマスタデータの扱い方・KVSの場所について・local memcachedに保存・local redisに保存• グラブルのマスタデータの特徴
90 / 120local redisに保存local redisだとlocal memcachedで起きていた問題点が起きないためWebサーバにlocal redisをたてて、マスタデータをlocal redisに移行したPHPlocalredis
91 / 1201700万人を満足させるためのシステム改修• 実際に改修してみた例• スキル計算の高速化• CSVの取得処理を効率化• グラブルのマスタデータ• マスタデータとは• 現状のマスタデータの扱い方• マスタデータの特徴• 改善ポイント• 改善方法
92 / 1201700万人を満足させるためのシステム改修• 実際に改修してみた例• スキル計算の高速化• CSVの取得処理を効率化• グラブルのマスタデータ• マスタデータとは• 現状のマスタデータの扱い方• マスタデータの特徴・マスタデータの構成について・更新頻度について・問題点
93 / 120マスタデータの構成について• キャラクターの例【キャラの情報】性別身長体重【パラメータ】攻撃力HP防御力【アビリティ】スキルのデータスキル文言追加効果の情報【図鑑】キャラ紹介の文言
94 / 120マスタデータの構成について基本情報バトルパラメータアビリティ 図鑑キャラクターのデータ
95 / 120マスタデータの構成についてID スキルのID 演出データID 奥義ID etc1 2 21 33 Etc…ID 効果値 スキル演出ID ダメージ補正ID Etc..2 2 9 43 Etc…ダメージ補正スキル基本情報ID 基礎値 ダメージの伸び方ID固定値 Etc…43 23 22 2000 Etc…
96 / 120マスタデータの構成についてマスタデータは多くのCSVファイルから構成されている多くのCSVファイルとリレーション関係がある
97 / 1201700万人を満足させるためのシステム改修• 実際に改修してみた例• スキル計算の高速化• CSVの取得処理を効率化• グラブルのマスタデータ• マスタデータとは• 現状のマスタデータの扱い方• マスタデータの特徴・マスタデータの構成について・更新頻度について・問題点
98 / 120更新頻度についてマスタデータがリリースされたら基本変わらないマスタデータが変わる例:1.不具合修正2.バランス調整
99 / 1201700万人を満足させるためのシステム改修• 実際に改修してみた例• スキル計算の高速化• CSVの取得処理を効率化• グラブルのマスタデータ• マスタデータとは• 現状のマスタデータの扱い方• マスタデータの特徴・マスタデータの構成について・更新頻度について・問題点
100 / 120問題点マスタデータの構成上CSVファイルが大量に関連しているため、検索コスト、データを保持するコストがかかる
101 / 1201700万人を満足させるためのシステム改修• 今回の改修の目標• 改修するところを探す• 実際に改修してみた例• スキル計算の高速化• CSVの取得処理を効率化• グラブルのマスタデータ• 改善ポイント• 改善方法
102 / 120マスタデータの構成について基本情報バトルパラメータアビリティ 図鑑キャラクターのデータ
103 / 120改善ポイント• 通信ごとにキャラクターのデータを作り直している
104 / 120改善ポイント• キャラクターのデータを作るときに多くのマスタデータを取得している• 通信ごとにキャラクターのデータを作り直しているCSVをとる頻度が高い
105 / 120改善ポイントCSVを取得する頻度を低くすれば効率が良い
106 / 1201700万人を満足させるためのシステム改修• 今回の改修の目標• 改修するところを探す• 実際に改修してみた例• スキル計算の高速化• CSVの取得処理を効率化• グラブルのマスタデータ• 改善ポイント• 改善方法
107 / 120改善方法必要な個所に対して中間データをキャッシュしたら効率が良い!
108 / 120改善方法基本情報バトルパラメータアビリティ 図鑑キャラクターのデータ• 改修前のイメージ
109 / 120改善方法基本情報バトルパラメータアビリティキャラクターのデータ• 改修後のイメージmemcached必要なデータに絞る一度取得したらmemcachedに保存
110 / 120改善方法【実装時に気を付けたこと】・中間データのキャッシュの置き場共通のデータを参照するため local memcachedに格納・マスタデータが更新された時について
111 / 120マスタデータが更新された時についてマスタデータが更新されたときに、同時に中間データも更新されなければならないそのためリリースバッチでマスタデータが保存されているredisと中間データが保存されているmemcachedを削除しているWebサーバlocal memcached中間データlocal redisマスターデータ サーバ内でflush_all
112 / 120改善結果中間データをキャッシュ化したことによって全体のCSV取得回数が減ったCSVファイルを検索する機会が減ったマスタデータをサーバメモリに展開する必要がなくなったのでメモリの節 約になった
113 / 120まとめ• スキル計算の高速化• CSV取得処理の効率化上記の処理を行いましたそれによる効果をグラフ化します
114 / 120まとめバトルAPIの平均速度は42.5%減050100150200250300350400450改修前 改修後APIの速度400ms230ms
115 / 120まとめバトルAPIのメモリ使用量は40%減020406080100120改修前 改修後メモリ使用量100MB60MB
116 / 120まとめ• CALL関数の数は50%減050000100000150000200000250000300000350000400000450000改修前 改修後CALL関数の数400,000関数200,000関数
117 / 120改修を通して感じたこと• 常に改善の意識をもつ必要性• プログラムを書く上での当たり前の大切さデータは最小限にまとめて再利用同じデータを何度も取得しないで再利用
118 / 120■まとめキャッシュは神使用用途は正しく守ってください
119 / 120
© Cygames, Inc. 120 / 120