Amazon DynamoDB - Developer Guide · PDF fileAmazon DynamoDB Developer Guide
日本最大の即レスサービス「アンサー」を支える Amazon DynamoDB
-
Upload
masahiro-akita -
Category
Technology
-
view
8.863 -
download
7
Transcript of 日本最大の即レスサービス「アンサー」を支える Amazon DynamoDB
日本最大の即レスサービス 「アンサー」を支える Amazon DynamoDB
2015/6/3at AWS Summit Tokyo 2015 デベロッパーカンファレンス
nanapi Inc. Masahiro Akita
自己紹介
• 2011年4月nanapi入社 (5年目) • 主にサーバーサイドをやってます • akiyan.com という個人ブログを書いてます
秋田 真宏 / あきやん株式会社 nanapi エンジニア (社員)
2
アンサーとは
•即レスコミュニケーションサービス • iOS / Android ネイティブアプリ展開 •リリースから約1年半 • 2014年12月時点で累計1億コメント
3
こんな感じ
4
DynamoDBとは
•フルマネージドで管理不要なデータストア •マルチAZに分散保存で高可用性 •設定値だけで自動スケール • 合計容量の限界なし •スループット課金 • スキーマレス • インデックスが作れる
5
デベロッパーにとってのDynamoDBとは
なんかすごい夢のデータストアサービス?
6
DynamoDBを運用する前のイメージ
•お金をかければかけたぶんだけスケールするらしくてすごい
• KVS(NoSQL)だけどインデックスも張れるからRDBの代わりにもなりそう
• インデックスを張らなくても強引にRDB的なこともできそう
7
DynamoDBを運用した後のイメージ
• DynamoDBはKVSである • RDBの代わりとして使うべきではない • 前提を理解していればスケールする • 前提を理解していなければスケールしない
8
今回の発表の立ち位置
アンサーにおけるDynamoDBの
運用後に得られた経験から
運用前の自分に向けて伝えたいこと
9
話す内容
• DynamoDBの基礎と導入の経緯 •スループットにまつわるあれこれ • スケーラビリティの確保 • インデックスとは何か • インポートのベストプラクティス • バックアップは難しい • おすすめの学習方法
10
DynamoDBの基礎知識
11
DynamoDBの基礎の基礎
•テーブルの種類 • スループット •主なAPI
12
テーブルの種類
•テーブルは2種類ある • HASHテーブル • HASH + RANGEテーブル
13
HASHテーブル
•一意なキーでItemが決定する、いわゆるKVS的なテーブル
• できることがKVS以上でも以下でもないので、安心して使える
14
HASH + RANGE テーブル
• HASHキーとRANGEキーの2種類の値の組み合わせでItemが決定する
• HASHとRANGEの組み合わせはユニークである必要がある
• HASHキーのみでも取り出すことができる • HASHキーに追加でRANGEキーを対象に範囲など条件指定して取得が可能
• 取得時にRANGEキーで昇順降順のソートが可能
15
スループットとは
• DynamoDBが内部のパーティション(ストレージ)からItemを読み書きした容量
• ネットワークの転送量ではない • 必要なスループットは予め設定し、設定値によって1時間単位で課金される
• 設定値は「キャパシティーユニット (CU)」と呼ぶ
•設定値の変更はオンラインで実行可能16
主なAPI
• getItem (1件取得) • query (1HASHに対してRANGEキーで検索複数取得)
• putItem (1件更新) • updateItem (特定のカラムを更新、アトミックインクリメント等)
17
DynamoDBの導入経緯
18
RDBの限界
• RDS上のMySQLでマスタースレーブ構成 • 1000万レコード級のALTERは辛い • ALTERすると派手にスレーブ遅延する • ALTERするときは一時的にマスターDBをスケールアップしてアクセスを集中させていた
•マスターDBのスケールアップの限界が見えてきた
19
少ない手間でスケールする点に注目
• DynamoDBは設定だけでスケールして限界が無いのが素敵すぎるしフルマネージドで管理不要
•レスポンスは十分速そう •容量課金は安そう •スループット課金はどれくらいになるかわからないが、他のメリットが大きいので許容されるリスクとした
20
実際の用途
•投稿内容のレプリカ •スポット参加状態のレプリカ •ユーザーログインセッション •シーケンス生成器
21
スループットのコスト
22
コストはキャパシティーユニットの設定値で決まる
•キャパシティーユニットは読み書き別々に設定する
• 書き込みユニットは1WCUあたり1KBの性能で、10ユニットで $0.00742 (Tokyo) / 時間
• 読み込みユニットは1RCUあたり4KBの性能で、50ユニットで $0.00742(Tokyo) / 時間
• 性能は「秒間あたり」の性能となる 23
スループット課金額例
•毎秒 100KB の読み込みスループットを確保するには 100KB / 4KB = 25 RCU が必要
• $ 0.00742 * 25(RCU) * 24(hour) * 30(days) = $ 133 / Month
24
Itemサイズ平均 1KB
1リクエストあたり 10Item読み込み
秒間アクセス 10アクセス
スループット消費量の確認方法
•現在消費しているスループットはマネジメントコンソールから5分単位で確認できる
• リクエストごとに消費したスループットは、APIの返り値で確認できる(ただしおおよそで、多めに盛られ気味)
25
スループット消費グラフ
26
消費スループットのAPIの返り値
# aws dynamodb query … ̶return-consumed-capacity TOTAL | jq .ConsumedCapacity { "CapacityUnits": 1.5, "TableName": “expample_table” }
27
DynamoDBの主なコストはスループット
• DynamoDBのコストボトルネックはスループット量になる
• 容量課金は安い (そもそも大きなデータを格納できないし、しないし、データが大きいとスループットのほうが先に高額になる)
• 転送量課金も安い(同一リージョン内なら無料)
28
スループット増大に注意
29
RDBのように使うとスループットが増えがち
• RDBのように多めのレコードを富豪的に読み込もうとすると、スループット破産する
• どうしてもRDB的に使うなら、テーブルをカラムごとの利用頻度によって分割したり、アイテムごとにキャッシュしてスループット消費を抑えよう
30
スループット破産例
•例えば256KBのItemを50件読み込む要件があると、少なくとも一度に「1,600 RCU」を消費する
• 1600 RCU をプロビジョニングすると月額 $170 (Tokyo) が必要
• この要件で毎秒あたり10ユーザーが同時アクセスして遅延なく応答するには 16,000 RCU が必要になり月額 $1,900 の課金になる。
31
KVSのように使おう
• RDBのように使わずKVSのように使っていれば現実的なスループットに収まるはず
• スループット消費を抑えようとすると、結果的にKVS的な利用に限定される
• スループット課金額からして、DynamoDBはそもそもKVS的な利用を想定していると思う
32
KVS的な使い方とは
• KVSでは毎回大量のItemを読み書きしたりはしない
• KVSでは1Itemをやたら大きくしたりはしない
• 256KBはDynamoDBとしては大きすぎる部類。最大でも400KB
33
節約できそうでできない スループット
34
DynamoDBは一度に複数Itemの取得が可能
•「query」で、RANGEテーブルやインデックスから一度に複数Itemを読み込むことができる
• HASH のみか、HASH と RANGE の条件指定での読み込みが基本
35
LIMITをつけてもスループットは節約できない
•「LIMIT」はquery APIのパラメータ •パーティションから複数のItemを読み込んだ後に、結果セットの数を制限してくれる
• LIMITの指定でスループットは減ることはない
• HASH + RANGE テーブルで、RANGEの指定無しでもLIMITをつければいかにもスループットが減りそうだが、減らない
36
HASH + RANGE テーブルでスループット消費を抑えるには
•先頭n件を取得する場合、スループットを節約しようとするなら、適当なRANGEキーを範囲指定しなければならない
• 適当なRANGEキーの決定は通常は無理がある場合がほとんど
• スループット消費低減のためにインデックスを用意すると、追加の書き込みスループットが必要になるので悩ましい
• あちらを立てればこちらが立たず状態 37
そもそもn件取得はKVS的でない
•「先頭/末尾のn件を取得」という要件が、そもそもKVS的でない (DynamoDBに向いていない)
• 時系列データをスループット消費の観点で効率的に読み込むには前提と工夫が必要
• 例えば「Itemは24時間以内に必ずexpireする」などの前提があれば、RANGE値を24時間のexpireに限定してクエリに指定できる
38
フィルタを指定してもスループットは節約できない
•「フィルタ」はquery APIのパラメータ •パーティションからItemを読み込んだ後に、結果セットのデータを絞り込んでくれる機能
•絞り込み条件にはあらゆるキーを指定出来る
• 読み込んだあとの絞り込みなので、スループットは絞り込み前の結果で消費される
39
フィルタの使いどころ
• query は結果セットの容量に1MBの制限がある
• 結果セットが1MBを超えるようなリクエストで、取得後に絞り込みが必要な場合の、リクエスト回数の削減用
• 転送量の削減にもなる • アプリケーションサーバー側のCPU節約としてもよい
40
LIMITとフィルタを組み合わせると、LIMITが先に適用される
• LIMITとフィルタを組み合わせると、「LIMITで制限してからフィルタで絞り込む」という挙動になり、LIMITの数より少ない結果セットになる
• RDB脳からすると直感的でない挙動
41
スループットの主な節約手段
•キャッシュの活用 •「結果整合性」での読み込み
42
「結果整合性」とは
• DynamoDBからの読み込みには「強い整合性」と「結果整合性」の2種類があり、場合によって選択可能
•「結果整合性」は「強い整合性」の読み込みに比べて、 半分のスループットで読み込める
43
整合性をRDBに例えるなら
•「強い整合性」はマスターDBからの読み込み相当。完了済みの書き込みAPIリクエストの結果が確実に取得できる
• 「結果整合性」はスレーブDBからの読み込み相当。書き込み同期遅延(レプリカラグ)の発生が前提
• 遅延が許される箇所であれば積極的に「結果整合性」での読み込みを行う
44
スループットが足りない時は
45
いつスループットが足りなくなるのか
•一度のリクエストで消費できるスループットは限られている
• プロビジョニングされたスループットと、現在消費されているスループットの差で、1度に消費できるスループット量が決まる
46
スループットが足りないときの挙動
• getItem(1件の取得)であれば、回復まで待たされるかタイムアウトする
• query(複数件の取得)の場合、残量ぶんのItemを読み込んだらその次点で結果セットを返す
•ゆえに、複数取得では1リクエストで全てのItemを取得できないことがある
47
複数取得では再帰実行が必須
•複数件を確実に取得するには、再帰的な処理を仕込む必要がある
• APIの返り値に追加読み込み用の項目があるので、それを元に再帰実行するかを判断できる
• 結果セットの容量に1MBの制限があり、こちらも同様の考慮が必要になる
48
スループットのオートスケーリングは無い
• DynamoDBの機能としてのオートスケーリングは無く、サードパーティ製のスケーラがあり、公式から推奨されている
• KVS的な利用に限定していれば、そこそこの規模まで十分安く運用できるのでオートスケールは最初は気にしなくていい
• スケールアップ回数は無限だが、スケールダウンは1日4回まで
49
隠れスループットの存在
•設定値とは別に隠れたスループットが用意されており、ユーザーも使用可能
• ただしこれはAWS側がメンテナンスのために用意したスループットなので、いつでも使えることを期待してはいけない
• とはいえ開発環境用の小さなスループット設定のテーブルに対してバッチ実行をするときなどに、スループットがバーストしているように振る舞うのでそこそこ便利
50
スケーラビリティの確保
51
スケールに必要な前提とは
•ハッシュアクセスを分散させる • パーティションの分割を想定する
52
ハッシュアクセスを分散させる
•同一HASHへの連続した書き込みは、分散したHASH書き込みに比べて性能が低い
• PVや投票のような激しい書き込み用途に使う際は、HASHを分割して保存するなど工夫が必要
• RANGEが異なってもHASHが同じ場合は、同一HASHとみなされる
53
パーティションの分割を想定する
•容量もしくはプロビジョニング量によってデータが複数のパーティションに分割され、プロビジョニングされたスループットはパーティションごとに均一に振り分けられる
• パーティション分割は容量が10GB単位、スループットは RCUを3000で割った数とWCUを1000で割った数の合算値で決まる
•パーティションが複数で、アクセスされるハッシュが偏ると、スループットを使い切れない場合がある
54
容量増加で性能低下する場合がある
• 10GBと3,000 RCUはそうそう到達しないが、それでも想定する必要はある。特に容量
• アンサーではコメントデータをDynamoDBに同期しているが、20GBを超えており3パーティション化されている
• アンサーのコメントはHASHがスポットID、RANGEがコメントIDになっている
• スポットIDへのアクセスは十分に分散しているので、スループットを使いきれている
55
インデックスの特性
56
インデックスの実態は「自動で作られる別のテーブル」
•ローカルセカンダリインデックス(LSI)も、グローバルセカンダリインデックス(GSI)も、実態としては「別のテーブル」
• インデックスに対して読み込みにおいてできることは HASH+RANGE テーブルにできること以下になる
• 多少の例外はあるが、やはり基本はテーブルと同じ
57
LSIの特性
• LSIの実態は「テーブルと同じHASHで別のRANGEを持った複製テーブル」
• 例えばテーブルの定義ではRANGEを「作成日」にして、LSIでは「更新日」にするなど
•複製したぶんだけ容量が増え、書き込みスループットも追加で要する
• スループットはテーブルと共有する 58
LSIの制限
• LSIはテーブル作成時にしか定義できないのでよーく考えてつけるべき
•作成出来るLSIはテーブルあたり5つまで • LSIは「強い整合性」での読み込みが出来る(ラグなしで読み込める)
•アンサーではまともに使っている箇所はない
59
GSIの特性
• GSIの実態は「選択したカラムをHASHとして複製したテーブル」
• RANGEありなし、どちらもOK • 例外として、GSIではHASH or HASH+RANGEはユニークでなくても別々のItemとして保存され、参照可能
•スループットは独自に設定する
60
GSIの制限
•テーブルとLSIでは1HASHあたり10GBの容量制限があるが、GSIには無い
• テーブル作成後でも作れるし削除できる •作成出来るGSIはテーブルあたり5つまで • 「強い整合性」での読み込みが出来ない(ラグの発生を前提にしなければならない)
61
インデックスにも十分なスループットが必要
•書き込みリクエストにおいて、インデックス側のみスループットが足りないときでも、テーブルへの書き込み性能が低下する。
• インデックスの作り方によってはHASHが集中するので、HASH集中による性能低下が起きないか注意が必要
62
インデックスの運用は結構難しい
•追加の書き込みスループットが必要 • とりあえず作っておけばいいものではない
• RDBとの併用を考えるべき
63
インポートのベストプラクティス
64
マネジメントコンソールからインポートできる
•マネジメントコンソールから簡単にインポート操作が行える
65
インポートの動作
• DataPipelineとして動作する • インポートするファイルはS3を経由する •インポート速度(スループット消費量)は指定できる
66
データフォーマットはマニュアルに載ってる
• PHP SDKにエクスポート用のデータ列にフォーマットして返す機能は見つけられなかった
• フォーマットはシンプルなので、マニュアル通りに自分でフォーマットすればよい
•「AWS Data Pipeline」の項目に記載されている
67
データフォーマット
• STX/ETX/LF で区切られたそこそこシンプルな行指向データ
「データエクスポートファイルの確認」で検索するとヒットするはず
68
HASH分散しないと速度がでない
•素朴に時系列でデータを並べてインポートしたらスループットを使い切れなかった
• サポートに問い合わせると、同一HASHへの連続した書き込みが起きていて使い切ってないようだ、というアドバイスを得た
• HASHを分散して並べたデータをインポートさせたらちゃんとスループットが出た
• HASH分散超大事69
HASH集中してるデータをインポートするには
•そうはいってもどうしてもHASHが集中しているデータをインポートする場合がある
•その場合はゆっくりじっくり時間をかけてインポートするしかない…と思う
•アンサーで行ったのは最大で10日間 •インポート時にはタイムアウト時間を設定する必要があり、UIからは9999時間まで設定できそう
70
バックアップは難しい
71
マスターデータのバックアップをどうするか
• DynamoDB はレプリカやユーザーセッションとして使い始めた
• どちらもDynamoDB自体のバックアップは不要
• 慣れてきたのでDynamoDBをマスターデータとして使い始めてみた
• そういえばバックアップはどうしよう?
72
DynamoDBのバックアップに銀の弾丸なし
•結論として、大容量のテーブルに大しては、現状で簡単なソリューションは無い
•全てのデータを読み込むことはできるが、現実的な時間で完了させるにはスループット消費がとんでもないことになる
• 「データ全体にアクセスする」「大量のItemを一気に読み込む」といった要件について、DynamoDBは無頓着っぽい
73
データが消えることは無いはず
• 3つのAZに複製されるのでItemが消えることはないはず
• 大量のItemを一度に消す方法はテーブル削除以外にはないので、誤操作のリスクは限定的
• 誤操作はIAMの権限で防止しよう
74
データの向き不向き
75
DynamoDBに向いているデータ
•例えば、スレッド型掲示板のコメント、ユーザーの行動ログ
•遅延が許されない要件 • 何らかの順序で小さく分割可能 • アクセスが分散すること •際限なく増えるデータ
76
DynamoDBに向いていないデータ
•インデックスの必要性が高い • データ全体の走査が必要
77
おすすめの学習方法
78
SlideShareのDynamoDB関係資料を通読
• AWS マイスターシリーズ • AWS Black Belt Techシリーズ • Deep Dive • 公式以外も有用なものが多い
79
「よくある質問」の通読
•マジでよく書かれてる •サポートに質問していた内容がほとんどすべて載っていた
80
手を動かす
•悩んだらテーブルを作ってクエリを打つ •マネジメントコンソールからデータを編集できる
•単発のクエリは aws cli が便利
81
DynamoDBを今後も使うか
82
DynamoDBは今後も使いたい
•使ってみてよかった。簡単にスケールするインフラは素敵だ
• KVS的な要件があれば今後も積極的に使いたい
•前提さえ守れば運用はスループットを監視するだけなので手間が少ない
•将来的に AWS Lamda との併用も魅力
83