クラウドDBのアーキテクチャの形式について

## はじめに

- 特に深い意味のないポエムです
- 一般論であり、特定の製品とは一切関係がないです
- 内容に誤りや偏りが含まれている可能性があるので、内容を鵜呑みにしないようお願いします

## クラウドDBのアーキテクチャの分類

教科書的にはデータベースのアーキテクチャの形態として以下のものが主に挙げられることが多いです。
- Shared-Memory
- Shared-Disk
- Shared-Nothing
 
[Database System Concepts, 7th Ed.](https://db-book.com/slides-dir/PDF-dir/ch1.pdf)

それぞれの形式では物理メモリ、ストレージを共有しているかどうかが異なります。
※実際の定義、物理的な構成は実装により大きく異なると考えられます

| 名前 | 物理メモリの共有 | ストレージの共有 | スケール・アウトの対象|
|:-:|:-:|:-:|:-:|
|Shared-Memory|◯|◯|なし|
|Shared-Disk|-|◯|コンピュート|
|Shared-Nothing|-|-|コンピュート, ストレージ|

Shared-Memory形式は単一ノードで動作するDBMSであり、スケーラビリティに限界があります。
一方でShared-Diskはストレージが共有されているものの、CPU、メモリを持つコンピュート・ノードは共有されておらず、スケール・アウトが可能です。
Shared-Nothingではストレージ、コンピュート・ノードともに共有されておらず、どちらもスケールアウトします。

しかしながら、現代のクラウドで主流のDBMSのアーキテクチャの形態は上記の分類では実態に即していないことから、こちらの論文では新たな分類方法が提案されています。

[Is Scalable OLTP in the Cloud a Solved Problem?](https://www.cidrdb.org/cidr2023/papers/p50-ziegler.pdf)

- Single-Writer
- Partitioned-Writer
- Shared-Writer

分類の軸としては「ストレージを共有しているかどうか」「ストレージを共有している場合、ノード間でデータの整合性を取り、どのノードからも書き込みを実現しているかどうか」となります。
※この論文では登場していませんが、ストレージを複数ノードで共有せず、非同期のレプリケーションで別のストレージを持つレプリカへ変更差分を伝搬する方式もクラウド上で広く使われていると考えられます

| 名前 | ストレージの共有 | ストレージを共有している場合、ノード間のデータの整合性の維持 |
|:-:|:-:|:-:|
|Partitioned-Writer|-|-|
|Single-Writer|◯|-|
|Shared-Writer|◯|◯|

ストレージを一切共有していないPartitioned-Writerは特定のストレージに対して特定のWriterからのみ書き込みを実施可能です。
通常は何らかの方法でデータの配置を決定しアクセスを分散させ、ノードを追加することで読み込み、書き込みの双方のスケールアウトを実現しています。
ストレージを共有していないのでアクセスがおおよそ均等に分散させる場合には処理性能がスケールしますが、アクセスの偏りには弱い傾向があります。

Single-Writerはストレージを複数のノードで共有してはいるものの、書き込みを単一ノードから実施可能としていることから書き込み性能には制限があります。
一方で読み込み処理は複数の非同期リード・レプリカでスケールアウト可能です。
このときストレージが共有されていることから、データのアクセスに偏りがある場合にもスケーラビリティを発揮することが可能です。
※ストレージを複数ノードで共有せず、非同期のレプリケーションで別のストレージを持つレプリカへ変更差分を伝搬する方式も利点と欠点は同じであり、変更差分を伝搬する関係でより多くの書き込みI/Oが発生すると考えられます。

Shared-Writerはストレージを複数ノードで共有するだけではなく、各ノード間でデータの整合性を維持することから書き込みに関しても複数ノードから実行可能です。
この方式の場合、アクセスに偏りがある読み込み処理だけではなく、共有されたストレージのスループットが許す範囲で、特にアクセスに偏りがある場合の書き込み処理に関してもスケールすると考えられます。
※書き込みスループットの上限はストレージを共有していないPartitioned-Writerのほうが優れていると考えられます

## なぜクラウドではPartitioned-WriterとSingle-Writerが多いのか?

クラウド・ネイティブのDBMSではShared-Writerはあまり見かけず、Partitioned-WriterとSingle-Writerに偏っているように見受けられます。
Partitioned-WriterとSingle-Writerに偏っている理由については様々な要因があると考えられますが、以下のような要素が影響を与えていると考えられます。

### Webサービスの膨大なスループットを捌きたい

大規模なWebサービスは非常に高いスループットを要求し、急激に成長し続ける可能性があります。
したがって、アクセス・パターンやクエリを最適化することにより、読み込み、書き込みともに高いスケーラビリティを発揮し、新しいノードを追加することでスループットを拡張し続けられるPartitioned-Writer形式のDBMSが求められていると考えられます。
特に書き込み処理に関してはSingle-Writer方式ではどうしても限界があるので、書き込み処理のスループットを捌く際に有効であると考えられます。

### Single-Writer方式が有効な場面
 
しかしながら、世の中にはジョインを多用したり、複雑なACIDトランザクションの実行などが求められるアプリケーションもたくさん存在します。
Single-Writer方式の場合、各ノードはジョイン対象のinner/outerのテーブルや、トランザクションでの更新対象データを必要に応じてShared-Storageから取得し、物理メモリやローカル接続のNVMeストレージ上にキャッシュしてから同一ノード上で処理可能であることから、必ず他のノードからネットワーク経由でデータを取得する必要があるPartitioned-Writerと比較し効率的かつシンプルであると考えられます。
また、更新についても単一ノードからの更新であれば2PCを避けられることから、アクセスを分散できない更新処理もSingle-Writer方式のほうが効率的であると考えられます。

次のドキュメントで説明されている通り、同一ノード上の物理メモリ(おそらくキャッシュ)へのアクセスはネットワーク越しのデータの転送と比べて桁違いにレイテンシーが低く効率的に行うことが可能です。
※実際にはDC内外のネットワークのレイテンシーはドキュメントの値よりもやや大きいと考えられます
https://gist.github.com/hellerbarde/2843375

また、ワークロードによってはPartitioned-Writer方式を利用しても、きれいにアクセスをノードごとに分散できない可能性もあります。
Single-Writer方式では各リード・レプリカがShared-Storageの任意のデータを保持してワークロードを処理できることから、読み込み処理に関してはアクセスの偏りに強いと考えられます。
※各ノードのキャッシュで補えるものの、Shared-Storage自体のスループットの限界があると考えられます

加えて、一般的に一つの処理で多くのノードへのアクセスが必要になればなるほど障害に遭遇する可能性が高まることから、単一ノード内の処理とすることでこれらの複雑さを軽減し、エラー・ハンドリングなども簡素化することが可能となります。

### クラウドの環境ではノード間のネットワークのレイテンシーの削減よりも複数DCへの分散による高い可用性、耐久性が求められること

クラウド環境では各ノードを複数のDCに分散することでDC障害に対応可能な高い可用性、耐久性を実現していることから、頻繁に他のノードを参照し、各ノードが低いレイテンシーで接続されている必要のあるShared-Writer方式の実現が難しいと考えられます。

以上のことから、クラウド環境ではワークロードに合わせてSingle-Writer, Partitioned-Writerを使い分けることが一般的となっているのではないでしょうか。

## Partitioned-Writer方式のSQLを実行可能なDBMSについて

前述の通り、ネットワークのレイテンシーはメモリ上のデータのアクセスよりも遥かに遅く、また複数ノードをまたがる処理のエラー・ハンドリングも非常に複雑となります。
したがって、SQLのジョインを素直に処理しようとすると大量のネットワーク越しのデータの転送が必要となることから非常に非効率で、またネットワークや他のノードの障害に脆弱となります。
※ジョインの計算量はアルゴリズム次第であるものの、ジョインのinner/outerのテーブル・サイズが増加すればコストも増加していきます

その弱点を克服するためにPartitioned-Writer方式のSQLを実行可能なDBMSでは、事前にinner/outerテーブルを同一ノード上に手動で配置することでネットワークを介さずにジョインを効率的に実施可能としていることが多いようです。

以上のことを踏まえると、ネットワーク越しに他のノードのデータを必ず取得する必要のあるPartitioned-Writerは物理メモリを共有するSingle-Writer方式のようにad-hocなクエリを記述して効率的に処理可能なDBMSではないと考えられます。

ネットワークのレイテンシーが遅いという物理的な制約に基づくものであることから劇的な改善も難しく、Single-Writer、ないしShared-Memory方式のような同一物理メモリ上のデータにアクセス可能なDBMSのように扱うことはできないと考えられます。
※無理やりそういったクエリを実行することはできなくはないものの、大量のネットワークのトラフィック、CPU負荷が発生し著しく不経済であると考えられます