2020年版 モダンアプリケーションでのDB選定
こんにちは、クラスメソッドの岡です。
この記事は Serverless Advent Calendar 2020 8日目の記事です。
今日は2020年におけるモダンアプリケーションでのデータベース選定の話をまとめたいと思います。
前提として、今回はAWSでのマネージドサービスのデータベースでの比較になりますのでご了承ください。
今年は 4/23 Amazon KeyspacesのGAや、6/30 RDS ProxyのGA、9/30 Amazon TimestreamのGAが発表されて、サーバーレスで選択できるデータベースも幅が広がりました。
その中でどのユースケースでどのデータベースを選択していくのか、どんな特性があるのかを比較しながら見ていきたいと思います。
リレーショナルかNoSQLか
まずNoSQLは何かという話をはさむと、NoSQL=Not Only SQLで、RDBMS以外のデータベース管理システムを指すおおまかな分類語です。
なのでこの記事で紹介するDBはRDS以外は全てNoSQL、という分類になります。
NoSQLのDBでも機能や特性は様々なので、SQLかNoSQLかではなく各DBで比較していきたいと思います。
VPCが必要なデータベース
RDSもそうですがフルマネージドといってもVPCが必要なものとそうでないものに分かれます。
VPCが登場する以上、ネットワーク設計が必要になってくるので純粋なサーバーレスに比べると、どうしても構築コストやインフラの管理コスト、ランニングコストまで高くなってしまいます。
また、インスタンスを作成するものはインスタンスのサイジングも考える必要があります。
比較表
分類 | VPC | インスタンス | 読み込み整合性 | トランザクション(分離レベル) | |
---|---|---|---|---|---|
Amazon Aurora | リレーショナル | 必要 | 必要 | 一貫性 | 別表 |
Amazon DynamoDB | Key-Value | 不要 | 不要 | 結果整合性(オプションで強い整合性あり) | Serializable |
Amazon DocumentDB | ドキュメント | 必要 | 必要 | レプリカは結果整合性(読み込み設定あり) | - |
Amazon ElastiCache | インメモリ | 必要 | (クラスターとノード) | 結果整合性 | - |
Amazon Neptune | グラフ | 必要 | 必要 | 一貫性 | ※後述 |
Amazon Timestream | 時系列 | 不要 | 不要 | 結果整合性 | - |
Amazon QLDB | 台帳 | 不要 | 不要 | 一貫性 | Serializable |
Amazon Keyspaces | ワイドカラム | 不要 | 不要 | 結果整合性(オプションで強い整合性あり) | - |
目的別データベース選定
それぞれのDBの特徴や特性を軽く紹介していきます。
リレーショナル(Amazon Aurora)
RDSに管理されるMySQL/PostgreSQL互換のRDBです。
RDSのMySQL/PostgreSQLと比較したAuroraのメリット
- 対障害性
- 並列クエリ
- Global Database
- パフォーマンス: MySQLの最大5倍, PostgreSQLの最大3倍高速
RDSでは特段理由がなければ、Auroraを選択することになるかと思います。
適しているユースケース
- ERP
- CRM
- 財務・銀行
- SaaS(マルチテナントアプリケーション)
構成要素
- DBCluster
- DBInstance
- プライマリインスタンス(Writer)(書き込み/読み込み)
- Auroraレプリカ(Reader)
エンドポイント
- クラスターエンドポイント
- 読み取りエンドポイント
- カスタムエンドポイント
基本はクラスターエンドポイントと読み取りエンドポイントの2つを使って、読み取りインスタンスの用途がそれぞれ違って接続先をコントロールしたい場合のみカスタムエンドポイントを使います。
RDS Proxyの制限
前提として、RDS Proxyはあくまでライターインスタンスへのproxyなので読み込み用インスタンスには接続できません。
読み取りのワークロードの負荷分散には従来のReaderエンドポイントを利⽤する必要があります。
また、RDS Proxyを使う上で意識しないといけないのが、ピン留め(特定のクライアントのセッションが固定される現象)が発生した場合、接続の再利用の有効性が低下してしまうことです。
ピン留めの発生条件・回避方法はエンジンによって異なるので公式ドキュメントを参照してください。
Key-Value(Amazon DynamoDB)
分類としてはkey-valueとしていますが、正確にはkey-valueおよびドキュメントデータベースです。 スケーラビリティの仕組み上、Lambdaとの相性がいいです。
ただDynamoDBを使う前提として、アクセスパターンの定義を明確にしてそれを元にテーブル/インデックスを設計していくのが重要となります。
逆に言うとアクセスパターンが決まっていないようなサービスであれば、不十分な設計のままDynamoDBを使うよりもRDB(Aurora)を選択した方がいいと思います。
適しているユースケース
- リアルタイム入札アプリ
- Eコマース
- ゲームアプリ
- トラフィックの多いWEBアプリ
DynamoDBの読み込み整合性
DynamoDBの読み込みオペレーション (GetItem、Query、Scan) はデフォルトの場合、結果整合性になります。
しかし、オプションの ConsistentRead
を利用することで、強力な整合性のある読み込みを利用できます。(レイテンシは多少高くなります)
ConsistentRead
を使用した場合はRCUを2倍消費するため、コストも2倍になります。
注意点として、GSIでは強力な整合性のある読み込みはサポートされていません。
トランザクション
DynamoDBではトランザクションをサポートしています。
分離レベルはSerializableなので、トランザクションの実行中にトランザクション外でアイテムが更新された場合、トランザクションはキャンセルされて例外が発生します。
複数のトランザクションが同一アイテムを頻繁に変更するようなワークロードには不向きです。
ドキュメント(Amazon DocumentDB)
Amazon DocumentDBはMongoDB互換のフルマネージドなドキュメントデータベースです。
JSON-likeなデータなのでアプリケーション側で使うデータをほぼそのままDBに持たせることができます。
DynamoDBとの使い分けとしては、スケーラブルを優先するのであればDynamoDB、JSONのよりネストした構造にたいして柔軟にアクセスさせたいという場合にはDocumentDBの方が開発工数を下げられる可能性が高いです。コスト面はDynamoDBに比べると高いです。
適しているユースケース
- カタログ
- コンテンツ管理システム
- ユーザープロファイル
- パーソナライズ
読み込み設定のオプション
DocumentDBのレプリカは結果整合性となります。
しかし、ユースケースによって読み込みオペレーションの動作をオプションによって設定することが可能です。
- primary
- 読み込みをプライマリインスタンスにルーティング
- 高可用性およびスケーリングよりも整合性を優先するケース
- primaryPreferred
- 読み込みをプライマリインスタンスにルーティング、フェイルオーバー時はレプリカにルーティング
- 整合性を優先するがスケーリングを保ちたいケース
- secondary
- 読み込みをレプリカのみにルーティング
- 整合性よりスループットを優先するケース
- secondaryPreferred
- 1つ以上のレプリカがアクティブなときに、読み込みをリードレプリカにルーティング
- 整合性を優先するケース
- nearest
- レイテンシーに基づいて、読み込みがルーティング
- 整合性とスケーリングよりも、可能な限り低レイテンシーと高可用性の達成を優先するケース
インメモリ(Amazon ElastiCache)
Redis/Memcached互換のエンジンを持ったインメモリデータストアです。
どちらもインメモリデータストアですが、 RadisはKey-Value型データベースなのに対し、Memcachedは分散型メモリキャッシュです。
ノードやクラスターを作成して管理する必要があるのでその辺りの管理コストも考慮する必要があります。
ElastiCacheに限りませんが、頻繁に更新するデータをキャッシュするのは不適切なのでアクセスが頻繁で更新頻度が低いデータをキャッシュするように設計しましょう。
Radis OR Memcached
TH | Redis | Memcached |
---|---|---|
スナップショット | ◯ | × |
マルチスレッド | × | ◯ |
レプリケーション | ◯ | × |
トランザクション | ◯ | × |
Pub/Sub | ◯ | × |
地理空間のサポート | ◯ | × |
データ型 | List、Set、Sorted Set、Hash、Bit Array, HyperLogLog | Stringのみ |
シンプルなデータをキャッシュしたい場合はマルチスレッドのMemcachedで良さそうですが、Redisの方がかなり多機能になっているので用途に合わせて選択する必要があります。
適しているユースケース(Redis)
- キャッシュ
- DBクエリ結果のキャッシュ
- フルページキャッシュ
- セッションストア
- ゲームのリーダーボード
- 地理空間
- リアルタイム分析
- メッセージブローカー
適しているユースケース(Memcached)
- シンプルなデータのキャッシュ
グラフ(Amazon Neptune)
Amazon Neptuneはフルマネージドのグラフデータベースサービスです。
データモデル
一般的なグラフモデルであるプロパティグラフと、RDFモデル2つのデータモデルをサポートしています。
プロパティグラフの場合、オープンソースであるApache Tinkerpop Gremlin を使用してデータを作成及びクエリします。
対してRDFグラフの場合は、W3Cによって標準化されたグラフパターンマッチング言語であるSPARQLを使用してデータを作成およびクエリします。
適しているユースケース
- SNS
- リコメンデーション
- 不正検出
- 鉄道(路線図)
このように多対多の関係性を示すものに適しています。
トランザクション
Amazon Neptune は、読み取り専用クエリとミューテーションクエリに異なるトランザクション分離レベルを実装します。以下の基準で読み取り専用とミューテーションを区別します。
- SPARQL
- 読み取りクエリ: (SELECT/ASK/CONSTRUCT/DESCRIBE)
- ミューテーションクエリ: (INSERT/DELETE)
- Gremlin
addE()
addV()
drop()
などのクエリパスステップを含む: ミューテーションクエリ
ミューテーションクエリの一部として行われた読み込みは、トランザクションの分離レベルは READ COMMITTED
となります。
対して読み取り専用クエリの分離レベルは SNAPSHOT
となります。
Amazon Neptuneの関連記事 - Developers.IO
時系列(Amazon Timestream)
※現在(2020/12/08)東京リージョンはまだ利用できません。
Amazon Timestreamは高速でスケーラブルな時系列データベースで、1日あたり数兆の時系列データポイントを簡単に保存および分析できます。
柔軟な検索
SQL構造をサポートしているので、SQLライクなTimestreamのクエリ言語を使ってデータの検索が可能です。
公式のベストプラクティスを見るとデータ書き込み時は、パフォーマンスの最適化のためバッチ処理的に1つのリクエストで複数レコードを更新すのがいいと書かれています。さらにTimestamp順に書かれていると書き込みパフォーマンスが向上します。
適しているデータの例
- IoT機器データ
- 株価
- 気温
- 通信量
Timestreamの関連記事 - Developers.IO
台帳(Amazon QLDB)
Amazon QLDBはフルマネージドな台帳専用データベースです。
データの変更履歴はイミュータブル(変更や削除が不可能)で、意図しない変更が発⽣していないことを暗号技術で検証します。
履歴の追跡と変更管理をしたい(管理者でも履歴を改竄できないことを保証したい)場合に有用です。
SQL準拠のクエリ言語、PartiQLを使ってデータにアクセスします。
制限として、全てのPartiQLに対応している訳ではなくいくつかSortが対応していなかったりします。
QLDB Streaming
QLDBからKinesis Data Streamsへデータを送って後続のLambdaで任意の処理を行うことができます。
QLDBを使ったデータ分析
※ 一歩踏み込んだAmazon QLDBの利用方法 から引用
QLDBのエクスポートジョブを使うことでS3にデータを出力することができます。S3のデータをGlueに渡して分析処理に使用できます。
適しているデータの例
- 医療カルテ
- 戸籍・住民票
- 金融・銀行
- 契約管理(保険等)
- ポイント管理サービス
ワイドカラム(Amazon Keyspaces)
Amazon Keyspacesは、Apache Cassandra互換のマネージドデータベースです。
Cassandra クエリ言語 (CQL) API, Cassandra ドライバー、使用中の開発者ツールをサポートしているので、オンプレのCassandraを使用していた既存のアプリケーションをほぼそのまま利用できます。
適しているユースケース
低レンテンシが必要なアプリケーションに向いています。
- 設備保全、フリート管理、ルート最適化といった用途の大規模な産業アプリケーション
- IoTのデバイスデータ、ゲームのプレーヤー情報
- オンプレCassandraのクラウド移行
まとめ
アーキテクチャを選定する上で、データベースの選択はかなり重要です。
サーバーレスでアプリケーションを構築する以上、データベースレイヤーもインフラの管理コストがかからないというのも大事な指針になるかと思います。
可能な限り、VPCやインスタンスが不要なデータベースを選ぶことでよりアプリケーション側の開発に注力できます。
また、サービスの中で同じエンティティでも書き込みと読み込みのデータ表現が一致しないこともあるかと思います。
必要に応じて、書き込みと読み取りを別々のモデルに分離(CQRS)してそれぞれに適したデータベースサービスを選択していくことも有用です。(書き込みはDynamoDBに、DynamoDB Stream経由でAuroraに読み取り用データを配置する、など)