Azure Cosmos DB がやってきた

DocumentDB の記事を書いていたら[15]、//Build 2017で、Azure Cosmos DB が発表[1]された。 Cosmos DBは、Multi-model database and multi-APIのGlobally Distributed データベース・サービスだ。

Azure Cosmos DB in KeyNote

//Build 2017 Keynote より [1]

「DocumentDB何処行った、名前が変わったの?」と思ったら、そんなに簡単な話では無かった、Azure Cosmos DBは、DocumentDB、MongoDB, Azure Table,Gremlin などの複数のAPIをサポートしたマルチモデルの分散データベース[2]で Document DBはそのAPIの一つという位置づけになった。従来の Document DBで使ってた分散データベース基盤の部分は、ある程度汎用的に出来ていてJSON以外のデータモデルも扱えるので、今回はKey-Value と GraphのデータモデルにAPIを付けてブランディングも新たにお披露目したよという話だ。素晴らしい。

ざっくりまとめると、下図のような感じになってる。Cosmos 分散データベース基盤に、データモデルが乗っていて、それぞれAPIを提供するといった感じだ。AzureTable(Key-Value), Gremlin(Graph) は、Preview(既に試すことができる)で、Splark は、アナウンスだけ、DocumentDBとMongoDB APIはGAのままだ。この2つがGAのままなのは、Cosmos DBになっても基本的な実装は同じだからだろう。

Azure Cosmos DB in KeyNote

Azure Cosmos DB スタック

Breakout Session

//Build 2017のCosmos DBの2つのBreakout Session、B8047[3]と、T6058[4]では、もう少し詳細に触れられている。

Table API in Azure Cosmos DB

//Build 2017 B8047 より [3]

その中でも興味深いのは、B8047 のTable APIの下りだ(動画だと35:50あたり[5])。超訳すると。

Cosmos DB に、既存のTable Storage(以下Standard Storage)互換のTable API(以下Premium Table)を実装した。もう、Premium Table SDK[6]をダウンロードして試せる。アプリケーションの変更は必要ない(SDKでを切り替えるだけ)で、ローレイテンシー、5つの一貫性、グローバルディストリビューション、セカンダリーインデックス等、数々のCosmos DBの特性が得られる。

特に重要なのは、これに続く部分だ。

現在「storage optimized offer」に向けて作業中、現在の Cosmos DB は、スループットの最適化、ローレイテンシーなどのpremium experience にフォーカスしているが、hot work load 以外の場合でも選択肢にできるように取り組んでいる。

現在のCosmos DB(旧DocumentDB)の料金体系は、基本hot work load向けだ。アクセス頻度が低いデータが多くなってくるとAzure Storageとのコスト差がどんどん大きくなっていく。データ全体の中で一部だけのアクセス頻度が高く、殆どのデータはアクセス頻度が低い場合は、Cosmos DBだけでなく、なんからの外部データストアとの連繫を検討する必要がある。これは特に、Standard Table(これからは、Azure Table StorageのことはStandard Tableと呼ぼう)からの移行を考えた時に重要な検討課題だろう。それがうまく解決できるなら、かなり有り難い。

同時に公開されたBlogから

Cosmos DBも発表共に公開されたBlogもなかなか面白い。Azure Cosmos DB: The industry’s first globally-distributed, multi-model database service[7]の A Brief History of Cosmosには簡単なCosmos DBの歴史が書いてあった。それによると、

Azure Cosmos DBは、2010年に「Project Florence」で開始、グローバルディストリビューションの課題を解決するためにMSの社内で使っていたが、他の皆にも役に立つと思い、2015年にAzure DocumentDBの形でこのテクノロジの第1世代を利用できるようにした。

云々だそうだ。世界中で展開するサービスの下りをみて連想したのは、AzurePortal。「最近ポータルが速くなってきてるのはエンドポイントを日本に持ってきたからかな、でもUSのリソースも普通に見れて操作できるしどうなっているのだろう」と思っていたが。Cosmos DBのようなグローバルディストリビューションの仕組みがあれば実装イメージが湧いてくる。実際のところはどうなっているかはわからないが。なかなか興味深い。

あとA technical overview of Azure Cosmos DB[8]に、Leslie Lamport 博士が出てきて、Cosmos DBの一貫性の設計、実装にTLA+[9]のCosmosでの活用の話をしていたのが興味深かった。[9]

「正しく動く分散システムを作るのはなかなか難しい、そんな中で形式手法が有効だ。Cosmos DBは設計、実装で、TLA+が複数の一貫性のサポートやSLAの提供に貢献した」的なことを言っている(超訳過ぎるので原文参照)。AWSでは、2011年からFormal Methodsを使って、重要な分散システムのアルゴリズム設計を行っている[10]と話題になったが、MSが分散システムの設計に使っている公言したのは初めてな気がする。利用者サイドからの一貫性の検証は難しいので設計、実装の取り組みがわかるのは有り難い。

この記事には、Azure Cosmos DBのデータベースエンジンの中身についても少し書いてあった。以下超訳

Azure Cosmos DBのデータベースエンジンのコアタイプシステムは、汎用的にどのようなデータにも対応するatom-record-sequence (ARS)と呼ばれる構造となっている。Atomは、文字列、論理型、数値などのprimitive型、recordは構造体、sequence はatom、record、sequenceの配列である。また、Azure Cosmos DBのデータベースエンジンは、JSONなどのAPIが利用するデータモデルとARSベースのコアデータモデルの効率的な変換と投影を実装し、動的型付き言語(dynamically typed programming languages)からコアデータモデルへのネイティブアクセスをサポートする。このデータベースエンジンを使うことで、Cosmos DBのAPIは、battle-tested でフルマネージドな、グローバル分散型データベースシステムのすべての利点を得ることができる。

ARSは、プリミティブ型を単純に並べただけの構造なのでJSONをそのまま保存するよりは効率は良いだろうし、別のデータモデルを実装し易いだろう。コアデータ・モデルを扱うデータベースとしての基本的な部分、整合性、リプリケーション、バックアップなどは共通の仕組みが使えるというわけだ。

Premium Tableの現況

大分長くなってしまったので、最後に、Premium Tableをちょっと動かしてみた感想を書いて終わりにする。

GitHubに、Getting started with Azure Cosmos DB: Table API[11]というサンプルコードがある。Premium/Standard Table に繋いで簡単な速度を測るようなコードだ。それを動かしてみた。まずは結果から。※Premium Table の測定は、2000 RU/秒のパーテーション無しコレクションで行った。

Premium/Standard Table のレイテンシー
Title 操作 p0 p50 p90 p99
Premium 作成 5.2 7.2 9.0 13.0
Standard 作成 4.2 11.9 20.7 26.2
S/P 比   81% 164% 229% 201%
Premium ID検索 1.3 2.0 3.2 5.7
Standard ID検索 2.4 3.4 5.2 11.2
S/P 比   184% 170% 162% 197%
Premium プロパティ検索 2.9 4.8 6.9 10.8
Standard プロパティ検索 49.4 55.7 67.0 78.3
S/P 比   1683% 1166% 965% 726%
Premium 置換 5.0 7.6 9.3 13.2
Standard 置換 4.7 12.2 20.6 25.4
S/P 比   94% 161% 221% 192%
Premium 削除 4.5 6.0 7.2 9.4
Standard 削除 2.8 3.6 4.9 10.0
S/P 比   62% 60% 68% 106%

1万エンティティで1度だけしか測っていないので、数値の絶対値は参考程度にしかならない。注意して欲しい。それでも傾向ぐらいはわかる。

ID検索の部分が、パーテーションキー、ローキーによる検索。プロパティ検索は、Standard Tableだとインデックスの効かずにフルスキャンになるが、Premium Tableでは全てのプロパティに自動的にインデックスが作成されるので、この場合もインデックスが利用される。

全体的な傾向を見ると、50パーセンタイルでは、プロパティ検索以外は、Premium が1.5から1.6倍程度Premiumが速い。プロパティ検索はセカンダリーインデックスの効果を見る項目で、Standardだとフルスキャン、Premiumだとインデックスが使われる。セカンダリーインデックスの効果は絶大で10倍以上Premiumが速くなる。データ件数が多くなればさらに差が出るだろう。

99パーセンタイルでは、2つの差は広がり、2倍程度の差になる。今回は件数が少ないので、この程度の差になったが、件数を増やして調査時間を長くすれば差は大きくなると思われる。

数字だけ見ると、Standard Tableが意外と奮戦している、前に調べて時より少し速くなっているようだ。Premium Tableはまだプレビューという点を差し引いても、一貫してレイテンシーが低いというのは魅力的だ。セカンダリーインデックスを更新する分、更新系は不利なはずだが、それでもStandardより速いのも今後が期待できる。

総じて、Premiumが速く、特にセカンダリーインデックスが効くと劇的に速くなる。全体的にPremiumのレイテンシーはバラツキが小さく一貫してレイテンシーが低いのは好印象だ。

Premium Table SDK

サンプルコードを見ると、PremiumとStandardの切替は接続文字列[12]の設定だけだ。Premium Tableには、DocumentDBと同じように、Consistencyや接続モードの設定がある、それをどうやってやるのかと言うと、現状では、AppSettings に書く[13]。 AppSettingsには下記の設定ができるようだ。基本的にはDocumentClient関連の設定だ。この方法だと、Standard Tableのコードを修正せずに動かしたいという目的は果たせるが、Premium Tableに最適化されたコードを書きたい場合には、あまり適さない。コードで変更できるようにして欲しい。

AppSettings での設定項目
設定名
TableConnectionMode
TableConnectionProtocol
TableConsistencyLevel
TableDisableRUPerMinuteUsage
TableIndexingPolicy
TableIsRUPerMinuteEnabled
TableMaxConnectionLimit
TablePreferredLocations
TableQueryContinuationTokenLimitInKb
TableQueryEnableScan
TableQueryMaxDegreeOfParallelism
TableQueryMaxItemCount
TableThroughput

現在のSDKだと、スロットリングがかかったときのリトライのハンドリングが怪しいようだ。それにサンプルコードではスロットリングエラーになった場合の処理が考慮されていない。そのため今回の測定ではスロットリングがかからないように2000RU/秒に設定した。

AppSetting設定やスロットリング対策からも言えることは、Premium Tableに最適化したコードが必要な場合は、そのためのコードが必要になるということだ。例えば、レスポンスヘッダーのRequestChargeを見てアプリケーションで消費RUを制御するなどのコードはスロットリングの仕組みが違うので、Standard TableとPremium Tableでは互換性が無い。ある程度SDKで吸収できるだろうが、プロダクションコードでは、ある程度アプリケーション側で対応する必要があるだろう。

Fidderで通信を覗いてみたところ、Premium Table SDKは、Premiumに繋ぐときは、x-ms-version: 2017-02-22 を、Standardのときは、x-ms-version: 2016-05-31 を使ってた。Premium の場合は、パーテーションマップの取得など、DocumentDBでお馴染みのやつが最初に入るなど、wired protocal としては全く互換性が無い別プロトコルだ。エンティティの作成も、今のStandardではレスポンスは空になるが、Premiumではしっかり中身が入っている。

リクエストとレスポンスはこんな感じだ

ちょっと見 DocumentDBとウリ2つだ。Premium Table SDK が、DocumentDB Client SDK を参照していることからも、実際の通信はDocumentDBと同じプロトコルを使っていることが伺える。このままGAになるかどうかは分からないが、この仕組だとプロトコルレベルではStandardとPremiumは別物になるので、既存のStandard Table Storage向けのライブラリは作り直す必要がある。最初に聞いたときは、REST APIレベルで互換なのかと思ったので、ちょっと肩透かしだ。しかし、パフォーマンスを考えた場合、今のStandardのREST APIよりDocumentDB形式の方が将来性がある気もする。なかなか面白いアプローチではある。

まとめ

つらつらと書いていたら随分長くなってしまった。これで、Graph APIの話とかTLA+の話も書きたかったが疲れたので、この辺で一旦終わる。最初、Premium Tableを聞いた時は、DocumentDB時代の価格体系だとちょと用途が限定される気がして、どうなのかとも思ったが、B8047[5]の話を聞いて、今はとても期待している。

今の気分は、「Cosmos DBはいいぞ」と言う感じだ。

追記 (2017/5/15)

現在のTable APIではパーテーション無しコレクションしか作成できず、コレクションの容量は10GBだ。これはプレビューの制限だと思われる。10GB以上のデータで評価したい場合は要注意だ。現時点でもスループットは、10万 RU/秒まで設定でき、Standardのストレージアカウント全体のパフォーマンスターゲット(1Kエンティティで毎秒20,000トランザクション)[14]を上回る。また、Table StorageのTableがCosmos DBのコレクションになるので、Table単位で課金される。Standardだと割りと気軽にTableを作れたのでこれも設計変更の要因になるだろう。

脚注

[1](1, 2) [1:22:26]Azure Cosmos DB Introduction
[2][1:27:20]Rimma Nehme, Azure Cosmos DB demonstration
[3](1, 2) B8047 How to build globally-distributed, fast, billion-user applications with Azure Cosmos DB
[4]T6058 Azure Cosmos DB: NoSQL capabilities everyone should know about
[5](1, 2) [0:35:50]B8047 のTable APIの部分
[6]Premium Table SDKソースは未公開
[7]Azure Cosmos DB: The industry’s first globally-distributed, multi-model database service
[8]A technical overview of Azure Cosmos DB
[9](1, 2) Foundations of Azure Cosmos DB with Dr. Leslie Lamport, longレスリー ランポート先生のインタビュー、お勧めです。
[10]How Amazon Web Services Uses Formal Methods
[11]Getting started with Azure Cosmos DB: Table API
[12]接続文字列の切替部分
[13]AppSettingsでの設定箇所
[14]Blob、キュー、テーブル、およびファイルのスケーラビリティ ターゲットサンプルコードでは、IDでの読込が1 RU/秒程度、エンティティ作成が10 RU/秒程度を消費していた。それをベースに試算すると、読込はStandard Tableのストレージアカウントの10倍、書込は同等のスループットということになる。ここでは、Read/Write混合を想定して「上回る」という表現にした。
[15]日経クラウドファースト 2016年6月号Azure DocumentDB 予約性能と実測値がほぼ一致 応答時間はデータストアーで最高レベル

その他の参考リンク