Lv1から始めるWebサービスのインフラ構築
Upcoming SlideShare
Loading in...5
×
 

Lv1から始めるWebサービスのインフラ構築

on

  • 211 views

2014年9月9日開催の"AWS Cloud Storage & DB Day"で使用した講演資料です。 ...

2014年9月9日開催の"AWS Cloud Storage & DB Day"で使用した講演資料です。

以下のURLからもダウンロードすることができます。
http://iy-h.com/03/aws-storage-day-2014-09-09.pptx

Statistics

Views

Total Views
211
Views on SlideShare
211
Embed Views
0

Actions

Likes
4
Downloads
0
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

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
  • みなさんこんにちは。 <br /> <br /> 「今日はLv1から始めるWebサービスのインフラ構築」と題しまして、 <br /> いろいろとお話をさせて頂きたいと思います。 <br />
  • 軽く自己紹介させて頂きます。 <br /> <br /> 伊藤祐策と申します。 <br /> 株式会社マイネットという会社で働いています。 <br /> <br /> 会社の事業内容としては、 <br /> スマートフォン向けゲームアプリを展開しておりまして、 <br /> そのなかのインフラ構築やサーバーサイド設計などを <br /> 主なお仕事としています。 <br />
  • 一番好きなAWSのサービスはDynamoDBです。 <br /> 今日はDynamoDBについて沢山お話させて頂きます。 <br /> <br /> あと、S3とかクラウドフロントとかも大好きです。 <br />
  • まあでも青いアイコンのやつはだいたい大好きです。 <br /> これらについても沢山お話しようと思います。 <br />
  • 今日のお話はこんな人におすすめです。 <br /> <br /> Webサービスを作って <br /> スタートアップしたい人 <br /> <br /> ユーザー数1人から100万人までをAWSで、 <br /> というテーマでお話をしていきたいと思います。
  • 今回のもくじはこのような感じになっています。 <br /> <br /> 各部10分くらいで、途中で質問タイムを適宜はさんでいく予定ですので <br /> 話の中で疑問点があれば控えておいてください。 <br /> <br />
  • それでは早速、 <br /> 第一部「Lv1から始めるWebサービス」について <br /> お話をしていきたいと思います。
  • 今回は、話の内容を理解しやすくするため、ちょっとしたシナリオを用意しました。 <br /> <br /> あなたはとあるWeb系会社のエンジニアです。 <br /> ある日、社長が突然こんなことを言い出しました。 <br /> <br /> 「我が社もソーシャルゲーム事業に参入するぞ!」 <br /> <br /> 一瞬目眩がしましたが、あなたは覚悟を決めてシステム設計を開始しました・・・。 <br /> <br /> もちろんこのシナリオは全てフィクションです。 <br /> <br /> 今日お話する内容は、ソーシャルゲームはもちろん、 <br /> 一般的なWebサービスにもお使い頂けるノウハウを <br /> 惜しむことなくお話していきたいと思います。 <br />
  • さて、それでは早速、Webサービスの開発を開始してから <br /> リリースするまでの大まかな流れを考えてみましょう。 <br /> <br /> 第一部では、先にリリースについてフォーカスをあててお話していこうと思います。 <br /> <br /> アプリケーション開発がある程度終わったら、本番環境を構築して社内のスタッフを集め、 <br /> ユーザー数10人程度でアルファテストをすることになると思います。 <br /> <br /> これがLv1です。 <br /> <br /> 続いてベータテストに移行して、いよいよ一般ユーザーの受け入れをしていきます。 <br /> この頃にはもう、スケーラビリティのことを考慮した構成にしてきたいですね。 <br /> このあたりは第二部で詳しくお話していきたいと思います。 <br /> <br /> そして、ベータテストを終えると正式オープンすることになりますが、 <br /> ここからはいよいよ生半可な構成では太刀打ちできなくなる可能性が出てきます。 <br /> このあたりについては第三部でじっくりお話していきたいと思います。 <br />
  • 再びシナリオに戻ります。 <br /> <br /> 先輩社員の助言によりAWSを採用することは決定しましたが、あなたはAWSは全くの未経験でした。 <br /> そこでまずはAWSのアカウントを取るところから始めることにしました。 <br /> <br /> 最初の目標は「アルファテスト用の環境を構築する」です。 <br /> <br /> とはいっても、まだ開発が開始されていないので、技術検証の意味も兼ねての環境構築となります。 <br />
  • Step1、まずはAWSアカウントを取得しましょう。 <br /> <br /> 弊社の場合、1サービスにつきAWSアカウントを1つ用意するようにしています。 <br /> 現在ゲームタイトルを3つ運用しているので、3アカウントを並行して運用しています。 <br /> <br /> それとは別に、開発環境用、兼試験環境のアカウントを1つ取得して使っています。 <br /> これは本番環境と同じ環境での動作検証をする時や、AWSコンソールの操作訓練等に使っています。 <br /> <br /> 訓練とはいてEC2インスタンスを立てたりするので費用は発生しますが、 <br /> 訓練費用を惜しむとあとで倍返しがくるのでケチらず予算をとってやっています。 <br />
  • Step2、IAMで子アカウントを作りましょう。 <br /> <br /> AWSアカウントを取得すると、まずはルートアカウントが作成されます。 <br /> ルートアカウントは登録時のメールアドレスでログインします。 <br /> <br /> しかし、AWSコンソールは複数のスタッフが触ることになるので、 <br /> アカウントを共有する形にすると後々不便がでてきてしまいます。 <br /> <br /> そこで使うのがIAMです。IAMはルートアカウントに紐付いたサブアカウント群です。 <br /> <br /> IAMは大きく2種類に分類でき、「人間ユーザー」と「アプリケーションユーザー」の2つがあります。 <br /> <br /> 「人間ユーザー」のほうはリアルな人間1名につき1ユーザーを発行してください。 <br /> エンジニアであれば Administrator 権限のテンプレートをそのまま使っても良いでしょう。 <br /> <br /> 一方、「アプリケーションユーザー」ですが、こちらはアプリケーションからAWSの各種サービスを <br /> APIを使って操作するときに必要になるものです。 <br /> 一般的なLAMPだけの構成では必要ないこともあります。 <br /> <br /> アプリケーションユーザーは、必要最低限の権限だけを付与するようにします。 <br /> たとえばS3の出し入れだけとか、DynamoDBへのアクセスだけ、といった感じです。 <br /> <br /> IAMユーザーをひと通り作成し終えたら、ルートアカウントは封印しておきましょう。 <br /> ルートアカウントを乗っ取られるとサービスは一巻の終わりです。
  • Step3、VPCの作成をしましょう。 <br /> <br /> VPCとは仮想プライベートネットワークのことです。 <br /> 昔はVPCを作らずともEC2の起動ができたのですが、今はもうできません。 <br /> <br /> LANやルータのセットアップをしてきた人ならば簡単に覚えられるので、 <br /> これを機に習得してしまいましょう。 <br /> <br /> やることは、プライベートネットワークのサブネット設計と、ゲートウェイの配置だけです。 <br /> <br /> ここでポイントなのは、サブネットをちゃんと考えて切ることと、オートアサイン パブリックIPをONにすることです。 <br /> オートアサイン パブリックIPをONにすると、EIPの使用数を節約することができます。 <br /> <br /> なお、EIPはデフォルトで5個までしか取得できません。5個以上は申請が必要となります。 <br />
  • サブネットの切り方の例です。 <br /> <br /> 大事なポイントは、全部の領域を使いきってしまうとあとで困るということです。 <br /> <br /> 切り方については、特にこだわりがなければ半分づつ切るという方法を使うことをオススメします。 <br /> <br /> 10.1のサブネットの場合、/16なので最初は16bit分の領域があります。 <br /> これを/17で切って、約3万2千の領域を「アベイラビリティゾーン a」に割り当てます。 <br /> <br /> AWSアカウントによっては「アベイラビリティゾーン a」ではなくbとかcになることもあるので注意してください。 <br /> この例ではaとcの組み合わせを前提としています。 <br /> <br /> 続いて10.1.128を/18で切って約1万6千の領域を「アベイラビリティゾーン c」に割り当てます。 <br /> <br /> さらに残りの10.1.192を/19で切って再び「アベイラビリティゾーン a」に割り当てます。 <br /> <br /> 1つ目のサブネットはEC2インスタンスの領域に。 <br /> 2つ目と3つ目は後述するRDSの「マルチAZ配置」で使います。 <br />
  • Step4、セキュリティグループを作成しましょう。 <br /> <br /> セキュリティグループとは、要するにファイアーウォールです。 <br /> iptables等のOS付属のファイアーウォールはこれがあれば要らないので切ってしまって構いません。 <br /> <br /> セキュリティグループはEC2インスタンスの役割種別ごとに作成して適用します。 <br /> たとえばWebサーバーであれば、外部から80番と443番を開けておきます。 <br /> <br /> SSH経由でメンテナンスすることも必要なので、プライベートネットワークから22番を許可しておきます。 <br /> <br /> RDSを使う場合にもセキュリティグループが必要なので、適宜作成しておきましょう。 <br />
  • Step5、EC2インスタンスを作成しましょう。 <br /> <br /> ここでやっとEC2インスタンスを作成することができます。 <br /> <br /> 前置きが結構長かったですが、 <br /> IAM、VPC、セキュリティーグループ、 <br /> どれも必修なので必ず習得しておきましょう。 <br /> <br /> さてEC2インスタンスの起動するときに注意しなければならないのが、 <br /> 配置先のアベイラビリティゾーンです。 <br /> <br /> アベイラビリティゾーンとは、データセンター、つまり物理的な場所のことです。 <br /> <br /> アベイラビリティゾーンはどのアカウントからでも最低2つは利用可能なのですが、 <br /> どちらか一方をメインと決めて利用しないと、リザーブドインスタンスという <br /> 割引制度を利用するときに困ります。 <br /> <br /> また、インスタンスタイプが枯渇して起動できないこともごくまれですが起こります。 <br /> 事前に営業担当をつけて相談しておくと、設備に余裕のあるアベイラビリティゾーンを教えてもらいます。 <br /> <br /> どうしてもインスタンスタイプの枯渇を回避したければ、リザーブドインスタンスを購入しておきましょう。 <br /> 購入した分だけは必ず起動できることが保証されます。 <br /> <br /> 最後に、セットアップが完了したEC2インスタンスは、一度シャットダウンしてAMIをとっておきましょう。 <br /> <br /> AMIをとっておけば、同じセットアップ内容のEC2インスタンスを複数起動したり、 <br /> 万が一EC2インスタンスが起動できなくなったときにAMIから起動しなおすことが可能です。 <br />
  • Step6、EIPを取得しましょう。 <br /> <br /> EIPとはグローバルIPアドレスのことです。 <br /> <br /> EIPを取得して、各インスタンスの仮想ネットワーク・インターフェースにアタッチすることで利用可能になります。 <br /> <br /> 先ほども説明しましたが、EIPはデフォルトで5個までしか取得できません。 <br /> 5個以上が必要であれば申請フォームから制限解除申請を送る必要があります。 <br /> <br /> また、インスタンスタイプ別にもEIPのアタッチ数制限があります。 <br /> たとえばマイクロインスタンスだとEIPは1つしか付けることができません。 <br /> <br /> 思わぬトラップにはまらないよう、事前に公式ドキュメントを確認しておきましょう。 <br />
  • ところでEIPについてですが、さて一体いくつあれば十分なのでしょうか。 <br /> <br /> 弊社事例だとこんな感じです。 <br /> <br /> 一般公開サイト用 <br /> 運営管理サイト用 <br /> メール配信サーバー用 <br /> SSHゲートウェイサーバーというメンテナンス用の裏口の4つです。 <br /> <br /> だいたい4つもあれば足りるはずなのですが、 <br /> もし5個以上使うような場合はサポート窓口に相談して <br /> 代替手段がないか聞いてみましょう。 <br />
  • Step7、ルート53の設定をしましょう。 <br /> <br /> Amazonルート53はDNSホスティングサービスです。 <br /> <br /> AWSを使うのであれば、DNSサーバーのホスティングはルート53を使いましょう。 <br /> 各種AWSサービスとの強力な連携機能があるので使わない手はありません。 <br /> <br /> ルート53でゾーン設定をしたのち、さきほど取得したEIPをここで登録します。 <br /> <br /> ここでのポイントですが、メールを送信するサービスであればSPFの設定と、 <br /> さらにEIPごとのメール送信制限解除申請も行っておきましょう。 <br /> <br /> 多くの人がこれを忘れて痛い目を見ています。 <br /> <br /> 申請はだいたい2~3日程度で通りますが、追加料金等はかからないので早めに済ませておきましょう。 <br />
  • 以上を踏まえた上で作られたシステムの構成はこのようになります。 <br /> <br /> EC2インスタンスはt2.microで、直接EIPを付与してインターネットからの通信を受け止める形にしました。 <br /> <br /> 月額2000円程度の非常にマイクロな構成です。 <br /> <br /> ユーザー数10人程度であればこのくらいで十分でしょう。 <br />
  • アプリケーションも完成に近づき、いよいよ一般ユーザーへサービスを公開することにしました。 <br /> <br /> しかし先輩社員はこんなことを言いだしました。 <br /> <br /> 「この構成でインスタンスタイプあげるだけじゃダメなの?」 <br />
  • ここで問題です。 <br /> <br /> この構成のままインスタンスタイプを上げるだけでは商用環境としてダメな理由を答えなさい。 <br />
  • 答えは「データの保全性が確保されていないから」です。
  • そもそもWebサービスとは、このような2つの要素から成り立っているものなのです。 <br /> <br /> 「アプリケーション」と、「データ」。 <br /> <br /> アプリケーションというのはプログラムはもちろん、サーバーそのものやサーバー構成、サーバーコンフィグ等も含まれます。 <br /> <br /> 一方でデータというのは、サービスインから蓄積されてきた全てのユーザーデータです。 <br /> <br /> これを万が一失ってしまうと、ユーザーからの信用を失ってしまい、 <br /> 二度とサービスを再開させることはできなくなってしまいます。 <br /> <br /> アプリケーションを肉体とすれば、データは魂です。つまり、Webサービスは生き物なのです。 <br />
  • さて、この2つの保全性について、それぞれ考えてみましょう。 <br /> <br /> アプリケーションの部分は今であればsubversionやgithub等の <br /> 保全性がある程度確保された場所に置かれているので、 <br /> 万が一構築したサーバー達が吹き飛んでしまってもリストアが可能です。 <br />
  • 一方で、Webサービスの魂である「データ」は、 <br /> 先ほどの構成ではEC2のEBS上に置かれていました。 <br /> <br /> EBSはデータの保全性を保証していないので、 <br /> ある日突然消失することもありえるのです。 <br /> <br /> 万が一消失したときは、即サービス終了で再起不能に陥ってしまいます。 <br /> <br /> 何百万もの開発費をかけて作り上げたものが、ある日突然無価値になってしまったら <br /> 会社はいったいどうなってしまうのでしょうか?ちょっと想像してみてください。 <br />
  • というわけで、商用環境としての最低ラインはこのように設定するわけです。 <br /> <br /> 「隕石が直撃しても大丈夫」 <br /> <br /> 商用環境として運用するのであれば、 <br /> データセンターが1つくらい壊滅したとしても <br /> サービスをすぐに復旧させて再開できる状態を目指しましょう。 <br />
  • 改めて、商用環境としてのLv1の構成はどのようになるのか考えてみましょう。 <br /> <br /> 大事なポイントはデータを置く場所であるデータベースを <br /> RDSのマルチAZ配置にしておくことです。 <br /> <br /> マルチAZ配置にしておけば、リアルタイムにデータセンター間での <br /> レプリケーションが行われ、片方が突然消失しても <br /> データの損失は最小限に留めることができます。 <br /> <br /> もうひとつ大事なのは、EC2インスタンスをAMIとして保存しておくことです。 <br /> <br /> AMIはS3上に保存されるので、 <br /> こちらもデータセンターが1つ壊滅したくらいでは消失することはありません。 <br />
  • もう少しがんばって、Lv2の構成がこちらになります。 <br /> <br /> さきほどの構成にELBを追加して、ログの保存をS3に出力させるようにします。 <br /> <br /> ELBに限らず、あらゆるログはトラブル発生時の大事な資料となります。 <br /> 得られたログはとりあえずS3に保存しておく習慣をつけておきましょう。 <br />
  • では早速、データセンターに隕石をぶち当ててみましょう。 <br />
  • さきほどの構成が・・・。
  • このように壊滅してしまいました。 <br /> <br /> この構成図のうち、バツ印は消失してしまったものです。 <br /> <br /> 一方、マルになっているところは <br /> 複数のデータセンター間で保全性が保たれているおかげで <br /> 無事であることが保証されているもの達です。 <br /> <br /> これだけ残っていればサーバーを再構築して、 <br /> 再びサービスを再開させることが可能なわけです。 <br /> <br /> 多少ダウンタイムは発生しますが、 <br /> 隕石が落ちたということで言い訳くらいは効くでしょう。 <br /> <br /> 隕石が落ちても1日以内に復旧できるのであれば十分優秀です。 <br />
  • ではここで問題です。 <br /> <br /> これらのAWS各種ストレージサービスのうち、 <br /> デフォルトで保全性が確保されているものはどれでしょう? <br /> <br /> Amazon S3 <br /> Amazon Elastic Block Store <br /> Amazon DynamoDB <br /> Amazon RDS Multi-AZ配置 <br /> Amazon ElastiCache <br />
  • 正解はこちらになります。 <br /> <br /> S3、DynamoDB、RDSのMulti-AZ配置が正解です。 <br /> <br /> その他は保全性が保証されていないので、消えてはこまるような大事なデータは置かないようにしましょう。 <br />
  • 第一部のまとめです。 <br /> <br /> 「大事なデータ」は保全性が確保されているストレージサービスに保存しましょう。 <br /> データさえ生き残っていればサービスは何度でも蘇ります! <br />
  • 最後におまけです。 <br /> <br /> この式はみなさん、見覚えあるかと思います。 <br /> <br /> 可用性 = 全稼働時間 ÷ 平均故障間隔。 <br />
  • よく話題になるのはMTBFを伸ばそうというお話なのですが、 <br /> 冗長化技術はだいぶ枯れて普及もしてきたので今回は態々お話はしません。 <br /> <br /> 一方でMTTRを短くしようとか、 <br /> ∞になるのを回避しようという話は <br /> 滅多に話題になることがないので <br /> 今回取り上げてみたという次第です。 <br /> <br />
  • 以上で第一部はおしまいです。 <br /> <br /> ここでいったん質問タイムを取りたいと思います。 <br /> <br /> なにか聞きたいことがありましたら遠慮なく手を上げて下さい。 <br />
  • それでは第二部いってみましょう! <br /> <br /> 第二部のテーマは「スケーラブルな構成にするには?」です。 <br />
  • 第一部では、保全性の確保された構成の構築方法はわかったのですが、 <br /> この「商用Lv2」の構成ではベータテストの負荷には耐えられそうにありません。 <br /> しかし、ベータテストでは何人のユーザーが押し寄せるのか全く検討もつきません。 <br /> <br /> そこで次の目標は、「想定以上の負荷が来てもすぐに対応できる環境を構築する」です。 <br />
  • ここで用語をちょっとおさらいしてみましょう。 <br /> <br /> 「スケーラブル」とはいったい何でしょうか? <br /> <br /> 1. 増大する負荷に容易に対応できる <br /> <br /> 2. 負荷に合わせて自動的に拡張される <br /> <br />
  • 答えは1です。 <br /> <br /> 2のほうはだいぶレベルの高い話になるので、また別の機会にさせてください。 <br />
  • もうひとつ用語のおさらいです。 <br /> <br /> スケールアップとは、ノードの性能を上げることです。 <br /> すなわち、EC2のインスタンスタイプを上げることです。 <br /> <br /> 一方、スケールアウトとは、ノードの数を増やして全体性能の向上を図ることです。 <br /> これはつまり、ロードバランサー下のインスタンスを追加することとなります。 <br />
  • スケーラブルな構成には、理想パターンがあります。 <br /> <br /> 1つ目。EC2インスタンスを追加すると全体性能があがる。 <br /> <br /> 2つ目。RDSのリードレプリカを増やすと全体性能があがる。 <br /> <br /> 3つ目。DynamoDBの性能予約を買い足すと全体性能があがる。 <br />
  • 一方で将来が不安なパターンもあります。 <br /> <br /> インスタンスタイプを上げると全体性能があがる。 <br /> EBSのIO性能を上げると全体性能があがる。 <br /> <br /> 単一ノードの性能をあげると全体性能は当然あがるのですが、 <br /> コスト効率が徐々に悪くなってしまいます。 <br /> <br /> そしてさらに怖いのは、 <br /> 一番上位のインスタンスタイプに到達してしまうと、 <br /> そこがシステムの限界となってしまう点です。 <br />
  • つまり、スケーラブルなシステムとは、 <br /> システム構成をスケール「アウト」ができる形にすることです。 <br /> <br /> スケール「アップ」しかできない箇所を全て排除することができれば、 <br /> それは完璧なスケーラブル構成と言っても良いでしょう。 <br />
  • 以上を踏まえた上で、スケーラブルな構成の基本形はこのようになります。 <br /> <br /> 一段目にELBを置き、その配下にアプリケーションサーバーを複数台配置します。 <br /> <br /> さらにその奥にはリードレプリカを何台か備えたRDSを配置し、 <br /> 各アプリケーションサーバーは、データの書き込みをマスターDBへ、 <br /> データの読み込みをランダムに選定したリードレプリカで行います。 <br />
  • システムへの負荷は、大きく分けて <br /> CPU負荷、DB書き込み負荷、 <br /> DB読み込み負荷の3つに分類されます。 <br /> <br /> CPU負荷はEC2インスタンスのスケール「アウト」で対応します。 <br /> <br /> DB読み込み負荷はリードレプリカのスケール「アウト」で対応します。 <br /> <br /> 一方、DB書き込み負荷はマスターDBのスケール「アップ」でしか対応できません。 <br />
  • サーバー負荷の傾向として、 <br /> ボトルネックになるのはいつだってデータベースの書き込み負荷です。 <br /> <br /> 巷の大規模サービスを運営している会社のエンジニア達は、 <br /> マスターDBへの負荷をどうするかで、大体いつも頭を抱えています。 <br /> <br /> あるエンジニアは垂直分散で対応しようとしました。 <br /> しかしデータの不整合に悩まされるようになりました。 <br /> <br /> あるエンジニアは水平分散で対応しようとしました。 <br /> しかしDBサーバーの障害で死ぬ思いをしました。 <br /> <br /> あるエンジニアはカサンドラを使って死にました。 <br /> <br /> あるエンジニアは東京なんとかを使いましたがどうなったのかは知りません。 <br />
  • 話が暗くなってきたので、 <br /> ここでAWSのストレージ系サービスを簡単に紹介していきたいと思います。 <br /> <br /> Amazon RDS <br /> Amazon DynamoDB <br /> Amazon ElastiCache <br /> <br /> の3つについて順番に紹介しようと思います。
  • Amazon RDS <br /> <br /> ここがすごい! <br /> メンテナンスフリー!自動的に定期バックアップ! <br /> あの面倒くさいバックアップ関連の処理を全部やってくれます。 <br /> <br /> そしてAZ間で自動的にレプリケーション。ただしMulti-AZ配置を明示的に指定する必要があります。 <br /> 第一部でも解説したとおり、データの保全性を強力に担保してくれる機能です。 <br /> <br /> さらにリードレプリカをボタン1発で作成! <br /> <br /> リードレプリカとは、マスターDBへの書き込みを <br /> リアルタイムに反映して作られるマスターDBの複製です。 <br /> 多少の一貫性は落ちますが、それでも構わないデータはこちらから取得して <br /> 読み込み負荷を分散させることができます。
  • しかし注意しなければならない点もあります。 <br /> <br /> まず一度起動すると停止ができません。 <br /> 削除するまでずっと課金され続けてしまいます。 <br /> <br /> EC2であればインスタンスを停止している間は課金も停止するのですが、 <br /> RDSはそうはいかないので、よく考えてから建てなければいけません。 <br /> <br /> また、スケールアップするためにインスタンスタイプを変更すると、 <br /> 一時的にアクセスできなくなります。 <br /> <br /> ちゃんとメンテナンスモードを用意してからスケールアップ作業を実施する必要があります。 <br />
  • さらに、リレーショナルDB特有の問題もあります。 <br /> <br /> 先ほど述べた通り、マスターDBへの負荷はどうあがいてもボトルネックになるのです。 <br /> <br /> しかし手立てがもう無いわけではありません。 <br /> <br /> きっとなんとかしてくれる救世主が存在します。
  • Amazon DynamoDB <br /> <br /> AWSのすごい人が作ったすごい分散データベースです。 <br /> <br /> すごい点は沢山あるのですが、 <br /> なにより「負荷による性能劣化を起さない」 <br /> という所が一番すごいんです。 <br /> <br /> 課金額さえ増やせば無制限に性能が上がるというすごいデータベースです。 <br />
  • DynamoDBは確かにすごい奴です。 <br /> <br /> マスターDBへの負荷がどうしようもなくなったときの <br /> 救世主となってくれるかもしれません。 <br /> <br /> これについては第三部で詳しく解説します。 <br />
  • 一方、DynamoDBには弱点もあります。 <br /> <br /> まず、バックアップが簡単にとれません。 <br /> 「一貫性」か「動的」のどちらかを諦める必要があります。 <br /> <br /> また、課金額から決定された性能上限に達すると <br /> 一時的にアクセスできなくなります。 <br /> <br /> これらを想定した上でアプリケーションを書かないと <br /> あっというまにデータ不整合が発生します。 <br /> <br /> あと、集計などの複雑な処理はできないことです。 <br /> これは分散DBなので仕方ありません。 <br />
  • さて、DynamoDBはどこにどう使ったらいいのでしょうか。 <br /> <br /> 使い方は大きく2つに分けられます。 <br /> <br /> 1つ目は負荷分散のための補助的なデータベースとして使うことです。 <br /> <br /> 単純な読み書き処理しかしない箇所のストレージを <br /> DynamoDBに置き換えることで、マスターDBへの負荷の軽減を目論みます。 <br /> <br /> こちらは比較的リスクが少ないので、 <br /> NoSQL初心者にはオススメです。 <br /> <br /> 一方、2つ目は、覚悟を決めてメインデータベースとして使うことです。 <br /> <br /> こちらはアプリケーションエンジニアに相当な力量が必要とされます。 <br /> 生半可な技術力で挑むと火傷することは請け合いでしょう。 <br /> <br /> 詳しくは第三部で解説します。 <br />
  • 最後はElastiCacheです。 <br /> <br /> 「エラスティキャッシュ」と読むので間違わないようにしましょう。 <br /> <br /> ぶっちゃけると中身はただのmemcachedなので、 <br /> とにかく速い以外の特徴はありません。 <br /> <br /> でも最近、Redisエンジンも使えるようになったそうです。 <br />
  • とはいえ、あくまでも「キャッシュ」なので <br /> 大事なデータの格納はNGです。 <br /> <br /> まずは各種ストレージへの読み込み負荷軽減のために使いましょう。 <br /> <br /> memcachedもRedisも、とにかく速いのでレスポンスタイムの改善にも貢献してくれます。 <br />
  • 第二部のまとめです。 <br /> <br /> スケールアウト可能な構成をがんばって構築しましょう。 <br /> しかし、それでもいつかはマスターDBの負荷が限界にくることでしょう。 <br />
  • 以上で第二部はおしまいです。 <br /> <br /> ここでも質問タイムを取りたいと思います。 <br /> <br /> なにか聞きたいことがありましたら遠慮なく手を上げて下さい。 <br />
  • ではいよいよ第三部です。 <br /> <br /> この節ではDynamoDBの正しい使い方についてお話しようと思います。 <br />
  • ふたたびシナリオです。 <br /> <br /> 無事リリースされたサービスは幸運にも大ヒットし、 <br /> ユーザー数を急速に伸ばしていきました。 <br /> <br /> しかしマスターDBの負荷は増大し、 <br /> インスタンスタイプをdb.r3.8xlargeまで上げたのにも関わらず <br /> 性能の限界が来てしまいました。 <br /> <br /> そこであなたが決断した最後の手段とは・・・。 <br /> <br /> 次の目標は、DynamoDBを使ってピンチを乗り切ることです。 <br />
  • 第二部でも紹介しましたが、DynamoDBとはこのようなデータベースです。 <br /> <br /> アプリケーション開発者視点では、 <br /> 分散データベース、キーバリューストア、 <br /> NoSQL、スキーマレスという特徴を備えています。 <br /> <br /> インフラエンジニア視点だと、 <br /> フルマネージド型サービスであるという特長があります。 <br />
  • DynamoDBで上手に負荷を捌きたければ、 <br /> このような仕様を知って置かなければいけません。 <br /> <br /> まず、負荷分散はハッシュキーを基に分散が行われます。 <br /> このため、1つのキーにアクセスが集中してしまうような作りにしてしまうと <br /> パフォーマンスを思うように稼ぐことができません。 <br /> <br /> ハッシュキーを上手に設計できるかが <br /> 高いパフォーマンスを実現できるかのカギとなります。 <br /> <br /> また、読み込み性能、書き込み性能はそれぞれ <br /> 課金額によって上限が決まる仕様となっています。 <br /> <br /> 性能予約は「キャパシティーユニット」という <br /> 1秒あたりのアクセス量で指定します。 <br /> <br /> 予約した性能を超過した状態をおおよそ30秒くらい持続させてしまうと、 <br /> 性能超過エラーを返されて一時的にアクセス不能となってしまいます。 <br /> <br /> 弊社の場合、1日のピーク値が70%ラインになるように <br /> 余裕をもった予約をしています。 <br /> <br /> 若干コスト効率が悪いですが、自前で分散DBを構築するよりは <br /> ずっと安く済んでいるので、あまり惜しまずに性能予約をしています。 <br /> <br /> あと細かいですが、1レコードには64キロバイトまでしか入りません。 <br /> 大きなデータを格納したいときはS3を利用するようにしましょう。 <br />
  • 第二部でもお話しましたが、 <br /> DynamoDBはどのように使うかで難易度に大きく差が出ます。 <br /> <br /> ユーザー単位で独立しているデータで、 <br /> かつレコード同士の整合性を保つ必要がないものに関しては <br /> 比較的カンタンにDynamoDBへ移行することができるでしょう。 <br /> <br /> 一方、全てのデータをDynamoDBへ格納して、 <br /> 集計などの複雑な機能はRDSに任せるという使い方をする場合、 <br /> よりスケーラブルなシステムにすることが可能となる一方、 <br /> アプリケーションエンジニアは大変な思いをすることになるでしょう。
  • ではいよいよテーブル設計のコツについてお話しようと思います。 <br /> <br /> 大事なポイントは、「テーブル設計はプライマリキーの設計が命」ということです。 <br />
  • DynamoDBのプライマリキーには以下の2パターンがあります。 <br /> <br /> 1つ目はハッシュキーのみのパターン。 <br /> この場合、他のKVSと同じような使い方となります。 <br /> <br /> 2つ目はハッシュキー+レンジキーのパターンです。 <br /> <br /> レンジキーを設定しておくと、範囲を指定して <br /> レコードを一括取得することができるようになります。 <br /> <br /> ただし負荷分散はあくまでもハッシュキーでのみ行われるので、 <br /> アクセスが集中しないようによく考えて設計する必要があります。 <br />
  • ではテーブルの設計例をいくつか紹介していきます。 <br /> <br /> まずはハッシュキーに「ユーザーID」だけを使ったテーブルの例です。 <br /> <br /> アカウント情報やプロフィール情報等が適用例として考えられます。 <br />
  • 次はハッシュキーに「ユーザーID」、レンジキーに「対象ユーザーID」を設定した例です。 <br /> <br /> Twitterで言うフォローやブロックといった、 <br /> ユーザーから他のユーザーへの一方的な関係情報を <br /> 保存するテーブルに適しています。 <br />
  • 次はハッシュキーに「ユーザーID」、レンジキーに「ログID」を設定した例です。 <br /> <br /> これはユーザーの行動履歴を保存するテーブルに適したパターンです。 <br /> <br /> たとえば、ゲーム内でアイテムを購入したり、攻撃コマンドを実行した等です。 <br /> <br /> DynamoDBは行動履歴の保存に非常に適しており、このパターンはとても良く使われます。 <br />
  • さて、ログIDについてですが、IDの作り方にも工夫があります。 <br /> <br /> DynamoDBにはオートインクリメントといった機能は備わっていないので、 <br /> シーケンシャルなIDを生成するのは苦手です。 <br /> <br /> そこで、日付と時刻から固定長文字列でIDを生成するという方法を取ります。 <br /> <br /> マイクロ秒や乱数も付け加えておけば、まず衝突するようなことはありません。 <br /> 万が一衝突した場合は、再度生成してリトライすれば良いのです。 <br /> <br /> 日付時刻からIDを生成しておくと、レンジキーの範囲検索を日付指定で <br /> 検索することができるようになって非常に便利です。 <br />
  • 次は、行動履歴テーブルに似ていますが、今度はレンジキーに「オブジェクトID」を使うパターンです。 <br /> <br /> たとえばゲーム内でカードを新規に手に入れたとします。 <br /> <br /> このとき、カードの「オブジェクトID」を「ログID」と同じ方法で発行し、 <br /> レンジキーに指定してレコードを作成します。 <br /> <br /> こうすることで、ユーザーの「所有物」という概念を実装することができます。 <br />
  • 最後の例は少し特殊です。 <br /> <br /> ハッシュキーとして、2つのユーザーIDを連結した文字列を使います。 <br /> <br /> これはユーザー間の関係情報、 <br /> たとえばフレンド関係といった情報を格納するテーブルに適したパターンです。 <br /> <br /> 2者の関係を1レコードにまとめることにより、 <br /> 排他制御を簡単にすることができるようになります。 <br /> <br /> 排他制御の方法についてはこのあと詳しく解説します。
  • さて、シナリオもいよいよ大詰めです。 <br /> <br /> マスターDBへ一番書き込んでいたのは実はユーザーの行動履歴でした。 <br /> そこで、ユーザー行動履歴をDynamoDBに移行させたところ、 <br /> 大幅に書き込み負荷が減って無事ピンチをのりきりました。 <br /> <br /> めでたしめでたし。 <br /> <br /> たいていのソーシャルゲームでは、ユーザーサポートで困らないために <br /> ユーザーが行ったあらゆる行動は全て記録しています。 <br /> <br /> よくアイテムが消失したとか、報酬がもらえなかったとかいうクレームが <br /> 頻繁にお問い合わせで来るのですが、このときユーザーのとった行動が <br /> 証拠として残っていないと真実が何なのかさっぱりわかりません。 <br /> <br /> そこで行動履歴を全て記録するのですが、これのせいでデータベースの <br /> 負荷が火を吹いてエンジニアが白目を剥くという例が跡を絶ちません。 <br /> <br /> せめてそこだけでもDynamoDBへ以降することができれば、 <br /> 安心して眠れる日々を取り戻せるかもしれないので是非検討してみて下さい。 <br />
  • さて、ここからは鬼門の入口となります。 <br /> <br /> DynamoDBをメインデータベースとして使いたければ、 <br /> ここからの話を理解した上で臨む必要があります。 <br />
  • まずはおさらいです。 <br /> <br /> リレーショナルDBでは、レコード同士の整合性を保証していますが、 <br /> その整合性の代償として、複数ノードで処理を分散できないという制約を受けています。 <br />
  • 一方、分散データベースでは、 <br /> レコード同士の整合性を放棄する代わりに、 <br /> 複数ノードで処理を分担できる仕組みを獲得しています。 <br />
  • 整合性の保証を失うこととは、すなわち、 <br /> 「トランザクション」が使えなくなるということです。 <br /> <br /> MySQLでもOracleでもいいのですが、 <br /> 「スタートトランザクション」と「コミット」と「ロールバック」を禁止された状態で <br /> アプリケーションロジックを実装することができるか考えてみて下さい。 <br />
  • トランザクションが使えないということは、 <br /> 複数のレコードを、整合性を保ったまま <br /> 更新することができないことを意味します。
  • トランザクションがないとどうなるかちょっと考えてみましょう。 <br /> <br /> 例えば、100ゴールドを支払って、 <br /> 薬草というアイテムを購入するシーンを想定してみます。 <br /> <br /> ここでは「所持金」と「アイテム所持数」という2つのレコードが存在することになります。 <br />
  • まず、所持金をマイナス100します。 <br />
  • 次に薬草の所持数をプラス1します。 <br />
  • しかし、処理の途中で通信経路に障害が発生して接続が切れてしまいました。 <br />
  • もしここで整合性保証があれば、 <br /> ロールバックしてしまえば万事解決します。 <br /> <br /> 整合性保証があれば、操作のオール・オア・ノッシングが保証されるのです。
  • ではトランザクションが使えないのであれば、 <br /> 一体どうすればいいのでしょうか。 <br /> <br /> 答えは簡単で、アプリケーション側でトランザクションを実装するということです。 <br /> <br /> 簡単とはいいましたが、実際には極めて面倒くさいです。 <br /> 鬼門と言われても仕方ありません。 <br />
  • いままでの構図はこのような形でした。 <br /> <br /> リレーショナル・データベースであるMySQLは、 <br /> トランザクションの機構を内部に備えています。 <br /> <br /> そのため、アプリケーションからは、 <br /> トランザクションの実装を特に意識することなく <br /> 読み書き操作をSQLで指示すればよいだけでした。 <br />
  • しかしDynamoDBを使うとなると、 <br /> 今度はトランザクションの機構をアプリケーション側で持つことになります。 <br /> すなわち、トランザクションの再実装を強いられるというわけです。 <br /> <br /> しかし具体的にはどう実装すれば良いのでしょうか。 <br />
  • DynamoDBでトランザクションを作るには、以下の基本事項を守る必要があります。 <br /> <br /> まず、更新処理の開始から完了までを1つのトランザクションと捉えます。 <br /> <br /> 各レコードの更新には楽観的ロックを用い、さらに全ての更新処理に「冪等性」を持たせます。 <br /> <br /> 処理の途中で失敗が発生したら最初からやりなおし、結果が収束するまで繰り返します。 <br /> <br />
  • さていくつか用語が出てきたので解説します。 <br /> <br /> まずは「楽観的ロック」ですが、 <br /> これは読み込んだレコードを基に <br /> 書き込み処理をする際、 <br /> 他の並行プロセスによって <br /> 割り込んで書き込みがされていないことを <br /> 期待して更新を行う方式です。 <br /> <br /> もし割り込みで書き込みがされていた場合は <br /> 自分の処理を最初からやりなおします。 <br /> <br /> この楽観的ロックを実装するには、 <br /> データベース側に「キャス操作」という機能が必要です。
  • CAS操作とは、 <br /> コンペア・アンド・スワップの略で、 <br /> 更新対象のレコードの状態が <br /> 期待した状態と一致していたときだけ <br /> 更新を実行するという操作です。 <br /> <br /> DynamoDBはもちろん、memcachedでも <br /> CAS操作はサポートされています。
  • CAS操作をSQLで表すとすればこんな感じになります。 <br /> <br /> 当該レコードのステータスという値が <br /> 0のときだけ1に更新するというSQL文です。 <br /> <br /> このクエリを何回実行しても、 <br /> レコードは1回しか更新されないことに注目して下さい。 <br /> <br />
  • 次に「冪等性」ですが、これは先ほどのCAS操作のように、 <br /> 何回行っても結果が同じになるという性質を表した言葉です。 <br /> <br /> 分散DBでデータの整合性を確保するために <br /> とても重要な概念です。 <br />
  • 冪等性のある処理は、基本的にこのようなフローとなります。 <br /> <br /> レコードを読み込んで、処理済みならばスキップします。 <br /> 未処理であればCAS操作を用いて更新し、更新に失敗したら最初に戻ってやり直します。 <br /> <br />
  • 冪等性が確保された処理は、 <br /> いくつ連結しても全体で冪等性を保たれるという性質があります。 <br /> <br /> この性質を利用してアプリケーション実装を進めていきます。 <br />
  • ではさらに詳しい例を解説します。 <br /> <br /> 冒頭でお話した失敗例を、 <br /> 今度はDynamoDBでちゃんと実装してみましょう。 <br /> <br /> まずはレコードを3種類準備します。 <br /> <br /> 所持金とアイテム所持数はそのままですが、 <br /> ここで「更新依頼書」というレコードを新たに用意します。 <br /> <br /> このレコードはユーザーが「薬草を1個買う」という <br /> アクションを起こした時に作成し、 <br /> レコードをどのように更新するかが <br /> 全て指示として書かれたレコードです。
  • まず、依頼書に従い所持金レコードを-100します。 <br /> <br /> このとき、依頼書のIDを所持金レコードに書き込んでおきます。 <br />
  • 次に、薬草の所持数も+1します。 <br /> 同様に、依頼書のIDを書き込んでおきます。 <br />
  • 最後に依頼書の状態を完了済みにします。 <br />
  • 最後に各レコードに書かれた <br /> 自身の依頼書IDをクリーンアップして <br /> 処理は完了となります。 <br />
  • ここまでの処理は、SQSと組み合わせて実装します。 <br /> <br /> SQSには、キューのメッセージが削除されるまでは <br /> 何度でも取り出しが可能という特徴があります。 <br /> <br /> この特徴を利用して、まず依頼書をレコードとして作成し、 <br /> そのレコードのIDを処理依頼としてSQSへキューイングします。 <br /> <br /> これをバックグラウド処理で1つづつ処理しますが、 <br /> 処理結果が収束するまで何度でも実行されるように実装します。 <br /> <br />
  • 全体のフローチャートはこのようになります。 <br /> <br /> ユーザーのアクションをトリガーとして、 <br /> 一番左上の「開始」から処理が始まります。 <br /> <br /> 原則、依頼書を作成してキューを発行したら <br /> いったんそこで、そのプロセスは処理を終えます。 <br /> <br /> あとはキュー処理で結果が収束するまで処理全体を繰り返します。
  • では再びさきほどの例で、 <br /> 途中で書き込みに失敗する場合のことを考えてみましょう。 <br /> <br /> まずはレコードを同じように準備します。 <br />
  • しかし想定外の並行プロセスが、 <br /> 薬草の所持数を上限である99個に <br /> 更新してしまいました。 <br />
  • しかしキュー処理は開始されてしまっているので、 <br /> 所持金の徴収処理をはじめてしまいます。 <br />
  • 所持金の徴収が終わった後に <br /> 薬草の数を更新しようとしたところ、 <br /> 所持上限エラーが発生してしまいました。 <br /> <br />
  • このとき、これ以上正常な処理を続行できない場合は <br /> トランザクションを中止して、 <br /> 全てをロールバックさせます。
  • 各レコードには更新依頼書のIDが書かれているので、 <br /> 差し戻しをすべきレコードか否かが情報として残っています。 <br /> <br /> 所持金レコードは-100したので、+100をして元に戻します。 <br />
  • 薬草の所持数も元に戻す処理を一応しますが、 <br /> 依頼書IDが書かれていないので <br /> 差し戻し処理をスキップすることができます。 <br />
  • こうして無事ロールバック処理が完了しました。 <br /> <br /> ユーザーは自分の操作が反映されていないことに一瞬戸惑うでしょうが、 <br /> 所持金は減っていないのでクレームになることはありません。 <br /> <br /> これでトランザクションをなんとか再実装することができました。 <br />
  • まとめです。 <br /> <br /> 分散DBをメインDBとして使う場合、 <br /> トランザクションの再実装をしなければいけないので大変です。 <br /> それでもやるというのであれば、 <br /> しっかりフレームワークを組んでから挑むことを強く推奨します。 <br />
  • 講演は以上となります。ご清聴ありがとうございました。 <br /> <br /> 以降、質問タイムとなりますのでご質問のあるかたは挙手をお願いします。 <br />

Lv1から始めるWebサービスのインフラ構築 Lv1から始めるWebサービスのインフラ構築 Presentation Transcript

  • Lv1から始める Webサービスのインフラ構築 2014-09-09 AWS Cloud Storage & DB Day 株式会社マイネット 伊藤祐策
  • 自己紹介 名前伊藤祐策 勤務先株式会社マイネット 肩書アーキテクト 事業内容スマートフォン向けゲームの開発・運営 お仕事内容 ・自社ゲームタイトルのサーバーインフラ構築 ・アプリケーション開発 ・主にサーバーサイド設計(特にDB設計!)
  • 自己紹介 大好きなAWSサービスは? 1位.Amazon DynamoDB 2位.Amazon S3 3位.Amazon CloudFront
  • 自己紹介 まあでも青いアイコンのサービスはだい たい大好きです。
  • 今日のお話はこんな人におすすめ Webサービスを作って スタートアップしたい人 ユーザー数1人から100万人までをAWSで!
  • もくじ 第一部 Lv1から始めるWebサービス 第二部 スケーラブルな構成にするには? 第三部 DynamoDBの正しい使い方
  • 第一部 Lv1から始めるWebサービス
  • シナリオ あなたはとあるWeb系会社のエンジニアです。 ある日、社長が突然こんなことを言い出しました。 「我が社もソーシャルゲーム事業に参入するぞ!」 一瞬目眩がしましたが、あなたは覚悟を決めてシス テム設計を開始しました・・・。 ※このシナリオは全てフィクションです
  • シナリオ サービスリリースまでのステップ 1. アプリケーション開発 2. 社内アルファテスト(ユーザー数10人) 3. ベータテスト(同500人~???) 4. 正式オープン(同1万人~???)
  • シナリオ 先輩社員の助言によりAWSを採用することは決定し ましたが、あなたはAWSは全くの未経験でした。 そこでまずはAWSのアカウントを取るところから始 めることにしました。 【最初の目標】 アルファテスト用の環境を構築する
  • Step1 アカウント取得 AWSアカウントを取得する ★ここがポイント 必ず2アカウント用意しよう! ・本番環境用アカウント ・開発環境用アカウント(兼試験環境) テストや訓練に費用を惜しまないこと!
  • Step2 IAM IAMで子アカウントを作成する グループは以下の2種類を作る ・AWSコンソールにアクセスする「人間ユーザー」 → Administratorテンプレートをそのまま使う ・アプリケーションユーザー → 必要最低限のアクセス権限だけを付与する ※IAMを作ったらrootアカウントは封印しましょう
  • Step3 VPC VPCを構築する サブネットとゲートウェイを作成して関連付ける ★ここがポイント ・サブネットは適切に切る(後述) ・"Auto-Assign Pulibc IP"をONにする → EIPを使う数を節約できる
  • Step3 VPC サブネットはこんな分割方法がオススメ 10.1.0.0/17 ← まずは半分をAZ-aに 10.1.128.0/18 ← 残りを半分をAZ-cに 10.1.192.0/19 ← さらもう半分をAZ-a に 領域を使いきってしまうとあとで困る!
  • Step4 セキュリティグループ セキュリティーグループを構築する サーバーの役割種別ごとにセキュリティーグループ を1個作る。 【例】 ・Webサーバー 外部から80番、443番。内部から22番。 ・RDS(MySQL)サーバー 内部から3306番。
  • Step5 EC2 EC2インスタンスを作成する ★ここがポイント ・配置先AZに気をつけて! → リザーブドインスタンスを買う時に困る → たまにインスタンスタイプが枯渇する ※AWSの営業の人に相談しよう ・セットアップが完了したらAMIをとっておこう!
  • Step6 EIP EIPを取得する 外部に公開するインスタンスのENIにアタッチする。 ★ここがポイント ・EIP取得数の制限に注意!(申請で解除可能) ・インスタンスタイプ別にも関連付け可能数の制限 がある
  • Step6 EIP 必要なEIPはいくつ? 1個目一般公開サイト用 2個目運営管理サイト用 3個目メール配信サーバー用 4個目SSHゲートウェイサーバー用 だいたい4個もあれば十分なのです!
  • Step7 Route53 Route53でゾーン設定をする 取得したEIPをホスト名登録する ★ここがポイント ・メール送信するときはSPFの設定を忘れずに! ・さらにEIPに対するメール送信制限解除申請も必 要なので一緒に済ませておこう!
  • システム構成図(Lv1) t2.micro 約2,000 円/月 PHP MySQL
  • シナリオ アプリケーションも完成に近づき、いよいよ一般 ユーザーへサービスを公開することにしました。 しかし先輩社員はこんなことを言いだしました。 「この構成でインスタンスタイプ 上げるだけじゃダメなの?」
  • 問題 この構成のままインスタンスタイプを上 げるだけでは商用環境としてダメな理由 を答えなさい。
  • 解答 データの保全性が確保されてい ないから。
  • Webサービスとは サービス アプリ ケーション= + データ Webサービスは「生き物」です!
  • 保全性について 「アプリケーション」は subversionやgithub等にマス ターがあるので保全性が確保さ れている。
  • 保全性について 一方「データ」はEC2のEBS上に あるのである日突然失われる可 能性がある。 データが消失→ サービス終了!
  • 商用環境の最低ライン 「隕石が直撃しても大丈夫」 データセンターが1つ壊滅して もサービスを復旧できること。
  • システム構成図(商用Lv1) 約10,000円/月 db.m1.small db.m1.small t2.small Multi-AZ 配置 EIP AMI 同期
  • システム構成図(商用Lv2) 約13,000円/月 db.m1.small db.m1.small t2.small ログ出力 Multi-AZ 配置 EIP AMI S3 ELB 同期
  • ちょっと隕石当ててみましょう データセンター 隕石
  • システム構成図(隕石直撃前) db.m1.small db.m1.small t2.small ログ出力 Multi-AZ 配置 EIP AMI S3 ELB 同期
  • システム構成図(AZ壊滅後) db.m1.small db.m1.small t2.small ログ出力 Multi-AZ 配置 EIP AMI S3 ELB 同期
  • 問題 以下のAWSストレージ系サービスうち、 デフォルトでデータの保全性が確保され ているものはどれか? S3 EBS DynamoDB RDS Multi-AZ ElastiCache
  • 解答 以下のAWSストレージ系サービスうち、 デフォルトでデータの保全性が確保され ているものはどれか? S3 EBS DynamoDB RDS Multi-AZ ElastiCache
  • まとめ 「大事なデータ」は保全性が確 保されているストレージサービ スに保存しましょう。 データさえ生き残っていれば サービスは何度でも蘇ります!
  • この式は見覚えありますよね? MTBF MTBF + MTTR A = A .......... 可用性 MTBF ... 平均故障間隔 MTTR ... 平均復旧間隔
  • まずはMTTRを∞にしない保証を作ること ・・・というお話でした。 MTBF MTBF + MTTR A = コレの件 A .......... 可用性 MTBF ... 平均故障間隔 MTTR ... 平均復旧間隔
  • 質問タイム 2分ほど休憩
  • 第二部 スケーラブルな構成にするには?
  • シナリオ 保全性の確保された構成の構築方法はわかったので すが、この「商用Lv2」の構成ではベータテストの 負荷には耐えられそうにありません。しかし、ベー タテストでは何人のユーザーが押し寄せるのか全く 検討もつきません。 【次の目標】 想定以上の負荷が来ても すぐに対応できる環境を構築する
  • 用語おさらい 「スケーラブル」とは? 1. 増大する負荷に容易に対応できる 2. 負荷に合わせて自動的に拡張される
  • 用語おさらい 「スケーラブル」とは? 1. 増大する負荷に容易に対応できる ↑こっちの話をします 2. 負荷に合わせて自動的に拡張される ↑これはややこしいのでまた今度...
  • 用語おさらい スケールアップ ノードの性能を上げること =インスタンスタイプを上げること スケールアウト ノードの数を増やすこと =インスタンスを追加すること
  • 理想パターン ・EC2インスタンスを追加すると全体性 能があがる。 ・RDSのリードレプリカを増やすと全 体性能があがる。 ・DynamoDBの性能予約を買い足すと 全体性能があがる。
  • 将来が不安なパターン ・インスタンスタイプを上げると全体性 能があがる。 ・EBSのIO性能を上げると全体性能が あがる。 → コスト効率が悪くなる → 性能拡張に上限がある
  • つまりこういうこと スケールアウトできる形にする スケールアップで全体性能があがるのは当たり前!
  • スケーラブルな構成(基本形) EC2 EC2 EC2 マスターDB リードレプリカ ELB
  • スケーラブルな構成(基本形) EC2 EC2 EC2 DB書き込み負荷 スケールアップ マスターDB リードレプリカ ELB CPU負荷 DB読み込み負荷 スケールアウト スケールアウト
  • サーバー負荷の傾向と対策 ボトルネックになるのは いつだってデータベース負荷 \もう限界/ マスターDB
  • 各種ストレージサービス解説 Amazon RDS フルマネージドリレーショナルDB Amazon DynamoDB フルマネージドKVS型分散DB Amazon ElastiCache ただのキャッシュサーバ
  • Amazon RDS ここがすごい! ・メンテナンスフリー! 自動的に定期バックアップ AZ間でレプリケーション※Multi-AZ配置時 ・リードレプリカをボタン1発で作成! 読み込み性能を簡単スケーリング
  • Amazon RDS ここは注意! ・一度起動すると止められない 稼働停止=データ削除 EC2のように休止ができない ・スケールアップ時にアクセス不可になる だいたい10分~30分くらい メンテナンスモード必須
  • リレーショナルDB特有の問題 マスターDBへの負荷は どうあがいてもボトルネックになる。 書き込み処理が激しいアプリケーションでは いずれ限界が・・・。 ...しかしそこへ救世主が登場!
  • Amazon DynamoDB ここがすごい! ・メンテナンスフリー! ・すごい耐障害性※3箇所以上に分散保存 ・性能予約課金 ・動的な性能調整が可能 ・負荷による性能劣化を起さない
  • Amazon DynamoDB Amazon DynamoDBは マスターDBへの書き込み負荷が ヤバい時の救世主!?
  • Amazon DynamoDB ここは注意! ・一貫性のあるバックアップを動的にとれない 「一貫性」か「動的」のどちらかを諦める ・性能上限に達すると一時的にアクセス不可になる ちょっと余裕を持って予約する必要がある ・単純な機能しかない 集計とかは無理です
  • Amazon DynamoDB どう使うか? 負荷分散のための補助データベースとして使う NoSQL初心者にはこちらがオススメ。 メインデータベースとして使う 鬼門。死ヲ覚悟セヨ。(※第三部で解説)
  • Amazon ElastiCache ここがすごい! ・とにかく速い ※中身はただのMemcachedです。 ※でも最近Redisも対応しました!
  • Amazon ElastiCache どう使うか? ・大事なデータの格納はNG ・ストレージの読み込み負荷を軽減 させるためのキャッシュとして使う
  • まとめ スケールアウト可能な構成をがん ばって構築しましょう。 しかし、それでもいつかはマスター DBの負荷が限界にくることでしょ う。
  • 質問タイム 2分ほど休憩
  • 第三部 DynamoDBの正しい使い方
  • シナリオ 無事リリースされたサービスは幸運にも大ヒットし、 ユーザー数を急速に伸ばしていきました。しかしマ スターDBの負荷は増大し、インスタンスタイプを db.r3.8xlargeまで上げたのにも関わらず性能の限界が 来てしまいました。そこであなたが決断した最後の手段 とは・・・。 【次の目標】 DynamoDBを使ってピンチを乗り切る
  • Amazon DynamoDBとは何か ・分散データベースである。 ・Key Value Storeである。 ・NoSQLである。 ・スキーマレスである。 ・フルマネージド型サービスである。
  • Amazon DynamoDBの特徴 ・ハッシュキーを基に負荷が分散される。 ・読込性能、書込性能それぞれの予約し た性能量に対して課金される。 ・1レコードは64kBまで格納可能。 ※キー名も容量に含まれるので注意
  • 使い方別難易度 【Easy】 ユーザー単位で独立しているデータだけを DynamoDBに移行して補助的に使う。 【Nightmare】 全てのデータをDynamoDBに載せてメイン データベースとして使う。RDSは補助データ ベースとして使う。
  • テーブル設計の勘所 ★ここがポイント テーブル設計は プライマリーキーの設計が命
  • プライマリキー設計 プライマリキーの仕様 ・プライマリキーの形式は2種類から選べる 1. ハッシュキーのみ 2. ハッシュキー+ レンジキー ・処理の分散はハッシュキーによって行われる ・レンジキーでのみ範囲検索が可能
  • プライマリキー設計 設計例1 ユーザー固有情報 HashKey : ユーザーID RangeKey : なし ・アカウント情報 ・プロフィール情報
  • プライマリキー設計 設計例2 ユーザーの対ユーザー関係 HashKey : ユーザーID RangeKey : 対象ユーザーID ・フォロー ・ブロック
  • プライマリキー設計 設計例3 ユーザーの行動履歴 HashKey : ユーザーID RangeKey : ログID ・ゲーム内アイテムの購入 ・攻撃コマンドの実行 ・etc
  • ログIDの作り方 ・ログの発生時刻から文字列で生成する。 ・乱数も混ぜるといいかも。 ・万が一衝突したらもう一度トライ。 例:"2014090916301234" ※桁数は固定しましょう
  • プライマリキー設計 設計例4 ユーザーの所有オブジェクト HashKey : ユーザーID RangeKey : オブジェクトID ・所有カード ・投稿記事 ※オブジェクトIDはログIDと同じ方法で生成
  • プライマリキー設計 設計例5 ユーザー間関係情報 HashKey : ユーザーID+対象ユーザーID RangeKey : なし ・フレンド ※ユーザーIDは小さい方を先にする
  • シナリオ マスターDBへ一番書き込んでいたのは実は ユーザーの行動履歴でした。そこで、ユー ザー行動履歴をDynamoDBに移行させたと ころ、大幅に書き込み負荷が減って無事ピン チをのりきりました。めでたしめでたし。 おしまい ※面倒くさいのでここでシナリオは打ち切りです
  • 鬼門の入口 ここからはNightmareモードです。
  • リレーショナルDBの限界 レコード同士の整合性を保証する代償として、複数 のノード上で処理を分散できないという制約を受け ている。 整合性の保証
  • 分散データベースの特徴 レコード同士の整合性を解消し、複数のノードで処 理を分担できるようにしたのが分散DB。 整合性の解消
  • 整合性保証を失うということ 要するに 「トランザクション」 が使えなくなる
  • トランザクションが使えないということ 同時に2つ以上のレコードを 整合性をたもったまま 更新することができない
  • トランザクションがないとこうなる 100ゴールドする薬草を買います。 所持金1,000 G 薬草0 個
  • トランザクションがないとこうなる 所持金を-100 します。 所持金900 G 薬草0 個 -100
  • トランザクションがないとこうなる 薬草を+1 します。 所持金900 G 薬草1 個+1
  • トランザクションがないとこうなる ・・・がしかし、通信障害が発生 して更新に失敗してしまいました。 所持金900 G 薬草0 個+1
  • もし整合性保証があれば・・・ ロールバックしてしまえば所持 金も元に戻るのでユーザーの被 害はない。つまり、 ALL or Nothingが保証されている
  • ではどうするのか? アプリケーション側で トランザクションを実装する そりゃ鬼門と言われても仕方がないですね
  • トランザクションの構図(RDBMS) アプリケーション トランザクション テーブルテーブルテーブル MySQL
  • トランザクションの構図(DynamoDB) アプリケーション トランザクション テーブルテーブルテーブル DynamoDB DynamoDB DynamoDB
  • トランザクションの作り方 ・更新処理の開始から完了までを1つのトランザ クションと捉える。 ・各レコードの更新には楽観的ロックを用いる。 ・全ての更新処理に冪等性を持たせる。 ・処理の途中で失敗したら最初からやりなおす。 ・結果が収束するまで何度もやりなおす。
  • 用語解説 楽観的ロック 【意味】読み込んだレコードを更新するとき、 他の並行プロセスによって変更がされてい ないことを期待して更新をする方式。 並列性を高めるためにとても重要な概念
  • 用語解説 CAS操作 【意味】Compare and Swapの略。更新対象 のレコードの状態が期待した状態のときの み更新を実行し、そうでない場合は何もしな い操作。 楽観的ロックに必要な概念
  • CAS操作をSQLで表すと UPDATE user SET status=1,updated_at=NOW() WHERE id=100 AND status=0 ※初期状態はstatus=0とする。
  • 用語解説 冪等性 【意味】ある操作を1回行っても複数回行っ ても結果が同じであること。 整合性を確保するためにとても重要な概念
  • 冪等性のある処理の作り方 処理済? CASで 更新 完了 開始 更新失敗 読込 更新成功 NO YES
  • 冪等性のある処理の作り方 冪等性の確保された処理はいくつ連結して も冪等性を保てる。 function() ✔ function() function() function() ✔
  • 実装例 更新依頼書 ID:123 所持金: -100 薬草: +1 所持金 1,000G 薬草 0個 レコードを準備
  • 実装例 更新依頼書 ID:123 所持金: -100 薬草: +1 所持金 900G -100 ID:123 薬草 0個 所持金を更新
  • 実装例 更新依頼書 ID:123 所持金: -100 薬草: +1 所持金 900G ID:123 薬草 1個 +1 ID:123 薬草の数を更新
  • 実装例 更新依頼書 ID:123 所持金: -100 薬草: +1 状態:完了 所持金 900G ID:123 薬草 1個 ID:123 完了済みにする
  • 実装例 更新依頼書 ID:123 所持金: -100 薬草: +1 状態:完了 所持金 900G 薬草 1個 掃除して完了
  • SQSと組み合わせて使う 1. 依頼書をレコードとして作る 2. SQSへ依頼書IDが書かれたメッセージを発行 3. バックグラウンドでSQSからメッセージを受け取 り、結果が収束するまで何度も実行する。
  • 全体フローチャート 開始 依頼書 作成 キュー 発行 完了 開始 冪等処理 冪等処理 完了 エラー発生 エラー発生
  • ロールバック処理 更新依頼書 ID:123 所持金: -100 薬草: +1 所持金 1,000G 薬草 0個 レコードを準備
  • 別の並行処理が邪魔をする 所持金 1,000G ロールバック処理 更新依頼書 ID:123 所持金: -100 薬草: +1 薬草 99個 +99
  • ロールバック処理 更新依頼書 ID:123 所持金: -100 薬草: +1 所持金 900G -100 ID:123 薬草 99個 所持金を更新
  • ロールバック処理 更新依頼書 ID:123 所持金: -100 薬草: +1 所持金 900G ID:123 薬草 99個 +1 上限エラー 薬草の数を更新
  • ロールバック処理 失敗済みにする 更新依頼書 ID:123 所持金: -100 薬草: +1 状態:失敗 所持金 900G ID:123 薬草 99個
  • ロールバック処理 更新依頼書 ID:123 所持金: -100 薬草: +1 状態:失敗 所持金 1,000G +100 薬草 99個 所持金を戻す
  • ロールバック処理 薬草の数も一応処理 更新依頼書 ID:123 所持金: -100 薬草: +1 状態:失敗 所持金 1,000G 薬草 99個
  • ロールバック処理 完了(状態収束) 更新依頼書 ID:123 所持金: -100 薬草: +1 状態:失敗 所持金 1,000G 薬草 99個
  • まとめ 分散DBをメインDBとして使う場合、 トランザクションの再実装をしなけ ればいけないので大変。 しっかりフレームワークを組んでか ら挑むことを強く推奨。
  • 質問タイム お疲れ様でした