Writeの分散
それぞれWriteとReadの負荷分散があるが、Readについては、MySQLにマスタースレーブ方式のレプリケーション(複製)機能が標準実装されているため、基本的に参照専用のスレーブ台数を単純に増やせば対応できる。
一方、複製したスレーブは一様にデータ更新が必要なため、サーバー単位のWrite量が減少するわけではない点がネックとなる。
![Readの負荷分散は参照専用のスレーブを単純に増やせば解決](http://cz-cdn.shoeisha.jp/static/images/article/5433/5433_0863.jpg)
つまり、1台のマスターによるマスタースレーブ構成ではWrite処理の限界が低い(グリーでは、15Krpm/RAID10のディスクで2~3Mbps程度)。
この場合、データベース(テーブル)を複数サーバーに分割することが一般的で、機能ごとにテーブルを分ける「垂直分割」と、1つのテーブルを分割する「水平分割(Sharding)」の大きく2つの方法がある。
垂直分割
垂直分割では、ユーザープロファイル、アイテムデータといったデータの種類ごとにデータベースを分けてしまう。結果、異なるデータベースにあるテーブル間でJOINできない制約が発生する。
この対処方法として、グリーでは「ユーザーの不利益にならない順番で更新する」という方針を説明した。例えばアイテム購入といった複数のテーブルを同時に更新する必要がある場面では、先に購入アイテムをユーザーに付与した後で、購入ポイントの減算を行い、負荷などによって最悪後者の更新処理が行えない状況になったとしてもユーザーが損しないように配慮している。
もちろん、後から復旧できるように、処理の失敗時には必ずログを吐き出すようにもしている。
水平分割(Sharding)
一方、水平分散(Sharding)は、IDの奇数偶数といった基準で、1つのテーブルのデータを複数のデータベースに分散させる方式だ。この場合、分散の基準となったフィールド以外でSQL文の条件を指定できないという制約が発生する(例えば、ユーザーIDで振り分けた場合にユーザーの年齢で抽出できないなど)。
当然、数十台のサーバーにリクエストを投げて集約するというわけにもいかない。これについて特に画期的な解決方法はなく、条件に指定したいフィールドをプライマリーキーにした逆引き用の索引、いわゆる転置インデックスを別のテーブルで用意するといった方法で対応している。
ディスク書き込みを行わない
ディスク書き込みを避けるには、例えばLinuxであれば、オンメモリーファイルシステム「tmpfs」や分散型メモリーキャッシュシステム「memcached」に全データを置いてしまうという方法があり、ハイパフォーマンスでI/Oがほどんどボトルネックにならない効果が見込める。
もちろん、サーバーダウン時の全データ消失、メモリーサイズの限界などに注意する必要があり、少なくとも別のラックにレプリカを作る、デイリーでスナップショットを取っておく、といった対処が必要だ。また、性能が出すぎるためトラフィックの総量に注意にすべき点や、データサイズがいつの間にかSwap領域まで膨らみディスクI/Oが発生してしまう可能性などについても指摘した。
RDBMSの処理を肩代わりする
RDBMSを代替する手段としては、一般的にKVS(キーバリューストア)を使うことが多く、グリーでは「Flare」という自作KVSを利用している。「キー」と「値」による小さく単純なデータモデルで構成されるため、サーバー台数増加によるスケールアウトに適している。RDBMSに比べパフォーマンスがよい、運用コストが低い、memcachedより高いデータ信頼性、といった利点も示した。
一方、KVSはデータの集計などが苦手なため、プレイヤーのレベルアップといった切りのよいタイミングで、RDBMSにデータを戻すようにしているという。
DBサーバー運用の工夫
MySQLの運用については「スレーブが落ちたら切り離し、あらかじめ常備待機させているStandbyのサーバーをスレーブとして追加」「スレーブは最低2台」「マスターが落ちたら自動で別のマスターに切り替え」といった工夫を紹介した。
通常オンラインゲームでは定期的にサービスを止めてメンテナンスを行うが、グリーではメンテナンスの際にサービスを停止させない。これは、同じ構成のマスタースレーブを現行のマスターの下に用意し、先にWebサーバーからの参照先を新しいスレーブに切り替え、次に書き込み先を新しいマスターに切り替える、という形で実現している。
![無停止によるデータベースの切り替え](http://cz-cdn.shoeisha.jp/static/images/article/5433/5433_0898.jpg)
機会損失しないために
今回のような話は、もちろん最初から対策が必要なものではない。藤本氏もスタートアップ時はメモリをある程度潤沢にして、すべてオンメモリファイルシステムでやってしまうのも悪くはないと述べている。
だが、ソーシャルゲームの世界では急にブレイクすることが少なくなく、各社とも同じような負荷分散で苦しむことが多い。将来を想定してノウハウをあらかじめ理解しておくのと、とりあえず今動くものを作るのとでは、機会損失の面で大きな差が広がってしまう危険性を喚起した。