大規模ソーシャルゲーム開発から学んだPHP&MySQL実践テクニック
Upcoming SlideShare
Loading in...5
×
 

大規模ソーシャルゲーム開発から学んだPHP&MySQL実践テクニック

on

  • 61,201 views

OSC 2011 Hokkaidoの発表で使用したスライド資料です。

OSC 2011 Hokkaidoの発表で使用したスライド資料です。
弊社が「ブラウザ三国志」や「英雄クエスト」といったゲームを、PHP+MySQLで構築してきた上で、身につけたノウハウや、注意すべき箇所、指針などをまとめた資料となっています。

Statistics

Views

Total Views
61,201
Views on SlideShare
53,159
Embed Views
8,042

Actions

Likes
84
Downloads
465
Comments
0

28 Embeds 8,042

http://www.infiniteloop.co.jp 7458
http://s.deeeki.com 166
http://192.168.0.26 90
http://ss.dotbranch.com 59
http://localhost 59
http://paper.li 51
url_unknown 29
http://asklife.info 21
http://b3dev1.infiniteloop.co.jp 20
http://www.slideshare.net 14
http://10.211.55.6 13
https://twitter.com 10
http://us-w1.rockmelt.com 9
http://sc.dotbranch.com 8
http://b.hatena.ne.jp 7
http://webcache.googleusercontent.com 7
http://slideshare-download.seesaa.net 5
http://translate.googleusercontent.com 3
http://tweetedtimes.com 2
http://xxx.broceliand.fr 2
http://192.168.245.164 2
http://192.168.33.10 1
http://54.248.222.153 1
http://www.atmarkit.co.jp 1
http://www.onlydoo.com 1
http://slideclip.b-prep.com 1
http://slide.yoshiday.net 1
http://livebuzz.com.br 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

大規模ソーシャルゲーム開発から学んだPHP&MySQL実践テクニック Presentation Transcript

  • 1. 大規模ソーシャルゲーム 開発から学んだPHP&MySQL実践テクニック 株式会社インフィニットループ 松井 健太郎 2011/06/11
  • 2. 自己紹介(1)松井 健太郎・ 株式会社インフィニットループ 代表取締役・ LOCAL PHP部 部長・ ke-tai.org 管理人・ コーラとバイクが好き
  • 3. 自己紹介(2)http://ke-tai.org/
  • 4. 自己紹介(3) →                 ↓先日、自販機の営業さんが来て、現在導入予定無料設定なので、ボタンを押すだけで、コーラが飲める環境に!!
  • 5. 会社紹介株式会社インフィニットループ所在地: 札幌市中央区設立: 2007年6月人員: 27名(契約・アルバイト含む)業務内容:ソーシャルゲーム開発• もともと数人規模のよくあるウェブアプリケーション開発会社だったが、ブ ラウザゲーム開発をきっかけに、メイン事業を「ゲーム開発」「高負荷サ ーバサイド開発」にシフト• 絶賛人材募集中!! このスライドを見て興味を持たれた方は是非声を掛けてください
  • 6. 開発実績[ブラウザ三国志] ブラウザ三国志] 三国志 運営(株)AQインタラクティブ 開発ONE-UP(株) プログラム開発を(株)インフィニットループが担当 2009年7月正式サービス開始 公式のほか、mixi、Yahoo!モバゲー、ハンゲーム、 ニコニコアプリなど多くのプラットフォーム・チャネリングに対応、 海外にも展開中[英雄クエスト] 英雄クエスト] クエスト 運営・開発ONE-UP(株) サーバ側プログラム開発を(株)インフィニットループが担当 2010年10月正式サービス開始 Yahoo!モバゲーにて運用中
  • 7. 本日の内容1. ソーシャルゲーム案件の特徴 6. アプリ実装のポイント2. 基本設計とポリシー 7. DBのインデックスについて3. サーバとアプリの構成 8. DBのロックについて4. なぜPHP+MySQLなのか 9. ロック処理のコツ5. DBの多重化について 10. KVSの利用
  • 8. ソーシャルゲーム案件の特徴・ 基本動作は、通常のウェブアプリケーション案件と同じ→ HTMLとCSSで作られた画面の遷移→ FlashやJavaScriptによる処理→ DBへの登録・修正・削除→ 培った業務スキルは、そのまま流用出来る・ 通常案件との違い→ アクセス数や負荷が桁違いに大きいため、負荷対策が必要→ 多ユーザの同時操作に耐えるため、ロック等はしっかりと→ 開発規模が大きく、スピードが求められる  ・ 個人戦での限界、チーム開発は必須  ・ 開発だけではなくマネジメント的な要素も求められる  ・ 仕様書ありきの仕事ではない、コミュニケーションスキルが必要  ・ リリースしてからが本当の戦い   (感覚的にはリリース時点で、全体の60%くらい)
  • 9. 基本設計とポリシー(1)破綻をきたさない設計が重要 【よくある失敗パターン】  1. とりあえず仕様を満たすように開発を進める  2. テストもパスしてオープンした  3. 利用者が増え、負荷が大きくなる  4. サーバ台数を増やすなどして対処するが、設計上の問題からボトルネック    発生し、ある一定数以上の接続数はどうしても捌くことができない  5. 慢性的に重い状態となり破綻※テストの段階で、本番と同等の負荷をかけるのはかなり難しい※ゲームという性質上、利用人数の増加が読めない→ サーバ台数を増やすことで、   処理能力を上げられる設計が重要
  • 10. 基本設計とポリシー(2)負荷対策を考慮した設計が重要・ 負荷を「さばく」よりも、負荷を「かわす」方法を考える・ データはとにかく溜めないこと → データには保存期限を設ける → DELETE文は遅いので、バッチ削除とかは無理が出てきやすい → データを追加するときに、最も古いデータを消すなどの工夫が必要・ 厳密に扱う必要がないところは、どんどんルーズに → 重要度が低く、変更が頻繁なデータは、DBに保存しない → 例えばメールの新着チェックは、毎回行わずにn回に1回とする・ ゲーム企画チームとのすり合わせがすごく大事 → 負荷との戦いは、ゲーム仕様を決めるところから始まっている → 仕様書が来てから仕事開始ではない
  • 11. 基本設計とポリシー(3)仕様はなるべく簡単に → 面白さに影響が出ないのであれば、仕様は簡単な方が良い → 仕様を限定しないと、のちのちサーバ負荷に限界が出てくる 難しい仕様の例 簡単な仕様の例 全プレイヤーが1つのワールドでプレイ ワールドで分けられる (分割は不可) (ワールド単位でのサーバ分割が可能) 他者との関わりが多い 他者との関わりが少ない (連携プレイが主のため、ユーザ単位での分割が難しい) (ユーザID単位での分割が可能、排他ロックも不要) 二窓でのプレイを許可する 二窓でのプレイができない/許可しない (同時操作系のバグが起こりやすい) (同時操作系のバグが起こりにくい ※) アイテムに個数制限がある 例:武器Aは世界に10個まで 個数制限はない (厳密なロック処理が必要) (ロック処理は比較的ルーズでも大丈夫 ※) 処理結果が公開され、多くの人の目に触れる 処理結果が1度しか表示されず、1人にしか見えない (処理に間違いが許されない) (処理に多少の間違いがあっても気づかれない ※) ※バグを容認しているわけではないです バグを容認しているわけではないです
  • 12. サーバとアプリの構成(1)使用している主なOSとソフトウェア HTTPアクセス・ Linux・ Apache ロードバランサ (Varnish) HTTP振り分け・ PHP・ MySQL バッチ処理サーバ Webサーバ Webサーバ Webサーバ ・ ・ ・・ memcached (Apache) DBアクセス (Apache) (Apache)・ (+ MongoDB) キャッシュサーバ (memcached) 負荷に応じて 負荷に 台数を 台数を調整 DBマスター (MySQL) ログサーバ レプリケーション (syslogd)この構成でほとんどの ・ ・ ・ゲームに対応可能 DBスレイブ (MySQL) DBスレイブ (MySQL) DBスレイブ (MySQL)
  • 13. サーバとアプリの構成(2)サーバ環境にはクラウドサービスを利用している。ヒットするかどうかで、利用者数の変化の激しいゲーム案件は、クラウドサービスとの相性が良い。(可能ならDBマスターなど、要所にリアルサーバを併用できるとなお良い)・ Amazon EC2 → 他と比べると安価な料金 → コントロールパネルやコマンドから全て操作可 → オートスケーリングが利用可能 → 2011年春には、東京リージョンができ、通信レスポンスも早くなった・ 国内クラウドサービス → 料金ちょっと高め → 日本語による手厚いサービス → 業者によっては、インスタンスを足すのに、   営業に連絡して数日かかるなど、スピード感に欠ける
  • 14. なぜPHP+MySQLなのか・ 高負荷での運用に、数多くの実績がある鉄板構成・ ネット上の情報も多く、実務に反映しやすい・ チームマネジメント上もメリットが多い → 人材確保が容易、教育も容易 → 開発スピードの向上に繋がる・ PHPのダメなところはコーディング規約でカバー・ APCは必ず導入 → 試した範囲では、他の高速化エンジンよりもかなり早い・ MySQLはなるべく新しいバージョンを
  • 15. DBの多重化について・ MySQL標準のレプリケーション機能を使っての、 マスター/スレイブ構成が基本・ スレイブは数を増やせば良い、マスターの負荷軽減が課題となる・ マスター分割は、ゲーム上の仕様も絡んできて、難易度も高い・ レプリケーション遅延を防ぐ工夫をする→ サイズがメモリに収まる範囲なら、スレイブはtmpfs上に展開→ 参照率をアプリ側で制御できるようにする・ マスター/スレイブの使い分けには主に2つのアプローチがある→ 最初マスターしか見ないように作って、   安全な部分から徐々にスレイブやKVSを見るように切り替えていく→ 普段はスレイブ、トランザクション開始時にマスターに接続を切り替える・ 「MySQL Cluster」、「XAトランザクション」ってどうなんだろう
  • 16. アプリ実装のポイント・ フレームワークは使わないもしくは自作 → 既存フレームワークを使っても結局改造するはめに → 機能よりも速度重視 → Flashなどのクライアントアプリとの連携部は作り込んだ方がよい・ O/Rマッパーは使用していない → 管理できないSQLは発行されないようにする → 自作のクエリビルダー的なものを作って利用している・ アプリを書くときは処理スピードをそれほど意識しなくても大丈夫 → がんばって書いても、それほど負荷は下がらない → それよりもDBの負荷を下げるほうが効果的 → ただし共通処理(毎アクセス処理される箇所)は、気合を入れる → 大量の配列処理は遅いので注意 → Apacheログから重いページランキングを生成し、上から順に潰す
  • 17. DBのインデックスについて(1)ここが負荷対策の最大のキモ!!・ インデックスとは → 本でいう索引のようなもの → 適切に利用すると、何十倍・何百倍も速度が変わることも・ むやみに張ればいいというものではない → 索引を増やすと本が厚くなる(サイズが大きくなる) → INSERT, UPDATE, DELETE時にインデックスを    作り直すので、速度が低下する → インデックスサイズがメモリに収まるサイズを超えると、    その瞬間から大幅に速度が低下する・ インデックスを適切に使うよう、SQLをチューニングしていく → インデックスを張っても、SQLの書き方によっては使われない → EXPLAINで確認しながら、チューニングしていく
  • 18. DBのインデックスについて(2)プログラマのインデックスをめぐる一生1. インデックスなんて知らない期 → インデックスの存在自体を意識したことがない → そもそも利用者が少ないアプリしか作ったことがない2. インデックス初体験期 ↓ → 初めて負荷のかかるアプリを作り、インデックスの存在を知る → インデックスを張ったところ、それだけで負荷が数分の1に → 興奮し、サルのようにインデックスを張りまくる3. インデックスわかってきた期 ↓ → インデックスは張りすぎてもダメとようやく気づく → 複合インデックスを活用しはじめる → インデックスサイズを意識しだす
  • 19. DBのインデックスについて(3)インデックスを使う上での主な注意点・ 「!=」、「<>」はインデックスが使用できない・ LIKE検索時、前方一致以外では、インデックスは使用できない・ ORや範囲検索(不等号)はインデックスが使用できないことがある・ ORDER BYは、インデックスを使用できないパターンが多数ある・ とにかくEXPLAINが大事、MySQLのスロークエリログも参考になる→ プロジェクト内の全てのプログラマに周知徹底を! 参考: インフィニットループ技術ブログ ソーシャルゲーム開発者なら知っておきたい MySQL INDEX + EXPLAIN入門      http://www.infiniteloop.co.jp/blog/2011/03/mysql-index-explain/
  • 20. DBのロックについて(1)これをしっかりやらないと、リリース後バグだらけに!!・ ロックはとても大事→ ロックをしっかりかけていないと、連打や同時操作でバグが起こる→ テスト環境では、再現しないことも多いのでやっかい・ 行ロックを使う、テーブルロックは使っていない・ ストレージエンジンには「InnoDB」、 分離レベルには、「REPEATABLE READ」を使っている・ ロックの挙動は複雑で、しっかり理解することが重要・ 特に行ロック時に、インデックスが使われなかった場合は、 テーブルロックがかかってしまうため注意が必要
  • 21. DBのロックについて(2)プログラマのロックをめぐる一生1. ロックなんて知らない期 → ロックの存在自体を意識したことがない → そもそも複数人数が同時に使うアプリを作ったことがない2. ロック初体験期 ↓ → 初めて負荷のかかるアプリを作り、同時更新系バグを出す → ここで初めてロックの重要性を知り、恐怖する → 興奮し、サルのようにロックをしまくる、とにかくロック → 「Deadlock」、「Lock Wait Timeout」祭りがはじまる ↓3. ロック青年期 → ロックしすぎはダメと気づく → 「SHOW ENGINE INNODB STATUS」の情報を活用 → ロックの内部処理や挙動を意識しだす
  • 22. DBのロックについて(3)行ロックの挙動 ※ 例は全てMySQL5.1系で検証例1: 存在するレコードを行ロックした場合SELECT * FROM t WHERE c = 2 FOR UPDATE Gap(Infimum) DELETE FROM t WHERE c = 2 1 Gap × 2 L Gap 5 × INSERT INTO t (c) VALUE(2) Gap(supremum) 参考: ・インフィニットループ社内勉強会資料 佐々木 亨基 MySQL InnoDB によるロック処理入門  ※近日公開予定      ・技術評論社  奥野幹也 著 エキスパートのためのMySQL運用+管理トラブルシューティングガイド
  • 23. DBのロックについて(4)ギャップロックの挙動例2: 存在しないレコードを行ロックした場合SELECT * FROM t WHERE c = 4 FOR UPDATE Gap(Infimum) SELECT * FROM t WHERE c = 3 1 FOR UPDATE Gap ○ 2 × INSERT INTO t (c) VALUE(3) × Gap L 5 INSERT INTO t (c) VALUE(4) Gap(supremum) レコードが存在しないため、ギャップがロックされる レコードが存在しないため、ギャップがロックされる しないため
  • 24. DBのロックについて(5)デッドロックの挙動二つ以上のセッションが互いの処理待ちとなり、各セッションの処理が進まなくなった状態例3: ロックして存在確認後、レコードがなければインサートする※ t に c < 200 のデータしか無い場合 A B SELECT * FROM t WHERE c = 200 FOR UPDATE SELECT * FROM t WHERE c = 300 FOR UPDATE INSERT INTO t (c) VALUE(200) INSERT INTO t (c) VALUE(300)これがデッドロックになる
  • 25. ロック処理のコツ・ MySQLのロック処理は複雑で、新米プログラマを含めた全員が、 完全に理解するのは難しい(INSERTが絡むと特に複雑)・ 基本指針を示し、難しい箇所はリードエンジニアがレビューで対応・ 基本は、「トランザクション開始後に、すぐ更新対象をロック」・ ロック時にインデックスが使用されていることをEXPLAINで確認・ 値を加算/減算をするときは、なるべくSQLの中で行う → UPDATE example_tbl SET a = a + 1 WHERE foo = ‘bar’; とても書き切・ ロックで取ったもの以外、値が正しいことを信じない れないので、 → スレイブ遅延やファントムリードに気をつける 近日中に弊社 技術ブログで・ デッドロックは、ロック範囲の見直しと、リトライで対処する 別途資料を 公開予定・ MySQLの気持ちになって考えるのが大事
  • 26. KVS(キーバリューストア)の利用・ KVS(memcachedなど)は、一時期積極的に利用したが、 今は一部での利用に留めている・ 開発やテストのコストがかかる → キャッシュのクリア漏れによるバグを生む → トランザクション中にKVSのデータを扱うのは難しい・ システム全体のトータルコストで考える → KVSから値を取得し、それをアプリ側で結合するくらいなら、    MySQLのJOINの方が早い・ 使うところにはもちろん使う → PHPのセッション管理 → 変更が入らないマスタテーブル類のキャッシュ → 読み込み回数が著しく多い箇所
  • 27. まとめ・ ゲーム案件であっても、特に変わったことはしておらず、 基本が大事、基礎に忠実に淡々と・ なるべく負荷をかけないゲーム仕様になるようすり合わせを・ SQLチューニングとインデックスの見直しが 負荷対策の中核・ ロックは大事、しっかりとした理解が必要・ キーバリューストアは、全体のコストを考えて 使いどころを検討して使う・ MySQL(というかデータベース)は本当に難しい!! → オレたちは、このMySQL坂を登りはじめたばかり
  • 28. 最後に・ ゲームの仕事は、大変なこともあるが面白い 仕事を楽しんでやることが重要・ 参考ゲームや自分の作ったゲームを、きちんとプレイすること が大事、ゲームを理解せずにゲームは作れない・ 皆に愛されるものを作れたときは、本当に幸せ・ プレイヤーやパートナーに対し、 いつも感謝の心を忘れずに
  • 29. おまけ(1) スタッフ募集のお知らせ株式会社インフィニットループでは、一緒に楽しんでゲームを作ってくれるスタッフを募集しています・ PHPプログラマ、Rubyプログラマ・ ActionScriptプログラマ・ データベースエンジニア・ サーバエンジニア・ ゲーム企画・運営経験者興味のある方は、直接声を掛けていただくか、HPからお問い合わせください
  • 30. おまけ(2) アルバイト募集のお知らせ株式会社インフィニットループでは、アルバイトも募集しています。・ プログラマ見習い・ テスター(プログラムのテスト、バグ検証)・ その他雑務せっかくプログラムを書けるスキルを持っているのに、コンビニ等でバイトするのは勿体ない!!学生歓迎、ノートPC貸与興味のある方は、直接声を掛けていただくか、HPからお問い合わせください