Cosmos DB Change Feed セントリックなアーキテクチャ設計

ここ数年、公私ともに推し続けてきた Cosmos DB の Change Feed ですが、2022 年もやはり Change Feed 三昧となり、その有効性とさらなる可能性を実感する年になりました。特に、アーキテクチャ設計の観点では、Change Feed によって CQRS やマテリアライズドビューなどのクラウドデザインパターンを積極的に活用できるため、設計のシーンでは不可欠の存在になっています。

ということで、 2022 年の締めくくりとして「Cosmos DB Change Feed を中心としたアーキテクチャ設計」についてあらためてその考え方について紹介したいと思います。

単一データベースに依存したアーキテクチャの限界

アーキテクチャを設計する際、単一の大きなデータベース(ほとんどのケースが RDB)を中心に置き、それらを取り巻くように各種コンピューティングリソースを配置するという考え方が一般的でした。この考え方はアーキテクチャ設計としては非常にシンプルになる一方、少しでも要件がシビアになると、中心にあるデータベースがボトルネックとなり、アーキテクチャ全体の性能や拡張性を低下させてしまう結果になりやすいです。

なぜなら、データベースは書き込みと読み込みでは本来求められるデータ構造や処理特性が大きく異なるため、単一のデータベースで運用しようとすると必ずどこか(性能、拡張性、開発体験など)を妥協しなければならないためです。

コストをかけてスペックの高いデータベースにスケールアップして対策するという方法でその場をしのぐケースも多く見ますが、それでも一定の規模以上になると RDB の構造的な課題であるコネクション数の限界などによって、何らかの抜本的な対応が必要になることが多いです。

CQRS + マテリアライズドビューによる解決

この問題の解決策のひとつとして、「CQRS」 と「マテリアライズドビュー」というクラウドデザインパターンを組み合わせて、書き込みと読み取り双方のニーズを両立させようというアプローチがあります。

CQRS と マテリアライズドビュー

CQRS とは Command Query Responsibility Segregation の略で、コマンド(書き込み)とクエリ(読み取り)を分離することで、それぞれの負荷を分散させることができるという考え方です。

コマンド側には書き込みを得意とする特性を持ったデータストアを導入します。Azure ではコマンド側に Cosmos DB を選択することをお勧めします。Cosmos DB は非常に低レイテンシーで高スループットなデータ書き込みを実現できる特性を持っているためコマンド側の役割として最適です。適切なパーティション設計を行えば、ほぼ無限にスケールアウトさせるポテンシャルを持っている点もメリットです。

クエリ側にはデータの読み取りや集計などが得意なデータストアを配置するようにします。書き込み側と分離した効果を最大限に活かすため、読み取りのユースケースに最適な結果をすばやく返せるスキーマ構造を持ったデータベースを物理的に(場合によっては複数)配置してしまいます。これを「マテリアライズド ビュー」と呼びます。

読み取り専用の比較的シンプルなスキーマが設計できるなら、クエリ側にも Cosmos DB を採用できます。集計関数を多用したり動的にクエリを組み立てたりするようなシナリオであれば SQL DB や Postgres などの RDB を選択する方が良いでしょう。全文検索などが必要になるのであれば Azure Cognitive Search などの検索エンジンを配置することも可能です。それぞれに得意なエンジンを複数配置しても全く問題ないので、ユースケースに適切なデータストアを適材適所で使い分けましょう。

Cosmos DB Change Feed + Azure Functions による実現

CQRS とマテリアライズドビューを使ったアーキテクチャを構築するには、分離した書き込み側のデータストアと読み取り側のデータストアをできるたけリアルタイムに同期することが求められます。そこで、データストアの同期を正確に高速に実現するために、Cosmos DB の Change Feed を利用することができます。

Cosmos DB Trigger

Change Feed は、Cosmos DB のコンテナーに対して発生した追加や変更をほぼリアルタイムに配信する機能です。Cosmos DB は 99.99% ~ 99.999% の可用性を実現していますし、(パーティション毎に)配信される順序も保証されるので、高い信頼性のもとに整合性を保ったままマテリアライズドビューを構築できます。このような仕組みを自作して運用するのはかなり難易度が高く、Change Feed が存在していなかったら CQRS + マテリアライズドビュー は気軽に手を出せないアーキテクチャパターンになっていたでしょう。

ただし Change Feed は配信するところまでを担当する機能なので、配信されたデータをどのように処理するかはアプリケーション側で実装する必要があります。しかし、それについても Azure Functions の Cosmos DB Trigger を利用することで比較的容易に実装できるので心配はいりません。

Azure Functions の Cosmos DB Trigger を使うと、ごく簡単な設定だけで Change Feed と連動したデータ配信処理を実装することができます。中身は Azure Functions なので実装できることはもちろん自由です。例えば「ある条件に従ってデータを加工してから他のデータベースに書き込みたい」、「集計しやすいデータに整形してから、分析用のデータベースに書き込む」といったことが可能になります。

柔軟なアーキテクチャの実現

Change Feed を中心としたアーキテクチャーでは、コマンドとクエリが 1:1 ではなく、書き込み側のデータストアを中心にして、複数の Change Feed で同時並行でデータを配信できます。

ユースケース

例えば特定の条件に合致した場合に、一つはリアルタイムにイベント処理して Web ブラウザに通知し、同時にモバイルアプリにメッセージを送るといったことができます。さらに RDB と BI ツールを使った複雑なデータ集計といったパイプライン等も同時に生成することができます。

Cosmos DB Change Feed の用途は幅広く、将来を見据えて常にデータを低コストなストレージにアーカイブしておき、後から Spark などをアタッチしてビッグデータ分析を行うといったプロセスを追加することも容易です。このように、やりたいことを後からでも追加できるのが Change Feed の特徴であり、一番の強みです。