ちょっと話題の記事

AWS re:Invent2013参加レポート #13 AWS Storage and Database Architecture Best Practices

2013.11.15

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

AWSのエンタープライズソリューションアーキテクトである、Siva Raghupathyさんによる「AWS Storage and Database Architecture Best Practices」に参加してきました。

各ストレージ、データベースの向き不向きとベストプラクティスを網羅的に紹介する内容でした。
AWSはデータベースだけでも沢山のサービスがあるので、どのサービスを利用するのが一番いいのか迷うことがよくあります。
以下は発表内容の直訳ですが、それぞれのサービスの特性を押さえておくことで、より確かな選定をするための一助になればと思います。

英語が分からなくて、訳せていない部分があります。
自信が無いところは元の英語を併記しています。
CloudSearchなどの使ったことが無いサービスはほとんど訳せていません。すみません...
理解が進んだら訳していきます。

RDS

向く場面

  • トランザクション処理が多いもの
  • 複雑なクエリが必要なもの
  • 中から高程度の読み込み/書き込み
    • 3万IOPS(15000読み込み/秒 + 15000書き込み/秒)くらいまで
  • データ容量は数百GBから数TBまで
  • 1ノードで処理できるくらいの負荷
  • 高い耐久性が必要

向かない場面

  • 大量の読み込み/書き込み
    • 15万書き込み/秒とか
  • シャーディングが必要なくらいのデータサイズやスループットが求められる場合
    • 数十から数百TBのデータサイズ
  • クエリがシンプルなPUT/GETばかりでNoSQLで対応できる場合
  • 複雑な分析

ベストプラクティス

  • 適切なインスタンスクラスを選択する
  • EBS-optimizedインスタンスを利用する
    • db.m1.large, db.m1.xlarge, db.m2.2xlarge, db.m2.4xlarge, db.cr1.8xlarge
  • Provisioned IOPSを利用する
  • 冗長化のためMulti-AZを利用する
  • Read Replicaを利用する
    • 読み込みスケールのため
    • スキーマ変更のため
    • 障害に備えて

DynamoDB

向く場面

  • 高速かつ予測可能なパフォーマンスが必要
  • シームレスで巨大な規模が必要
  • 自動シャーディング
  • 安定した短いレイテンシ
  • 容量やスループットの上限が決まってない
  • 非常に高い耐久性が求められる
  • Key-Value型、もしくは単純なクエリで十分

向かない場面

  • 複数アイテムもしくは複数テーブルにまたがったトランザクションが必要
  • 複雑なクエリやJOINが必要
  • 時系列データのリアルタイム分析が必要
  • アクセスの少ないデータの保存

ベストプラクティス

  • アイテムのサイズは小さく
  • メタデータはDynamoDBに、でかい本体データはS3に
  • Use a table with a hash key for extremely high scale
  • 時系列データを保存する場合は、月、週、日等ごとにテーブルを作る
  • Use hash-range key to model
    • 1 N relationships
    • Multi-tenancy
  • 特定のハッシュキーにアクセスが集中しないようにする

ElastiCache(Memcached)

向く場面

  • Key-Value型データの一時的な保存
  • 高速な読み込み/書き込みが必要
  • 発行頻度の高いSQLやNoSQLの結果を保存
  • 一時的で更新頻度の高いデータを保存
    • 増減の激しいゲームのスコア
    • ウェブアプリケーションのセッション
  • データの重複を許容できる

向かない場面

  • あまり利用されないデータの保存
  • 永続性が必要

ベストプラクティス

  • Auto Discoveryを利用する
  • Share Memcached client objects in application
  • TTLを利用する
  • コネクションによるメモリのオーバーヘッドを考慮する
  • CloudWatchのアラームとSNSのアラートを利用する
    • コネクション数
    • Swap利用量
    • 空きメモリ量

ElastiCache(Redis)

向く場面

  • より複雑なKey-Value型データが必要
    • 文字列型、リスト型、セット型、ソート済みセット型、ハッシュ型
  • キャッシュ用途
  • リーダーボード
  • 高速並び替え
  • アトミックカウンター
  • キューイングシステム
  • アクティビティストリーム

向かない場面

  • シャーディングやスケールアウトが必要
  • 「強い」永続性が必要
  • データがメモリに乗り切らない場合
  • 例外発生時にもトランザクションロールバックが必要

ベストプラクティス

  • TTLを利用する
  • 適切なインスタンスタイプを選ぶ
    • 高CPUかつネットワークパフォーマンスがいいインスタンスほど高いスループットを出せる(m2.4xlarge, m2.2xlarge)
  • Read Replicaを利用する
    • 読み込みスループット向上のため
    • AOFだけでは防げない障害があるから
    • Read Replicaをプライマリに昇格できるから
  • オンプレミスからの移行時はRDBスナップショットファイルを利用する
  • 主要な設定
    • パラメータ設定の「appendfsync」は「always」にしない。パフォーマンスの悪化がきわめて激しいので。
    • 「appendfsync」は「everysec」にする。耐久性とパフォーマンスのバランスが一番良い
    • Publish/Subscribe構成のときは「client-output-buffer-limit-pub-sub-hard-limit」と「client-output-buffer-limit-pub-sub-soft-limit」をセットする

CloudSearch

向く場面

  • 検索に関する専門知識が無い(No search expertise)
  • 全文検索(Full-text search)
  • ランキング(Ranking)
  • Relevance
  • データは構造化されている場合も構造化されていない場合もどちらでもOK(Structured and un-structured data)
  • ファセット(Faceting)
    • 例えば、0~10ドルは4件ヒット、10ドル以上は3件ヒットみたいな検索結果が欲しい場合

向かない場面

  • データベースの代わりにはならない(Not as replacement for a database)
    • Not as a system of record
    • Transient data
    • Non-atmic updates

ベストプラクティス

  • Batch documents for updating
  • CloudSerchは検索用に利用し、結果表示用には他のデータストアを利用する。つまり、かえってきた値は表示には利用しない。(Use CloudSearch for searching and another store for retrieving full records for the UI. i.e. don't use return fields)
  • documentに人気度といった他のデータを含める(Include other data like popularity scores in documents)
  • 検索対象にしたくないような一般的な単語を取り除くため「stopwords」を設定する。(Use stop words to remove common items.)
  • Use fielded queries to reduce match sets.
  • Query latency is proportional to query specificity.

Redshift

向く場面

  • 分析、レポーティング
  • Complex DW queries that summarize historical data.
  • Batched large updates e.g. daily sales totals.
  • 同時に発行されるクエリ数が数十個
  • データ量が数百GBからペタバイト
  • Compression
  • Column based
  • 非常に高い耐久性が求められる

向かない場面

  • オンライントランザクション処理が多い
    • 同時ユーザ数が数千
    • 一意な列の更新を大量に行う(Large number of singleton updates)

ベストプラクティス

  • 大量のデータを更新するときはコピーコマンド(COPY from S3/DynamoDB)を利用する。
    • データを複数のファイルに分割すること
    • GZIP圧縮やLZOP圧縮を利用すること
    • マニフェストファイルを利用すること
  • ソートキーには適切なものを選択する。
    • WHERE句で指定するもの。範囲指定も可。(Renge or equality on WHERE clause)
  • 分散キーには適切なものを選択する。
    • JOIN用のカラム、外部キー、largest dimension、GROUP BYカラム
    • 正規化されていないカラムは避ける

※Redshiftのテーブル設計についてはこちらのエントリも参考になるかと。
Amazon Redshift DB開発者ガイド – テーブル設計のベストプラクティス

Elastic MapReduce

向く場面

  • バッチ処理、分析
    • 応答に数分から数時間かかっても良い場合
  • データは構造化されている場合も構造化されていない場合もどちらでもOK(Structured and un-structured data)
  • 全データに対する並行したスキャンを安定した性能で行いたいとき
  • Hive QLや他の言語を利用したいとき
  • ギガバイトからペタバイトまでのデータ量
  • Replicated data store(HDFS) for ad-hoc and real-time queries(HBase).

向かない場面

  • リアルタイム分析
    • 数秒での応答が必要な場合
  • 同時ユーザ数が数千

ベストプラクティス

  • 運用も含む全コストを考慮して、一時クラスタを使うか、永続クラスタを使うか選択する。
    • 耐久性の高いS3と、内部ストレージをうまく組み合わせる
    • クラスタ内のインスタンスは各ジョブに適切なものを選ぶ。あらゆるジョブに適しているインスタンスサイズは無い。
    • コストを効率化するために、インスタンスサイズの調整やスポットインスタンスの数の調整を行う(Leverage resizing and spot to add and remove capacity cost-effectively.)
  • Hadoopのコードをチューニングするよりはクラスタのインスタンスをチューニングする方が楽。

S3

向く場面

  • 巨大なオブジェクトの保存
  • Key-Valueストアとして。(GET/PUT/LISTが使える)
  • 無制限のストレージとして。
  • オブジェクトのバージョニングがしたいとき。
  • 非常に高い耐久性が欲しいとき。
    • 99.999999999%
  • 非常に高いスループットが欲しい場合。ただし、クライアントが並列でないと性能が落ちる。
  • 永続的なデータ保存。
    • バックアップ
    • EMRのソース/結果
    • メタデータをSQL/NoSQLデータベースに入れて、本体を保存

向かない場面

  • 複雑な問い合わせが使いたい場合
  • ミリ秒レベルの非常に低いレイテンシが求められる場合
  • 検索
  • 書き込み(更新)後の読み込み一貫性が必要な場合
  • トランザクションが必要な場合

ベストプラクティス

  • キーのプレフィックスにランダムなハッシュ値をつける
  • アクセスパターンがランダムになるようにする
  • GETやPUTに高いスループットが必要な場合は、CloudFrontを利用する
  • 高い耐久性とスループットというS3の特徴を活かし、バックアップや一般的なデータ保存場所として利用する(Leverage the high durability, high throughput design of S3 for backup and as a common storage sink)
    • 耐久性の高いデータ保存場所として、他のデータ処理サービス間で利用する
    • Supports de-coupling and asynchronous delivery
    • コピーデータの保存先としては耐久性が低い代わりにコストも低い低冗長下ストレージ(RRS)を検討する
  • 書き込みを高速化するために、スレッドを並列化しマルチパートアップロードを行う
  • 読み込みを高速化するために、スレッドを並列化し範囲リクエスト(Rangeヘッダを使ったGET)を行う

Data Pipeline

向く場面

  • 自動的なデータの移動と変換
  • 依存性の管理
    • データ
    • 制御
  • 処理のスケジュールの管理
  • EMRの一時クラスタと組み合わせて
  • データの移動に決まったパターンがあるとき
    • 30分ごと、毎時、毎日
  • DynamoDBのバックアップに
    • リージョンまたぎ

向かない場面

  • データ移動のスケジュールが15分よりも短い間隔のとき
  • 実行時間が1分以下である必要があるとき
  • 時間ベースではなく、イベントベースのスケジュールが必要な場合

ベストプラクティス

  • 時間ベースのデータ移動よりも、依存関係を持つデータ移動に利用する
  • アクティビティが冪等であるようにする
  • シェルコマンドスアクティビティを利用し、自作ツールと組み合わせる
  • S3を利用する(Use S3 for staging)

Glacier

向く場面

  • 年単位のデータの保存
  • データへのアクセス頻度が低い
  • セキュリティが重要
  • データ保存のコストを下げたい
  • データを簡単に取り出したい
  • PB級のデータ量
  • 非常に高い耐久性が必要
    • 99.999999999%
  • 無制限のストレージとして。

向かない場面

  • アクセスが頻繁
  • 低いレイテンシが求められる

ベストプラクティス

  • ファイルを集約してリクエスト数とストレージコストを下げる
    • Glacierに送る前にファイルを集約してより大きなファイルにする
    • ファイルと一緒にチェックサムも保存しておく
    • 集約されたファイルから目的のファイルにアクセスできるような集約フォーマットを使う
  • マルチパートアップロードを使いスピードと信頼性を向上させる
  • 範囲リクエストを使いコストを下げる
  • インデックスを耐久性の高いストレージに保存する

EC2 + EBS/Ephemeral disk

向く場面

  • AWSで提供していないデータ保存技術を利用する場合
  • 細かいパフォーマンスチューニングが必要な場合
  • データに直接アクセスする必要がある場合

向かない場面

  • AWSのマネージドサービスで間に合う場合
  • 運用経験が浅い場合

ベストプラクティス

  • 適正なインスタンスタイプを選ぶ
    • EBSのIOPSを十分に活かすためにネットワークパフォーマンスが高いインスタンス
    • EBS-Optimized EC2インスタンス
  • 安定したIOPSが必要なデータベース用の場合、プロビジョンドIOPSボリュームを利用する
  • 低から中程度のIOPSと時々急激なIOが発生するような処理の場合は、標準のボリュームを利用する
  • より高いIOPSが必要な場合は、複数のEBSをストライピングする
    • より高いIOにはRAID0
    • 耐久性が必要な場合はRAID10
  • EBSスナップショットを活用する
    • ファイルシステムの静止点をもうけ、スナップショットを撮る
  • IOPSとキューの深さとレイテンシは互いに依存している

感想

CloudSearchやData Pipelineはあまり関心が無かったのですが、他のサービスと比較することで何となくイメージが出来て、使ってみたくなりました。

また、SimpleDBが無いのが気になりました。

参考サイト

【AWS】はじめてのCloudSearch/ElasticMapReduceでCSV形式に変換したログをCloudSearchで検索する
AWS Data Pipelineリリース!
AWS Data Pipelineによるタスクスケジューラの利用
Amazon Redshift DB開発者ガイド – テーブル設計のベストプラクティス