SQLer 生島勘富 のブログ

RDB・SQLの話題を中心に情報発信をしています。

「艦これ」もう少し思い出して考えてみた

「艦これ」はあんまり関係ないのですが、スケールアウトについて。

 「艦これ」は既に MySQL Cluster を使っているなら関係ないのですが、何度も書きますけれど、「JOIN禁止」はスケールアウトと関係ない

 Twitter規模になれば別の考え方が必要になりますが、取りあえず今は DBサーバ は1台だけれど、「スケールアウトのためにJOIN禁止」は「究極のバッドテクニック」ですのでやらないように!

 単純だから良いも、複雑だから良いもない。

 必要なのは効率的かどうかを考えることだけで、それはどんなシステムでも同じ。

「艦これ」は……

 「艦これ」は MySQL Cluster を使っているとのこと。私が始めた頃は、4・5個の鎮守府(サーバ群)があった様に記憶しています。

 MySQL Clusterと聞いて、DBは1つのクラスタ構成で処理されていると思ったのですが、障害は鎮守府(サーバ群)単位で起きている様で、「DBサーバの不調」である鎮守府で障害が起きている。というアナウンスがしばしばあった様です。

 つまり、図の様に

鎮守府(サーバ群)毎に、DBサーバクラスタを配置して、それぞれのDBサーバは連携してないというイメージのようで、全体が落ちないということは、DBサーバがシングルポイントになっている訳ではないということですね。

 ユーザ数60万、アクティブユーザ35万、同時ユーザ10万、更に増え続けていると言われていますが、鎮守府(サーバ群)単位で見ればもっと少ない。ということは、MySQL Clusterは、負荷分散ではなく、フォールトトレランスのために使っているのかな?

 私の記憶の範囲では、ゲーム内で他のユーザのデータが必要になる処理は、「ランキング」と「演習」しかなかったように思います。

 ランキングが鎮守府(サーバ群)単位なのか、全体なのか分かりませんし、リアルタイムなのか、ディレイあり(バッチ処理)なのかは分かりませんが、まず間違いなくバッチ処理でしょう。バッチ処理なら、鎮守府(サーバ群)を跨いでも全く大したことはない。

 また、「演習」では1日2回対戦相手を5名選んでいる(つまりバッチ処理やね)ようですが、リアルタイムで対戦するわけではなく、自分が誰かの対戦相手になったかどうかも分かりません。更に、鎮守府(サーバ群)を超えての割り当てはないのでは?

 一般的なネット対戦型ゲームなら、ユーザのデータが変化すると同時に対戦相手のデータも変化しますが、対戦相手のデータに変化のない「艦これ」は非常に単純で、基本的なゲーム部分はスタンドアローンでも十分可能でしょう。
 演習の相手は架空でも分からない(?)からね……。

更新処理はどうなってる?

 コネクション数や、それに関わるメモリーボトルネックにならないように調整したら、次に来るのは「データ更新時の問題」になります。

 これはLOCKの問題や、I/Oの問題など様々なことが起こりますが、それは個別に見なければ分かりませんのでおくとして、更新については、亜種はいくつもありますが、「艦これ」のようなシステムなら、主に以下の様な処理になるでしょう。




 私なら、APサーバの負荷を下げるためにクライアントに抽選をさせてしまうかな……。まあ、抽選の元になるデータをクライアントに送信するのは嫌がる人が多いでしょうが、解析したり、改造したりする違法な人達は、ピックアップして退会させるなり、訴えるなりすればいいしね……。
    # 将来、対戦型にバージョンアップするために……。
    # まあ、そりゃそうかもな……。

 逆に、もし、ログが必要なぐらい厳格なシステムであれば、ログは、UPDATE より軽い INSERTだけ(書き換えたらログじゃない)になりますから、ログだけ書き込んだら処理が続けられるようにします。ログが必要なシステムで、ログのINSERT とデータの UPDATE が終わるまで次に進まないシステムでは、大量アクセスになればそれだけ厳しくなる。

 余談ですが、似たような処理で、例えば、ECサイトであれば、注文ボタンでログ(というか仮注文)を書いて確認画面に遷移、確定ボタンでログのIDと共に実際のテーブルに書き込む。という処理もありますね。1回のユーザアクションで2回書き込むのは厳しいですが、ページ遷移が挟まれば、コネクションを掴みっぱなしの処理とは違い、DBサーバにとって大変な時間稼ぎになります。
 尤も、確定ボタン押下時のボトルネックは、大抵確認メールの方ですけど(苦笑)

個人的な感想

 私が無課金ユーザ(初回入会ボーナスの500円分は使いましたが)だからかも知れませんが、「艦これ」って待ち時間ばっかりで、激しくサーバにアクセスしようとしてもできない。同時オンラインのユーザが10万いても、一人一人は、1時間に何回も更新してないと思うので、外から見る限りそんなにシビアとは思えないのです。

 MySQL Clusterのベンチマーク http://www-jp.mysql.com/why-mysql/benchmarks/mysql-cluster/ を見る限り、2台のサーバで1秒間に100万回の UPDATE文を流せている。
もちろん、これは理論値に近いテストで、現実にはそのままのパフォーマンスは出ないでしょう。しかし、10万の同時ユーザが平均10秒に1回の更新(そんなにできる!?)が行われるとしても、1秒1万回です。
つまり、鎮守府を分けないで2台で組んだ最小のクラスタ構成でも、NoSQL の API を使っていれば理論上は100倍以上、現実的にはあと10倍ぐらいは対応できてもおかしくない。

 それでも「艦これ」が、
    同時ユーザ10万 ÷ 鎮守府の数
 でトラブルるなら……。スタートラインのコネクション数のパンクの可能性も高いわけです。

 「艦これ」のようなシステムであればアニメーションの間は、APサーバも、DBサーバも別の処理が可能です。それをシーケンシャルに処理していたら、いずれも待ち時間が発生し、パンクの可能性も、ユーザのストレスも高まることになるでしょう。
(私はイラチなので滅茶苦茶ストレスが溜まった……)何度か落とされたタイミングのイメージでは、シーケンシャルな処理にして、NoSQLではなく、UPDATE の SQL を流す最悪のパターンの可能性すらあるんじゃないかと……。

    # 時間経過毎に資源が増えますが、まさか、その度にUPDATEを流すとか……。
    # まさか……、そんな……設計にはなってないよね。

 まあ、私には調べようがないけれど、例えば「艦これ」の対戦シーンなら、ユーザの1アクションに対して数回のUPDATE文を流すことになるハズです。ここで NoSQL(API) を使えるかどうかは非常に大きい。Oracle などの SQL をショートカットするような API がない場合は、この通信が1回で終わるように引数に詰め込んだストアドプロシージャにするべきでしょう。

 いずれにしても、「艦これ」に限らず、似たようなソーシャル系のゲームであればアニメーションという非常に長い余裕を作ることができます。「艦これ」ユーザはそのアニメーションを楽しんでくれる訳です。ですから、そのユーザを飽きないように何種類かアニメーションを用意して、クライアントでランダム(レアも用意)にアニメを流して時間稼ぎして、非同期処理すれば DBサーバに対する流量調節は十分にできるでしょう。

 私なら、「ここでx秒飽きさせないアニメーションをよろしく!」とか、厚かましく求めるけどね(苦笑)尤も、センスがないので「何をもって飽きさせない」かは、全く分からないのですが……。

当たり前の話が……

 プログラムをやったことのない人は、パチンコでリーチが掛かって祈ったり、叩いたりする人達が結構います(苦笑)「艦これ」もパチンコと同じように、演出(アニメーション)の途中で抽選をしていると感じる人もいるかも知れないけれど……。

 まあ、どのタイミングで抽選していても、祈ろうが、叩こうが関係ないですが(苦笑)

 パチンコでも「艦これ」と同じように派手な演出がありますが、もちろん、演出のほぼ全て(最近は演出を追加するためのボタンがついてたり)がチェッカーに球が通った瞬間に決まっています。

 「艦これ」もパチンコと同じで、「艦娘」の製造に20分掛かっても、クリックした瞬間(正確にはAPサーバに行ってからでしょうが)に何ができるかは確定しているハズです。戦闘画面では陣形を決定した瞬間に、「何が、どの順番に、どれだけのダメージを受けるか」(次のユーザアクションの)夜戦の選択に入るまでの全ての演出が決まっています。(違ったら腰抜かすほど驚くわ……)

 それが分かっていて、「艦これ」の待ち時間に耐えられるというのは……。イラチの私には理解できません……。

 「それを言っちゃぁ、お終めぇよ〜」ってことなんでしょうが……、もしかして、分かってない人の方が多いんじゃないかと……。