Dynamo論文からDynamoDBへ
2007年の論文「Dynamo: Amazon's Highly Available Key-value Store」と、あなたが 今日呼び出すDynamoDBは、名前と目標 — あらゆる規模で予測可能なパフォーマンス — を 共有していますが、同じシステムではありません。論文が記述したのは、あなた自身が 運用する内部の結果整合性ストアでした。DynamoDBは、教訓を残して仕組みのほとんどを 捨て去ったマネージドサービスです。
DynamoDBはDynamo論文に基づいている?
一部は。DynamoDBはその名前と中核的な目標 — 規模における予測可能なパフォーマンスと 高可用性 — を2007年のAmazon Dynamo論文から取っており、の ハッシュのアイデアをほぼそのまま残しました。しかしそれは別の、マネージドな システムです。論文のベクタークロック、ゴシップによるメンバーシップ、調整可能な 読み書きクォーラムは消え去り、AWS所有の内部構造に置き換えられました。
- 論文が解いたのは可用性であって、使い勝手ではありません。 その仕事は、たとえ 古い読み込みを返す代償を払ってでも、休日のトラフィックスパイク中に書き込みを 決して拒否しないことでした。
- DynamoDBは形を残し、内部を置き換えました。 キーのハッシュでパーティション 分けされ、AZをまたいでレプリケートされ、水平にスケールする — けれど競合解決の 内臓(ベクタークロック、ゴシップ、リードリペア)は消えました。
- もうツマミを調整しません。 論文の
N、R、Wは1つの選択になりました。ConsistentReadをtrueにするかfalseにするか。残りはAWSが所有します。 - メンタルモデルはいまだに報われます。 この系譜を知っていれば、なぜ
Scanが 高価で、なぜGSIの読み込みが遅れることがあるのかが説明できます — どちらも オリジナルの設計から自然に導かれます。
論文が実際に解いていたもの
Amazonのショッピングカートはダウンできませんでした。負荷下で書き込みを拒否する — あるいは失敗したレプリカでブロックする — リレーショナルデータベースは容認できません でした。2007年のDynamo論文は整合性より可用性を選びました。常に書き込みを 受け付け、不一致はあとで調整する。そのトレードが、以下すべての根っこです。
単一のマスターなしにそれをやるために、Dynamoは2つの問いに自ら答えなければなりません でした。キーはどこに住むのか、そして読み込みや書き込みが成立するまでに何個の コピーが一致しなければならないのか。
一貫性ハッシュ:キーはどこに住むか
論文はすべてのノードをハッシュリング上に配置しました。キーの位置はそのキーの
ハッシュで、時計回りで次のノードが所有し、続くN-1個のノードにレプリケートされます。
ノードの追加や削除は隣接するキーだけを再配置し、データセット全体は動かしません。
それが一貫性ハッシュで、DynamoDBがほぼそのまま残した唯一のアイデアです。
DynamoDBは今でもあなたのをハッシュして、どの物理
パーティションが項目を格納するかを決めます。カーディナリティの低いパーティション
キー — 例えば2つの値しか持たないSTATUS — を選ぶと、同じ値を持つすべての項目が
同じパーティションに着地します。それがの
落とし穴で、リングの直接的な帰結です。ハッシュは同一のキーを同一の住所に送るのです。
クォーラム:何個のコピーが一致しなければならないか
論文の2つ目のツマミはクォーラムでした。N個のレプリカがあるとき、書き込みは
そのうちW個がackすると成功し、読み込みはそのうちR個に問い合わせます。
R + W > Nと設定すればどの読み込みも最新の書き込みを持つノードに少なくとも1つ
重なる — 強い整合性です。それらを低く設定すれば、鮮度を速度と稼働時間と交換します。
Dynamoは「ずさんな」クォーラムを走らせました。ターゲットノードがダウンしていれば、 書き込みは代役に行き、あとで返されました(ヒンテッドハンドオフ)。競合する バージョンはベクタークロックでタグ付けされ、読み込み時にアプリケーションが 調整しました。
DynamoDBが残したもの、変えたもの
DynamoDBは目標とパーティショニングを継承し、それからオリジナルを運用しにくくして いた部分を削除しました。
| 関心事 | 2007年のDynamo論文 | 今日のDynamoDB |
|---|---|---|
| キーの配置 | 一貫性ハッシュリング | パーティションキーのハッシュ → マネージドパーティション |
| レプリケーション | Nノード、あなたが選ぶ | AZをまたぐ3コピー、AWSが固定 |
| 整合性のツマミ | R、Wクォーラムの調整 | 1つのフラグ:ConsistentRead |
| 競合解決 | ベクタークロック、読み込み時のアプリ側マージ | リージョン内では不要 — 書き込みはリーダーレプリカを通じて直列化され、ラストライターウィンズはグローバルテーブルのリージョン間でのみ |
| メンバーシップ | ピア間のゴシッププロトコル | フルマネージド、あなたには見えない |
| マルチキー操作 | なし — 純粋なキーバリュー | Query、GSI、トランザクションを上に重ねる |
論文のAPIは2つの呼び出しでした。get(key)とput(key, value)。DynamoDBは同じ
キーバリューの中核の上にソートキー、インデックス、クエリを加えました — だからこそ
Queryは安く(1パーティション)、Scanはそうではありません(リングがこれまでに
作ったすべてのパーティションを歩きます)。
書き込みはどう進むのか、当時と今
以下のフローは、論文のクォーラム書き込みとDynamoDBのマネージドな書き込みを対比 します。形は韻を踏みますが、責任はあなたのコードからAWSへ移りました。
論文ではクォーラムの計算とマージを自分が所有していました。DynamoDBではその下半分
まるごとがマネージドで、あなたはリクエストごとにConsistentReadを選ぶだけです。
系譜があなたのコードに漏れ出すところ
結果整合性のデフォルトは、論文が透けて見えているものです。グローバルセカンダリ インデックスは非同期にレプリケートされるので、書き込んだばかりの項目が一瞬 インデックスから欠けることがあります — 同じ「あとで調整する」取引が、インデックス層で 起きているだけです。その遅延が問題になるときについてはGSI vs LSIを 参照してください。
強い整合性は2つの方法で買い戻せます。ベーステーブルの読み込みで
ConsistentRead: trueを使う(リーダーコピーにルーティングされます)か、書き込みを
ConditionExpressionでガードして、項目の現在の状態が一致するときにだけ着地する
ようにする。DynamoDB Expression Builderで
1つスケッチしてみてください — 例えばattribute_not_exists(PK)でPutItemを挿入
専用の操作にする、論文の競合検出の現代版です。
覚えておくべき唯一のこと
論文は書き込みに決してノーと言わないことに最適化しました。DynamoDBはそのバイアスを
継承しており、だからこそデフォルトが可用性を優先し、強い読み込みのコストが高いの
です。シングルテーブル設計のように単一パーティションの
Queryのためにキーをモデリングし、本当に必要なときにだけScanに手を伸ばす —
リングは、全テーブルを歩くことを、聞こえるとおりに高価にします。
DynoTableを試すと、テーブルとそのGSIを参照し、それから自分のデータに 対してSQL WorkbenchでJOINとGROUP BYを実行できます。