[レポート][DEV-04:SERVICE] 日本最大の即レスサービス「アンサー」を支える Amazon DynamoDB

2015.06.04

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

AWS Summit Tokyo 2015 Dev–04: Service の日本最大の即レスサービス「アンサー」を支える Amazon DynamoDB」のレポートをお届けます。

スピーカーは株式会社nanapiの秋田 真宏さんです。

セッションの概要

これからDynamoDBを使ってみようという人たちに向けて、即レスQ&Aアプリ「アンサー」での運用経験から得られたDynamoDBの使いこなしノウハウを伝える、という内容でした。

セッションの内容

DynamoDB導入の経緯

バックエンドのデータベースについて、当初はRDS上のMySQLをマスター/スレーブ構成で使用されていたそうですが、レコード数の増加に伴いALTER実行時のスレーブ遅延が問題となってきたとのこと。

  • 1000万レコード級
  • ALTER時は一時的にマスターをスケールアップさせることでスレーブ遅延を回避していたがマスターのスケールアップでの対応の限界が見えた

この問題の対策としてDynamoDBを導入されたそうです。

  • 設定だけでスケールして限界がない
  • フルマネージドで管理不要
  • レスポンスは十分速そう、容量課金も安そう
  • KVS(NoSQL)だけどインデックスが作れる

DynamoDBを実際に使ってみて

導入の経緯にもあるように、DynamoDB導入時はRDBの代替ないしスーパーセット的な期待を持たれていたようですが、実際に運用してみた結果、

  • DynamoDBはあくまでもKVS
  • RDBの代替として使うべきではない
  • スケールさせるには前提を理解しておく必要がある

という知見を得たとのことでした。

スループットのコストについて

DynamoDBの主なコストボトルネック=スループット量であるため、スループット量の増大に注意する必要があるとのこと。

スループットが増えるパターン

  • RDBのように大量のレコードを読み込もうとするとスループットが大量の消費されてしまう
  • KVS的な使い方に徹することがスループット量を節約するコツ

KVS的な使い方のコツとしては、

  • 大量のItemを読み書きしない
  • 1Itemのサイズを小さく(DynamoDBでは最大400KBだが、256KBでも大きすぎる部類)

といったポイントが挙げられていました。

スループットが節約できそうでできない例

また、「Query」での複数Itemの読み込みにに関して、一見するとスループットが節約できそうだが実際は節約できない例として、“LIMIT”と“フィルタ”が挙げられていました。

  • “LIMIT”をつけて複数Itemを取得
    • パーテイションから複数Itemを読み込んだ後に結果セットの数を制限してくれる(のでスループットは減らない)
    • 「先頭n件/末尾n件を取得」はそもそもKVS的ではない = DynamoDBに向いていない
    • 時系列データをスループット消費の観点で効率的に読み込むには前提が必要(Itemは24時間以内に必ずexpireする、など)
  • “フィルタ”を指定
    • パーティションからItemを読み込んだ後に結果セットのデータを絞り込む(のでスループットは減らない)
    • “フィルタ”は結果セットが1MBを超えるようなリクエストで取得後に絞込が必要な場合に使う(リクエスト回数が削減できる)

「結果整合性での読み込み」

スループットの節約方法として、「結果整合性での読み込み」も挙げられていました。

  • 「結果整合性」で消費されるスループットは「強い整合性」の読み込みの半分
    • 強い整合性 : マスターDBからの読み込みに相当(ラグなしで読み込める)
    • 結果整合性 : スレーブDBからの読み込みに相当(レプリカラグの発生が前提)
  • 遅延が許容できる箇所では「結果整合性」での読み込みを使うとスループットが節約できる

スループットが足りない時の挙動

一度のリクエストで消費できるスループットは限られているため(「プロビジョニングされたスループット」と「 現在消費されているスループット」との差)、スループットが足りなくなった時の動作についても注意が必要とのことでした。

  • GetItem(1件の取得) : 回復まで待たされる or タイムアウト
  • Query(複数件の取得) : 残量分のItemを読み込んだ時点で結果セットを返す(1リクエストで全Itemを習得できないことがある)

故に、複数件のItemを確実に取得するにはアプリケーション側での再帰的な処理の組み込みが必須とのことでした。

スケーラビリティの確保

スケーラビリティを確保する方法として「ハッシュアクセスを分散させる」ことと「パーティションの分割を想定する」ことが挙げられていました。

ハッシュアクセスを分散させる

  • 書き込み性能 : 分散したHASHへの書き込み > 同一HASHへの連続した書き込み
  • 激しい書き込み用途では、HASHを分割して保存する等の工夫が必要

パーティションの分割を想定する

  • 容量もしくはプロビジョニング量によってデータが複数のパーティションに分割される
  • プロビジョニングされたスループットはパーティション毎に均一に振り分けられる

インデックス

インデックスの運用は難しく、とりあえず作っておけばOK、というものではないとのことでした。

  • LSIもGSIも実態は別のテーブル
  • インデックスにも十分なスループットが必要(インデックス側のスループット不足によりテーブルへの書き込み性能も低下する)
  • HASH集中による性能低下が起きないか注意が必要

どうしてもインデックスが必要という場合は、RDBとの併用も選択肢として考えるべき、とも。

インポート

データのインポートのベストプラクティスについて。HASH分散超大事、とのことでした。

  • インポートはDataPipeLineとして動作
  • フォーマットはシンプル。マニュアル通りに作れる(マニュアルはDynamoDBではなくData Pipelineのものを参照)
  • HASHを分散させないとスループットを使い切れず速度がでない

どうしてもHASHが集中しているデータをインポートしなければならない場合は、、、ひたすら待つしかないと思う、とも。

バックアップ

マスターデータのストア先としてDynamoDBを使う場合はバックアップの検討が必要だが、現状大容量テーブルに対する簡単なバックアップソリューションは無いとのこと。

  • 全データ読み込みは可能だが、現実的ではない。(時間とスループット消費の観点で)
  • 障害に対して : 3つのAZに複製されるのでItemが消えることはないはず
  • 誤操作に対して : IAMで権限をコントロールすることでリスクを低減

DynamoDBのユースケース

アンサーでは、以下の用途でDynamoDBを使っているそうです。

  • 投稿内容のレプリカ
  • スポット参加状態のレプリカ
  • ユーザログインセッション
  • シーケンス生成器

以下のようなデータについてはDynamoDB向きではないとのこと。

  • インデックスの必要性が高い
  • データ全体の操作が必要

おすすめの学習方法

よくある質問の通読がおすすめとのこと。サポートに問合せた内容のほとんどがここに載っていたそうです。

DynamoDBを今後も使うか

簡単にスケールするインフラは魅力的であり、KVS的な要件であれば積極的に使っていきたいとのことでした。 また、Lambdaとの連携にも魅力を感じているとも。

感想

アンサーはリリースから約1年半、2014年の12月時点で累計1億コメントが投稿されているそうで、実際に大規模サービスを運用した得られた知見がふんだんに盛り込まれた、すばらしく実用的なセッションだったと思います。

発表資料を含んだ秋田さんご本人のブログエントリも公開されておりますので、DynamoDBの使用中の方、使用を検討している方は一読されることを強くおすすめします!