異種DB環境でACIDを実現するScalarDB Clusterの基本構造と設計思想
目次
- 1 異種DB環境でACIDを実現するScalarDB Clusterの基本構造と設計思想
- 2 開発チームが知るべきScalarDB Cluster主要インターフェースと用途別選定基準
- 3 ScalarDB CoreとCluster版の機能差で判断する商用ライセンス採用の条件
- 4 マイクロサービス間トランザクションにおける2PC対応とルーティング設計の実務指針
- 5 Kubernetes環境にScalarDB Clusterを構築する際のノード設計と手順
- 6 本番稼働前に整理すべきライセンスコスト・運用負荷・チューニング方針の全体像
- 7 ScalarDB Cluster導入後の障害対応とスケールアウト時に見落とす注意点
異種DB環境でACIDを実現するScalarDB Clusterの基本構造と設計思想
マイクロサービスの普及に伴い、一つのシステム内にRDBとNoSQLが混在する構成は珍しくなくなりました。しかし、異なるデータベースをまたいだトランザクション整合性の確保は依然として難題です。ScalarDBは、多種多様なデータベースを統合するユニバーサルHTAP(Hybrid Transactional and Analytical Processing)エンジンであり、ACIDトランザクションとリアルタイム分析の両方を実現します。その中核コンポーネントであるScalarDB Clusterは、ScalarDB CoreライブラリをgRPCサーバーとしてラップし、複数ノードでクラスターを構成することで、分散環境でもデータ整合性を担保する設計になっています。本章では、ScalarDB Clusterがどのような背景から生まれ、どのような構造で動作するのかを基礎から整理します。
RDBとNoSQLが混在するシステムでデータ整合性が破綻する3つの典型パターン
異種データベース環境で整合性が壊れるパターンには、大きく3つの類型があります。第一に、マイクロサービスAがRDBに書き込み成功した直後に、マイクロサービスBのNoSQL書き込みが失敗し、補償トランザクションも不完全なまま中途半端な状態が残るケースです。第二に、NoSQLデータベース自体がACIDに対応していない、あるいは限定的にしか対応していないために、単一サービス内でもトランザクション境界を正しく設定できないケースがあります。CassandraやDynamoDBなどは軽量トランザクションをサポートしますが、複数パーティションにまたがる操作では整合性を保証しきれません。
第三のパターンは、Sagaパターンなどの補償トランザクションを自前で実装した結果、補償ロジックの複雑さが手に負えなくなるケースです。サービスが3つ以上関与するトランザクションでは、各サービスの失敗パターンごとにロールバック処理を記述する必要があり、テストケースも指数関数的に増加します。ScalarDB Clusterは、この問題をアプリケーション層ではなくミドルウェア層で解決することにより、開発チームが補償トランザクションのロジックを書く必要を根本的になくしています。
gRPCサーバーとしてScalarDB Coreをラップするクラスター構成の全体像
ScalarDB Clusterの構造は、アプリケーションとデータベースの間に位置するミドルウェアとして理解するのがもっとも正確です。アプリケーションはJava APIやSQLなどのインターフェースを通じてScalarDB Cluster にリクエストを送ります。ScalarDB Clusterの内部では、ScalarDB Coreライブラリが実際のトランザクション管理を担い、各クラスターノードがgRPCエンドポイントとしてリクエストを受け付けます。クラスターノードはさらに、ベンダー固有のプロトコルで下位のデータベース(MySQL、PostgreSQL、Cassandra、DynamoDBなど)と通信する構造です。
この3層構造により、アプリケーション開発者は下位データベースの種類を意識せず、統一されたAPIでトランザクション操作を記述できます。さらに、トランザクション層とストレージ層が分離されているため、それぞれを独立にスケールできる点も大きな設計上の特徴です。たとえば、トランザクション処理量が増えた場合はScalarDB Clusterのノード数を増やし、データ容量が増えた場合はデータベース側をスケールアウトするといった柔軟な運用が可能になります。
consensus-commitによるACIDトランザクション実現の仕組みと制約
ScalarDB Clusterの中核を成すトランザクションプロトコルは「consensus-commit」と呼ばれるものです。このプロトコルは、下位データベースが提供する条件付き書き込み(Compare-and-Swap的操作)を活用して、データベースの種類を問わずACID特性を実現します。具体的には、各レコードにトランザクションメタデータを付加し、コミット時にcoordinatorテーブルへの書き込みをもってトランザクションの成否を確定させる仕組みです。
ただし、この設計にはいくつかの制約があります。まず、各レコードにメタデータカラムが追加されるため、ストレージのオーバーヘッドが生じます。また、ストレージ非依存のトランザクションマネージャーであるがゆえに、特定データベースに最適化された分散SQLエンジン(CockroachDBやTiDBなど)と比較すると、単一データベースでの生のスループットでは不利になることがあります。一方で、既存の異種データベース資産をそのまま活かしながらACIDを後付けできるという点では、他のアプローチにない柔軟性を持っています。
Deuteronomy着想のストレージ非依存アーキテクチャがもたらす設計上の利点
ScalarDBのアーキテクチャは、Microsoft Researchが発表したDeuteronomyの論文(CIDR 2009, 2011)に着想を得ています。Deuteronomyの基本的な考え方は、トランザクション処理の論理層とストレージ層を完全に分離するというものです。この分離により、下位ストレージに一切の変更を加えることなく、トランザクション機能を上位から提供できます。ScalarDB Clusterはこの設計原則を忠実に実装しており、JDBCをサポートするRDB(MySQL、PostgreSQL、Oracle Database、SQL Server、MariaDB、SQLite、Amazon Aurora、YugabyteDB、TiDB、AlloyDBなど)からNoSQL(Apache Cassandra、Amazon DynamoDB、Azure Cosmos DB for NoSQLなど)まで幅広いデータベースに対応しています。
実務上の利点として、既存システムで稼働しているデータベースをそのまま流用できるため、データ移行コストが大幅に削減されます。たとえば、部門ごとに異なるデータベースを採用している大規模組織では、統合基盤を構築する際に全データベースを単一のNewSQLに移行するのではなく、ScalarDB Clusterをミドルウェアとして導入することで、既存データベースを活かしたまま横断的なトランザクション管理を実現できます。データベースベンダーへのロックインを回避しつつ、ACIDを確保できる点は、長期的なシステム運用を見据えた場合に大きなメリットとなります。
Jepsen・TLA+による正式検証を通過した信頼性の根拠と検証結果の読み方
分散トランザクションシステムを本番環境に導入する際、もっとも懸念されるのが「本当にACIDを保証できるのか」という点です。ScalarDBはこの懸念に対して、業界標準の2つの検証手法で信頼性を証明しています。第一にJepsen テストです。Jepsenは分散システムの正確性を検証するためのフレームワークで、ネットワーク分断やノード障害などのカオスを注入しながらデータの線形化可能性を検証します。ScalarDBのJepsenテストはScalar社自身が作成・実施し、結果はGitHub上で公開されています。
第二に、TLA+によるコミットプロトコルの形式検証です。TLA+はLeslie Lamportが開発した形式仕様記述言語で、consensus-commitプロトコルが仕様通りに動作することを数学的に証明しています。これらの検証結果を評価する際のポイントは、検証対象のバージョンと自社が導入するバージョンの一致を確認することです。また、Jepsenテストの対象データベースが自社環境と同一かどうかも確認すべきです。検証結果はGitHubリポジトリのtla+/consensus-commitディレクトリおよびscalar-labs/scalar-jepsenリポジトリで誰でも閲覧できます。
開発チームが知るべきScalarDB Cluster主要インターフェースと用途別選定基準
ScalarDB Clusterは複数のインターフェースを提供しており、開発チームの技術スタックやプロジェクトの要件に応じて最適な接続方法を選べます。ただし、すべてのインターフェースが同一のライセンス階層で利用できるわけではなく、Standard版とPremium版で利用範囲が異なります。この章では各インターフェースの特性を整理し、どの場面でどのインターフェースを選ぶべきかの判断材料を提供します。
Java API・gRPC・SQL・GraphQL・.NETの5種を機能で比較した対応表
ScalarDB Clusterが提供する主要インターフェースは、Java API、gRPC、SQL(JDBC経由)、GraphQL、.NET SDKの5種類です。それぞれの特性を正しく把握することが、技術選定の第一歩になります。なお、これらはすべてEnterprise版(ScalarDB Cluster)の機能であり、Community版(ScalarDB Core)はJava組み込みライブラリとしてのJava APIのみを提供します。
| インターフェース | ライセンス区分 | 主な用途 | トランザクション方式 | 言語/環境 |
|---|---|---|---|---|
| Java API | Enterprise Standard以上 | 低レベルCRUD操作 | 1PC / 2PC | Java(JVM) |
| gRPC | Enterprise Standard以上 | 言語非依存の通信 | 1PC / 2PC | 多言語(Go、Pythonなど) |
| SQL(JDBC) | Enterprise Premium | 宣言的クエリ操作 | 1PC / 2PC | Java(JDBC) |
| GraphQL | Enterprise Premium | フロントエンド連携 | 1PC | HTTP/GraphQL |
| .NET SDK | Enterprise Premium(プレビュー) | .NETアプリ統合 | 1PC / 2PC | C# / .NET |
Enterprise Standard版ではgRPCとJava APIが利用可能で、SQL、GraphQL、.NET SDKを利用するにはEnterprise Premium版のライセンスが必要です。プロジェクトの技術スタックがJava中心であればStandard版のJava APIで十分な場合が多いですが、チームに非Javaエンジニアが含まれる場合はgRPC APIを通じて任意の言語からアクセスできます。既存のSQLベースのORMを活用したい場合はPremium版のSQLインターフェースが有力な選択肢になります。
JDBC経由SQL接続を選ぶべきケースとSpring Data連携時の実装上の注意点
SQLインターフェースは、ScalarDB Clusterに対してJDBC経由でSQL文を発行できる機能です。既存のJDBCベースのアプリケーションを最小限の変更でScalarDB Clusterに接続したいケースや、Spring Frameworkを活用したプロジェクトでは、このインターフェースが最も生産性を高めます。接続設定ではscalar.db.sql.connection_mode=clusterプロパティを指定し、Envoy経由でClusterに接続するのが標準的な構成です。
Spring Data JDBC for ScalarDBを併用する場合、いくつかの注意点があります。まず、ScalarDB独自のスキーマ定義(namespace、パーティションキー、クラスタリングキーの指定)がSpring Dataの標準アノテーションだけでは表現しきれないため、追加の設定ファイルが必要になることがあります。また、スキーマのロードにはScalarDB専用のSchema LoaderまたはSQL CLIを使用する必要があり、Flywayなどの一般的なマイグレーションツールとの併用には工夫が求められます。導入前に、サンプルリポジトリ(scalardb-samples)のSpring Data JDBCサンプルを一通り動かして、自社の開発フローとの親和性を検証することを推奨します。
GraphQLインターフェースが有効な場面と自動スキーマ生成の制約事項
GraphQLインターフェースは、ScalarDB Clusterに登録されたテーブル定義から自動的にGraphQLスキーマを生成し、CRUD操作をGraphQLのクエリ・ミューテーションとして公開する機能です。フロントエンドチームがバックエンドのAPI開発を待たずにデータアクセスを開始できるため、開発の並行性を高められる場面で特に有効です。また、@transactionディレクティブを用いることで、複数のGraphQLリクエストにまたがるトランザクションも実行できます。
一方で、自動生成スキーマにはいくつかの制約があります。クラスタリングキーが存在しないテーブルにはscanフィールドが生成されません。また、ScalarDBのスキーマを変更した場合(テーブルの追加・変更・削除)、GraphQLスキーマはサーバー起動時に静的に構築されるため、変更が即座に反映されるわけではありません。この問題に対しては、定期的な自動チェック機能(デフォルト30秒間隔、scalar.db.graphql.schema_checking_interval_millisで設定可能)とオンデマンドの再構築機能(/update-graphql-schemaエンドポイントへのPOSTリクエスト)が用意されています。定期チェックが不要な場合は同プロパティを-1に設定して無効化することもできます。GraphiQLの設定はscalar.db.graphql.graphiql=trueがデフォルトで有効になっています。
indirect・direct-kubernetes両モードの性能差と使い分け基準
ScalarDB Clusterへの接続には、indirectモードとdirect-kubernetesモードの2種類があります。ただし、direct-kubernetesモードはJavaクライアントライブラリ専用の機能であり、非Java言語(gRPC APIを直接使用する場合)ではindirectモードのみ利用可能です。indirectモードは、ロードバランサー(通常Envoy)を経由してClusterに接続する方式です。アプリケーションがScalarDB Clusterとは別のKubernetesクラスターや外部環境で稼働している場合は、このモードを使います。設定はscalar.db.contact_points=indirect:<IP_ADDRESS>の形式で記述します。
一方、direct-kubernetesモードは、Javaアプリケーションが ScalarDB Clusterと同一のKubernetesクラスター上で稼働している場合に使用できる高性能な接続方式です。クライアントがKubernetes APIを使ってメンバーシップ情報を取得し、consistent hashingアルゴリズムによりトランザクション状態を保持する適切なクラスターノードに直接リクエストを送ります。ロードバランサーを経由しないぶんホップ数が削減され、レイテンシの改善が期待できます。ただし、このモードを使用するには、Role、RoleBinding、ServiceAccountの3つのKubernetesリソースを追加作成し、アプリケーションPodにServiceAccountをマウントする必要があります。Kubernetes APIへのアクセス権限(endpointsリソースのget/watch/list)が必要なため、セキュリティポリシーとの整合性を確認してから導入すべきです。パフォーマンス要件が厳しいJavaアプリケーションでは、まずindirectモードで動作確認を行い、次にdirect-kubernetesモードでベンチマークを取って比較検討する進め方が現実的です。
.NET SDK(プレビュー版)を採用する場合のリスク評価と後方互換性の確認方法
.NET SDKは、ScalarDB ClusterをC#/.NETアプリケーションから操作するためのクライアントライブラリです。分散トランザクション(1PC)およびTwo-Phase Commitインターフェース(2PC)の両方に対応しており、非同期メソッド(GetAsync、PutAsyncなど)を標準とした設計になっています。NuGetパッケージとして配布されており、ScalarDB Clusterと同一のメジャー・マイナーバージョンのSDKをインストールする必要があります。
ただし、現時点で.NET SDKはプレビュー版の段階にあり、公式ドキュメントにも将来のバージョンで後方互換性のない変更が入る可能性が明記されています。採用にあたっては、いくつかのリスクを評価する必要があります。具体的には、APIシグネチャの変更によるコード修正コスト、プレビュー期間中のサポート範囲の確認、プレビュー版から正式版への移行パスの有無が主な検討事項です。社内の.NETプロジェクトが小規模であればリスクを許容できますが、大規模な本番システムで採用する場合は、正式版リリースを待つか、Java API経由のgRPC接続で.NETアプリケーションから利用する中間的なアプローチも検討に値します。
ScalarDB CoreとCluster版の機能差で判断する商用ライセンス採用の条件
ScalarDBにはCommunity版(OSS)のCoreライブラリと、Enterprise版のCluster(Standard / Premium の2階層)が存在します。Community版はApache 2.0ライセンスで利用可能なJava組み込みライブラリですが、Enterprise版は商用ライセンスの取得が必要です。両者は同じScalarDBの基盤を共有しながらも、提供形態(組み込みライブラリ vs クラスタリングサーバー)や利用できるインターフェース、サポート範囲が大きく異なります。この章では、どのような条件下でEnterprise版の採用が合理的になるのかを具体的に整理します。
Core(OSS版)で利用できるgRPC・Java APIと商用版限定機能の範囲比較
ScalarDB Core(Community版)は、Apache 2.0ライセンスで提供されるJavaの組み込みライブラリです。アプリケーションにライブラリとして組み込んで使用し、Java APIを通じて分散トランザクション機能を直接利用できます。ただし、Community版はあくまでライブラリであり、クラスター化されたサーバーとしての機能は提供されません。ScalarDB Cluster(Enterprise版)はこのCore ライブラリをgRPCサーバーとしてラップし、クラスタリングやリクエストルーティングなどの本番運用に必要な機能を追加した構成です。
| 機能カテゴリ | Core(Community版) | Cluster(Enterprise Standard) | Cluster(Enterprise Premium) |
|---|---|---|---|
| Java API(組み込みライブラリ) | ○ | ○ | ○ |
| gRPCサーバー / クラスタリング | × | ○ | ○ |
| SQLインターフェース | × | × | ○ |
| GraphQLインターフェース | × | × | ○ |
| .NET SDK | × | × | ○(プレビュー) |
| Spring Data JDBC連携 | × | × | ○ |
| Scalar Admin連携 | × | ○ | ○ |
| リクエストルーティング | × | ○ | ○ |
| 商用サポート | × | ○ | ○ |
この比較から明らかなように、Community版とEnterprise版の差は「サーバー化・クラスタリング機能」「宣言的インターフェースの有無」「商用サポート」の3点に集約されます。Community版のJava APIはEnterprise版と共通の基盤を使用しているため、小規模な検証にはCommunity版で始め、本番運用に向けてEnterprise版に移行する段階的なアプローチも有効です。ただし、Community版はあくまで単一プロセス内での利用が前提であり、複数ノードへのスケーラビリティやgRPCによる多言語連携が必要な場合はEnterprise版が必須になります。
SQL・GraphQLなど宣言的インターフェースが必要になるプロジェクト規模の目安
SQLやGraphQLなどの宣言的インターフェースが求められるかどうかは、単純にプロジェクト規模だけで判断できるものではありません。しかし、いくつかの指標は判断材料になります。まず、開発チームの人数が10名を超え、全員がJava APIに精通しているわけではない場合、SQLインターフェースにより学習コストを下げる効果が期待できます。また、既存のSQLベースのツールやORMとの統合が必要なプロジェクトでは、Java APIで代替するとラッパーの自前実装が必要になり、工数が膨らむ傾向があります。
GraphQLインターフェースについては、フロントエンドとバックエンドの開発を並行して進めたいプロジェクト、またはBFF(Backend for Frontend)パターンを採用しているプロジェクトで特に有用です。自動生成されるGraphQLスキーマにより、バックエンドのAPI設計・実装を待たずにフロントエンド開発を開始できます。逆に、バッチ処理が中心のシステムや、サービス間通信がgRPCで完結しているシステムでは、宣言的インターフェースの恩恵は薄くなります。プロジェクト初期段階で「誰が」「どの言語・フレームワークで」「どのような操作を」行うのかを一覧化し、Enterprise StandardのgRPC / Java APIだけで無理なくカバーできるか、それともPremiumのSQL / GraphQLが必要かを検討することが、ライセンス判断の出発点になります。
商用ライセンスに含まれる管理ツール・Scalar Admin連携の運用メリット
ScalarDB Clusterの商用ライセンスには、Scalar Adminインターフェースとの連携機能が含まれています。Scalar Adminは、ScalarDB Clusterを一時停止(pause)する機能を提供し、これによりトランザクション的に一貫性のあるバックアップを取得できます。本番環境での運用では、データベースのバックアップはほぼ必須の要件ですが、分散トランザクションシステムのバックアップは通常のRDBのバックアップとは異なり、複数データベース間の整合性を保ったスナップショットを取得する必要があります。
Scalar Adminを使わずにバックアップを取得する場合、各データベースのバックアップタイミングを揃える独自の仕組みが必要になり、運用の複雑さとミスのリスクが大幅に増加します。特に、マルチストレージ構成でCassandraとMySQLを併用しているような環境では、両データベースのスナップショットの整合性を自前で保証するのは現実的に困難です。このような運用要件がある場合、Scalar Admin連携は商用ライセンスを選択する大きな理由になります。また、商用ライセンスには技術サポートへのアクセスが含まれるため、障害対応やチューニングの際に専門家の支援を受けられる点も、本番運用を見据えた場合の重要な判断材料です。
トライアルライセンスから本番契約へ移行する際のコスト構造と交渉で確認すべき項目
ScalarDB Clusterの導入を検討する際は、まずトライアルライセンスで検証を行い、その後本番ライセンスへ移行するのが一般的な流れです。トライアルライセンスの取得にはScalar社への問い合わせが必要で、検証期間や利用条件はプロジェクトごとに設定されます。本番契約に移行する際のコスト構造は公開情報が限られているため、以下の項目をベンダーとの交渉前に整理しておくことが重要です。
確認すべき項目としては、従量課金(Pay-As-You-Go)を利用するかBYOL契約を選ぶかという課金モデルの選択が第一です。AWS Marketplaceの従量課金ではPod稼働時間に基づく時間課金となり、商用ライセンスでは1Podあたり2vCPU / 4GBメモリという上限がある点にも注意が必要です。次に、Enterprise Standard版とPremium版の価格差と、自社が必要とする機能がどちらの階層に含まれるかを明確にします。さらに、サポートのSLA(応答時間、対応時間帯、緊急度区分)、ライセンスの更新条件(年次更新、複数年契約割引の有無)、スケールアウト時の追加コストも交渉時に確認すべきポイントです。PoCの段階で想定するPod数・ノード数を確定させておくと、見積もりの精度が上がります。
OSSのSagaパターン実装と比較した場合の開発工数削減効果の試算例
ScalarDB Clusterの商用ライセンス費用を正当化するうえで、最も説得力のある比較対象はCommunity版のScalarDB Core+自前Sagaパターン実装の場合の開発工数です。仮に3つのマイクロサービスにまたがるトランザクションをSagaパターンで実装する場合、各サービスの正常系処理に加え、サービスごとの補償トランザクション、各失敗パターンに対するリトライ・ロールバック処理、さらにそれらのテストケースが必要になります。3サービス構成でも補償パターンは数十に達し、テストケースは100を超えることが珍しくありません。
ScalarDB Clusterを導入した場合、補償トランザクションの実装は不要になり、トランザクション境界の定義とCRUD操作の記述だけで済みます。ある程度の粗い見積もりとして、3サービス構成のSagaパターン実装に4〜6人月を要すると仮定した場合、ScalarDB Clusterの導入により2〜3人月程度に圧縮できる可能性があります。さらに、障害パターンのテスト工数の削減、運用中のバグ修正コストの低減、補償トランザクションに起因するインシデント対応コストの回避まで含めると、中長期的なコスト削減効果はライセンス費用を十分に上回るケースが多いでしょう。試算の際は、自社の人月単価と想定されるサービス間トランザクションの複雑さを掛け合わせて具体的な数値を出すことが、稟議を通す際に有効です。
マイクロサービス間トランザクションにおける2PC対応とルーティング設計の実務指針
ScalarDB Clusterは、マイクロサービス間のトランザクションを実現するうえで、Two-Phase Commit(2PC)インターフェースを提供しています。モノリシックなアプリケーションであれば1フェーズコミットで十分ですが、複数のサービスがそれぞれ異なるトランザクションマネージャーインスタンスを持つマイクロサービス構成では、2PCの活用が現実的な選択肢になります。この章では、2PCの具体的な利用方法とルーティング設計のポイントを実務的な観点から解説します。
1フェーズコミットと2フェーズコミットを使い分けるアーキテクチャ判断の基準
ScalarDB Clusterでは、1フェーズコミット(1PC)と2フェーズコミット(2PC)の両方のインターフェースが利用可能です。判断基準は明確で、トランザクションが単一のトランザクションマネージャーインスタンス内で完結するなら1PC、複数のトランザクションマネージャーインスタンスにまたがるなら2PCを使います。実務的には、モノリシックアプリケーションや単一サービス内のトランザクションには1PCを、マイクロサービス間のトランザクションには2PCを採用するのが基本方針です。
ただし、「マイクロサービス構成だから必ず2PC」というわけではありません。たとえば、あるマイクロサービスが他のサービスのデータを直接操作せず、イベント駆動で非同期に連携している場合は、各サービスが独立したトランザクションを1PCで処理すれば十分なケースもあります。2PCを採用するのは、複数サービスのデータ操作がアトミックに成功・失敗する必要があるユースケースに限定すべきです。2PCはプロトコルの特性上、1PCと比較してレイテンシが増加し、コーディネーション障害時のリカバリも複雑になるため、必要な箇所にのみ適用するのが設計上のベストプラクティスです。
CoordinatorとParticipantの役割分担とトランザクションID受け渡し
2PCインターフェースでは、トランザクションの参加者にCoordinator(調整者)とParticipant(参加者)の2つの役割が存在します。Coordinatorはトランザクションを開始(begin)し、生成されたトランザクションIDをすべてのParticipantに送信します。各Participantはそのトランザクションに参加(join)し、それぞれのスコープでCRUD操作またはSQL操作を実行します。すべての操作が完了した後、Coordinator・Participant全員がprepare→validate→commitの3段階を経てトランザクションを確定させます。
実装上のポイントは、トランザクションIDの受け渡し方法です。マイクロサービス間でトランザクションIDを共有するには、gRPCのメタデータ、HTTPヘッダー、メッセージキューのペイロードなど、サービス間通信の仕組みに応じた方法を選択する必要があります。また、前のリクエストで開始・参加したトランザクションを後続のリクエストで再開(resume)する仕組みも提供されており、複数のリクエスト・レスポンスをまたぐトランザクションの実装が可能です。resumeメソッドはトランザクションオブジェクトの生成のみを行う同期処理であるため、非同期版は存在しない点にも注意が必要です。
prepare・validate・commitの3段階で発生しうるロールバック条件の整理
2PCのコミットプロセスは、prepare(準備)、validate(検証)、commit(確定)の3段階で構成されます。各段階で障害が発生した場合の対処ルールを正しく理解しておくことが、堅牢な実装の前提になります。prepareフェーズでCoordinatorまたはいずれかのParticipantが失敗した場合、全参加者でrollbackを実行する必要があります。validateフェーズでも同様に、いずれかの参加者が失敗すれば全参加者でrollbackを実行します。
commitフェーズの挙動はやや複雑です。CoordinatorまたはいずれかのParticipantがcommitに成功していれば、他の参加者がcommitに失敗していてもトランザクション全体は「コミット済み」として扱われます。この設計は、2PCプロトコルの特性上、prepare成功後のcommitは原則として成功する前提に基づいています。しかし、全参加者がcommitに失敗した場合は、全参加者でrollbackを実行する必要があります。これらの条件分岐を正しくハンドリングするために、例外処理のコードは慎重に設計する必要があり、公式ドキュメントの例外ハンドリングガイドを熟読してから実装に着手することを強く推奨します。
consistent hashingによるルーティングがホップ数削減に与える効果
ScalarDB Clusterでは、トランザクション状態が特定のクラスターノードに紐づくため、リクエストを正しいノードにルーティングする仕組みが重要になります。Javaクライアント専用のdirect-kubernetesモードでは、クライアントがconsistent hashingアルゴリズムを用いてトランザクション状態を保持するノードを特定し、直接リクエストを送信します。これにより、ロードバランサーがランダムにノードを選択した結果、転送(ホップ)が発生する事態を避けられます。
indirectモード(Envoy経由)では、リクエストがまずEnvoyに到達し、Envoyからいずれかのクラスターノードに振り分けられます。振り分け先が該当トランザクションの状態を持っていない場合、内部で適切なノードへの転送が発生し、ホップ数が増加します。2PCトランザクションのように複数のリクエスト・レスポンスを往復するケースでは、ホップ数の増加がレイテンシに直結するため、性能要件が厳しい場合はdirect-kubernetesモードの採用が合理的です。ただし、ホップ数削減の効果はトランザクションの頻度やパターンに依存するため、実際のワークロードに近いベンチマークで検証することが不可欠です。
gRPC・HTTP/1.1・ロードバランサー構成別に見るセッション維持の実装パターン
2PCトランザクションでは、1つのトランザクション内の複数リクエストが同一サーバーに到達することが前提となります。プロトコルやロードバランサーの構成によって、この前提を満たす方法が異なるため、自社のインフラ構成に合わせた実装パターンを選択する必要があります。gRPC接続の場合、クライアントサイドロードバランサーを使用すれば同一gRPC接続内のリクエストは同一サーバーに届きます。サーバーサイドのL3/L4ロードバランサーでも同様に、同一TCP接続内の通信は同一サーバーにルーティングされます。
問題が生じやすいのは、L7ロードバランサーを使用する場合です。L7ロードバランサーはリクエスト単位でルーティングを行うため、同一接続内でもリクエストが異なるサーバーに振り分けられる可能性があります。この場合、Cookieやカスタムヘッダーによるセッションアフィニティ(スティッキーセッション)の設定が必要です。HTTP/1.1接続でL3/L4ロードバランサーを使用する場合は、同一HTTP接続内のリクエストは同一サーバーに届きますが、L7ロードバランサーの場合はgRPCと同様の対策が必要になります。ScalarDB Clusterを採用する場合はこれらのルーティング課題をCluster自体が解決してくれるため、インフラ層の設計負荷を軽減できる点もCluster導入のメリットの一つです。
Kubernetes環境にScalarDB Clusterを構築する際のノード設計と手順
ScalarDB ClusterはKubernetes上での稼働を前提に設計されており、Helm Chartを使ったデプロイが標準的な導入方法です。ただし、適切なノード構成やリソース設計なしにデプロイすると、可用性やパフォーマンスの面で問題が生じます。この章では、本番環境を見据えたKubernetes構成の設計要件とデプロイの具体的な手順を整理します。
Helm Chart活用のClusterデプロイで最初に設定すべき5つのパラメータ
ScalarDB ClusterのKubernetesへのデプロイは、Scalar社が提供するHelm Chartを使って行います。Helm Chartのデフォルト設定はテスト環境向けであるため、本番環境ではいくつかのパラメータを明示的に調整する必要があります。最初に設定すべき5つのパラメータを以下に整理します。
- レプリカ数(replicaCount):高可用性のために最低3に設定する
- リソースリクエストとリミット:1Podあたり2vCPU / 4GBメモリのライセンス上限を踏まえ、requestsとlimitsを適切に設定する
- podAntiAffinityルール:各PodをそれぞれのワーカーノードおよびAZに分散させる設定を追加する
- ScalarDB Clusterノードの設定ファイル(scalardb-cluster-node.properties):下位データベースの接続情報、ストレージ設定、ライセンスキーを記述する
- ネットワーク設定:プライベートサブネット内での稼働を前提とし、Envoyサービスのtype(LoadBalancerまたはClusterIP)を環境に応じて設定する。なお、Javaアプリケーションでdirect-kubernetesモードを使用する場合はEnvoy Podのデプロイは不要
これらの設定を事前に確定させてからデプロイを開始することで、後から構成変更を行う手戻りを防げます。特にpodAntiAffinityとネットワーク設定は、デプロイ後の変更がPodの再スケジューリングを伴うため、最初から正しく設定しておくことが重要です。
ワーカーノード3台・Pod3台を最低構成とする高可用性設計の根拠とAZ分散の効果
ScalarDB Clusterの本番環境では、最低3台のワーカーノードに3つのPodを分散配置する構成が推奨されています。この「3」という数字には明確な根拠があります。まず、クラスターノードの1台が障害でダウンした場合でも、残り2台でサービスを継続できる冗長性を確保するためです。また、Kubernetesのローリングアップデート時にも、アップデート中のPodを除いて最低2台が稼働を維持できます。
さらに、ワーカーノードを異なるAvailability Zone(AZ)に配置することで、AZ単位の障害に対する耐性を獲得できます。podAntiAffinityの設定を適切に行うことで、KubernetesスケジューラーがPodを異なるノード・異なるAZに自動的に分散配置します。AKSを使用する場合は、Azure CNIネットワークプラグインの使用を検討する必要があります。デフォルトのkubenetでもCalico Network Policyを利用できますが、Azureサポートチームの公式サポート対象外であり、問題発生時はCalicoコミュニティまたは有償サポートに依存することになる点を考慮すべきです。
1Pod あたり2vCPU/4GBメモリのライセンス制約を踏まえたリソース設計の考え方
商用ライセンスでは、ScalarDB Clusterの1Podあたりのリソースが2vCPU / 4GBメモリに制限されています。このライセンス制約は、ノードのリソース設計に直接影響します。ScalarDB ClusterのPodに加えて、Kubernetesが各ワーカーノードにデプロイするシステムコンポーネント(kube-proxy、CoreDNSなど)やEnvoy Podのリソース消費も考慮に入れる必要があるため、ワーカーノード1台あたり最低4vCPU / 8GBメモリが推奨されています。
リソース設計で見落としやすいのが、スケーリング時のバッファです。Horizontal Pod Autoscaler(HPA)を利用する場合、負荷増加時に新しいPodがスケジュールされる余裕をワーカーノードに確保しておく必要があります。HPAでPodが5台まで増える設計であれば、5台のPodを配置できるだけのノードリソースを事前に用意するか、Cluster Autoscalerを併用してノード自体のスケールアウトも自動化する構成を採る必要があります。ただし、2vCPU / 4GBメモリの制約はライセンス上の上限であり、実際のワークロードに必要なリソースがこの上限よりも小さい場合は、requestsをそれに応じて設定してノードの集約効率を上げることも可能です。
Envoyを経由するロードバランサー構成とEXTERNAL-IP取得後の接続確認手順
ScalarDB Clusterへの外部接続は、Envoyプロキシを経由するのが標準構成です。Helm Chartでデプロイすると、scalardb-cluster-envoyという名前のServiceリソースが作成されます。このServiceのEXTERNAL-IPを取得するには、kubectl get svc scalardb-cluster-envoyコマンドを実行します。デフォルトのポートは60053で、管理API・トランザクションAPI・SQL API・一時停止操作のすべてがこのポートを通じて提供されます。
EXTERNAL-IPが取得できたら、クライアント側の設定ファイルで接続先を指定します。Java APIの場合はscalar.db.transaction_manager=clusterおよびscalar.db.contact_points=indirect:<EXTERNAL-IP>を設定します。SQL接続の場合はscalar.db.sql.connection_mode=clusterとscalar.db.sql.cluster_mode.contact_points=indirect:<EXTERNAL-IP>を設定します。接続確認には、Schema Loaderを使ってテスト用のスキーマを作成し、サンプルアプリケーションからトランザクションを実行するのが最も確実な方法です。EXTERNAL-IPがPendingのまま取得できない場合は、クラウドプロバイダーのロードバランサー割り当て状況やネットワークセキュリティグループの設定を確認してください。
HPAとCluster Autoscaler併用でスケーリングが誤動作する失敗パターン
HPAとCluster Autoscalerを併用してScalarDB ClusterのPodとノードの両方を自動スケールする構成は、理想的ではありますが設定を誤ると意図しない挙動を引き起こします。最も典型的な失敗パターンは、HPAがPodの増加をトリガーした際にCluster Autoscalerがノード追加を開始するものの、ノードの準備が完了する前にHPAのスケールアップタイムアウトに達してしまうケースです。この場合、HPAはスケーリングを断念し、再度負荷が閾値を超えるまでスケールアップを試みません。
この問題を回避するには、いくつかの対策があります。まず、HPAのスケールアップ安定化ウィンドウ(stabilizationWindowSeconds)を、Cluster Autoscalerのノード追加にかかる時間(通常2〜5分)よりも長く設定します。次に、ノードプールに一定の余剰リソースを持たせておくことで、Podのスケールアップ時にノード追加を待たずに済む構成にします。また、AKSを使用している場合は、システムノードプールとは別にScalarDB Cluster専用のユーザーモードノードプールを作成し、そのノードプール内でのみスケーリングが行われるように設定することが推奨されています。スケーリング設定の検証は、負荷テストツールで段階的に負荷を増加させ、Pod数・ノード数の変動を時系列で確認する方法が有効です。
本番稼働前に整理すべきライセンスコスト・運用負荷・チューニング方針の全体像
ScalarDB Clusterの技術的な検証が完了した後、本番稼働に向けて整理すべきは非機能要件の周辺事項です。ライセンスコストの見積もり、パフォーマンスチューニングのアプローチ、運用フロー の確立など、技術選定の段階では後回しにされやすい項目を本章で網羅的に整理します。
商用ライセンスの費用体系と年間コストをPoC段階で見積もるための確認項目
ScalarDB ClusterのEnterprise版はAWS MarketplaceおよびGCP Marketplaceで従量課金(Pay-As-You-Go)での利用が可能です。AWS Marketplaceの公開価格では、Standard版が約$1.40/時間、Premium版が約$2.79/時間となっています(2025年時点)。一方、BYOL(Bring Your Own License)形式での契約も可能で、この場合の価格はScalar社への問い合わせが必要です。PoC段階で正確なコスト見積もりを行うためには、事前にいくつかの情報を整理しておく必要があります。最も重要なのは、本番環境で想定するPod数です。商用ライセンスでは1Podあたりのリソース上限が定められているため、想定するトランザクション量とレイテンシ要件からPod数を逆算しておきます。
次に、必要なライセンス階層(Standard / Premium)を確定させます。SQLやGraphQLインターフェースが不要であればStandardで十分ですが、これらが必要な場合はPremiumの費用を見積もりに含める必要があります。また、開発環境・ステージング環境・本番環境のそれぞれでライセンスが必要かどうかも確認すべき点です。従量課金を利用する場合はPodの稼働時間が直接コストに影響するため、非本番環境では必要時のみ起動するなどのコスト最適化も検討材料になります。トライアルライセンスの期間中に本番相当の構成でベンチマークを取り、必要なPod数を確定させることが、正確な年間コスト見積もりへの最短ルートです。
slot_capacityとtimeout_millisの組み合わせで性能が変わる調整例
ScalarDB Clusterのパフォーマンスチューニングにおいて、グループコミット機能は注目すべき最適化オプションです。ただし、この機能はデフォルトでは無効化されており(scalar.db.consensus_commit.coordinator.group_commit.enabled=false)、明示的に有効化した場合にのみ関連パラメータが適用されます。有効化すると、coordinator.group_commit.slot_capacity(デフォルト: 20)とcoordinator.group_commit.group_size_fix_timeout_millis(デフォルト: 40ms)が重要な調整対象になります。slot_capacityはコミットグループの最大サイズを、group_size_fix_timeout_millisはグループが確定するまでの待機時間を制御します。なお、グループコミットはTwo-Phase Commitインターフェースとは併用できない制約がある点にも注意してください。
公式ドキュメントでは、デフォルト値に対して75%と125%のバリエーションでベンチマークを取ることが推奨されています。たとえば、slot_capacityのデフォルトが20であれば、15と25でも測定します。さらに重要なのは、これらのパラメータを組み合わせてベンチマークすることです。slot_capacity:20 / timeout:40ms、slot_capacity:30 / timeout:40ms、slot_capacity:20 / timeout:80msのように、複数のパラメータを組み合わせた網羅的な測定が必要です。また、グループコミット以外にも、並列実行(parallel_preparation、parallel_commit、parallel_validationなど)のオン・オフはデフォルトで有効になっており、これらもワークロードに応じた調整対象です。最適な値はアプリケーションのアクセスパターンと下位ストレージの特性に強く依存するため、自社のワークロードに近い条件で測定し、スループットとP99レイテンシの両方を評価指標として最適な組み合わせを特定してください。
multi-storage構成のnamespace_mapping誤設定で起きる不整合
ScalarDB Clusterのmulti-storage機能は、複数のデータベースをネームスペース単位でマッピングする設計です。たとえば、顧客情報をMySQLに、注文情報をCassandraに格納する場合、scalar.db.multi_storage.namespace_mapping=customer:mysql,order:cassandra,coordinator:cassandraのように設定します。この設定で特に注意が必要なのが、coordinatorネームスペースの配置先です。
coordinatorネームスペースには、トランザクションのコミット状態を管理するcoordinatorテーブルが格納されます。このテーブルが意図しないストレージに配置されたり、namespace_mappingから漏れたりすると、トランザクションの成否判定が正しく行われず、データ不整合が発生する恐れがあります。また、default_storageの設定を誤ると、namespace_mappingに明示されていないネームスペースのデータが想定外のストレージに格納されます。本番環境に適用する前に、すべてのネームスペースが正しいストレージにマッピングされていることをスキーマロード時に確認し、テスト用データを投入して各テーブルへの読み書きが期待どおりのストレージで行われることを検証する手順を運用フローに組み込んでおくべきです。
Scalar Adminを用いたトランザクション一貫バックアップの運用フロー
Scalar AdminはScalarDB Clusterを一時停止(pause)する機能を提供し、これを利用してトランザクション的に一貫性のあるバックアップを取得できます。通常の運用フローは以下の通りです。まずScalar Admin経由でScalarDB Clusterをpause状態にします。この間、新しいトランザクションの開始は保留され、進行中のトランザクションが完了するのを待ちます。全トランザクションが完了した時点で、下位データベースのスナップショットを取得します。
このバックアップ方式の利点は、複数のデータベースにまたがるデータの整合性をトランザクションレベルで保証できる点です。たとえば、MySQLとCassandraの両方に書き込むトランザクションが進行中の状態でバックアップを取得してしまうと、リストア時にデータ不整合が発生しますが、pause機能を使えばこの問題を回避できます。バックアップの頻度や保持期間、リストア手順のテストは事前に定義し、定期的にリストアテストを実施して復旧手順が正しく機能することを確認しておくことが、本番運用の信頼性を担保する上で不可欠です。自動化する場合は、CronJobでpause→スナップショット→resumeの一連の処理をスクリプト化する構成が一般的です。
cross-partition scanのSERIALIZABLE利用時のリスクと回避策
ScalarDB Clusterでは、cross-partition scan(パーティションをまたぐスキャン操作)が利用可能ですが、使用する分離レベルによっては注意が必要です。特に、JDBC以外のデータベース(Cassandra、DynamoDBなど)でSERIALIZABLE分離レベルを有効にしたcross-partition scanを使用する場合、実際にはSNAPSHOTレベルで実行される可能性があると公式ドキュメントで明記されています。
この制約は、非JDBCデータベースのストレージ層がSERIALIZABLEレベルのスキャン操作をネイティブにサポートしていないことに起因します。したがって、データの一貫性が厳密に要求されるトランザクションでは、非JDBCデータベースでのcross-partition scanの使用は推奨されていません。回避策としては、パーティションキーを適切に設計してcross-partition scanの必要性を最小化する方法が第一です。また、一貫性が重要なデータについてはJDBCデータベース(MySQL、PostgreSQLなど)に格納し、SERIALIZABLEレベルのcross-partition scanをJDBCデータベース上でのみ実行する設計も有効です。multi-storage構成を活かして、データの一貫性要件に応じたストレージの使い分けを行うことが、この問題への現実的な対処法になります。
ScalarDB Cluster導入後の障害対応とスケールアウト時に見落とす注意点
ScalarDB Clusterの導入が完了し本番稼働が始まった後、運用チームが直面する課題の多くは障害対応とスケーリングに関するものです。分散トランザクションシステム特有の障害パターンを事前に把握し、対応手順を整備しておくことが、安定稼働の鍵になります。この章では、運用フェーズで頻出する課題とその対処法をパターン別に整理します。
クラスターノード障害時のトランザクション状態復旧とリトライ処理の実装指針
ScalarDB Clusterのノードが障害でダウンした場合、そのノードが保持していたトランザクション状態への影響を正しく理解しておく必要があります。進行中のトランザクション(未コミット)は、ノード障害によりタイムアウトし、最終的にアボートされます。コミット済みのトランザクションは、coordinatorテーブルにコミット状態が記録されているため、ノード障害による影響を受けません。
アプリケーション側での対処として最も重要なのは、適切なリトライ処理の実装です。ScalarDBのトランザクションは、コンフリクトや一時的な障害により失敗する可能性があるため、リトライロジックは必須の設計要素です。リトライ時には、失敗したトランザクション全体を最初からやり直す(begin→CRUD操作→commit)のが基本パターンです。部分的なリトライ(commitだけ再実行するなど)は、トランザクションの状態不整合を引き起こす恐れがあるため避けるべきです。リトライ回数の上限は、ワークロードの特性に応じて3〜5回程度に設定し、上限を超えた場合はエラーログに記録してアラートを発報する運用が標準的です。公式の例外ハンドリングガイドに従い、例外の種別ごとにリトライすべきかどうかを判定する処理を実装してください。
Pod増設時のconsistent hashing再分散でレイテンシが増加する原因と対処
ScalarDB ClusterのPod数を増やした場合、consistent hashingのリングにおけるキー空間の再分散が発生します。再分散中は、一部のトランザクションリクエストが新旧のノード間で転送される頻度が一時的に上がり、レイテンシの増加として観測されることがあります。この現象は特に、Javaクライアント専用のdirect-kubernetesモードでクライアント側のメンバーシップ情報が更新されるまでの間に顕著になります。
対処法としては、いくつかのアプローチがあります。まず、スケールアウトのタイミングをトラフィックの少ない時間帯に設定することで、再分散の影響を受けるトランザクション数を最小化できます。次に、HPAによる急激なスケールアウト(一度に複数Podを追加)ではなく、段階的なスケールアウトを行うことで、再分散の範囲を限定できます。また、クライアント側でメンバーシップ情報のキャッシュ更新間隔を短く設定することで、新しいノード構成への切り替えを高速化できます。スケールアウト後のレイテンシが安定するまでの時間を事前に測定しておき、SLAのバッファとして考慮に入れておくことが運用設計上のベストプラクティスです。
GraphQLスキーマの自動再構築タイミングとテーブル変更が反映されない場合の確認手順
GraphQLインターフェースを利用している場合、ScalarDBのスキーマ変更がGraphQLスキーマに反映されるタイミングに注意が必要です。GraphQLスキーマはサーバー起動時に静的に構築されるため、テーブルの追加・変更・削除を行っても自動的には反映されません。この問題に対して、ScalarDB Clusterは2つのメカニズムを提供しています。第一に、定期的な自動チェック機能です。設定された間隔でScalarDBスキーマの変更を検知し、変更があればGraphQLスキーマを自動再構築します。
第二に、オンデマンドの再構築機能です。/update-graphql-schemaエンドポイントにPOSTリクエストを送信することで、任意のタイミングでGraphQLスキーマの再構築をトリガーできます。テーブル変更後にGraphQLスキーマが更新されない場合の確認手順としては、まずscalar.db.graphql.schema_checking_interval_millisの値を確認します(デフォルトは30,000ms=30秒)。間隔が長すぎる場合は一時的に短縮するか、/update-graphql-schemaへのPOSTリクエストで即時再構築を実行します。次に、ScalarDB側のスキーマ変更が正しく適用されているかをSchema LoaderまたはSQL CLIで確認します。スキーマ変更自体が失敗している場合は、GraphQLスキーマの更新も行われません。GraphiQL(デフォルトで有効)のDocumentation Explorerで、生成されたクエリ・ミューテーションを確認し、期待するテーブルの操作が利用可能かどうかを検証してください。
AZ障害を想定したpodAntiAffinityルール設計と復旧時間の見積もり方法
AZ障害への耐性は、podAntiAffinityルールの設計によって大きく左右されます。ScalarDB Clusterの推奨構成では、requiredDuringSchedulingIgnoredDuringExecutionの設定でPodを異なるノードに分散させ、さらにtopologyKeyにAZを指定することでAZ間の分散を実現します。3台のPodを3つの異なるAZに配置していれば、1つのAZが完全にダウンしても残り2台でサービスを継続できます。
復旧時間の見積もりにおいては、いくつかの要素を考慮する必要があります。まず、AZ障害を検知してからKubernetesがNodeのNotReady状態を判定するまでの時間(デフォルトで40秒程度)があります。次に、NotReady判定後にPodがEvictされ、別のAZのノードで再スケジュールされるまでの時間があります。Cluster Autoscalerが有効な場合は、新しいノードのプロビジョニング時間(2〜5分)も加わります。これらを合計すると、AZ障害発生からサービスが完全に3台構成に復旧するまでに5〜10分程度を見込む必要があります。ただし、残存する2台のPodでサービス自体は継続しているため、エンドユーザーへの影響はPodの処理能力低下(約33%減)に留まるのが通常です。
100ノード規模クラスターのベンチマーク結果に見るスケーラビリティ90%達成の条件
ScalarDBのスケーラビリティは、Cassandraをバックエンドとした100ノード規模のベンチマークで検証されています。このベンチマークでは、3ノードクラスターの性能を基準として、100ノードクラスターで理論上の線形スケーリング(100/3倍)に対して約90%のスケーラビリティを達成したと報告されています。ベンチマーク環境は各ノードがi3.4xlarge(16 vCPU、122GB RAM、1900GB NVMe SSD × 2)で、レプリケーションファクター3の構成です。
この90%というスケーラビリティを自社環境で再現するための条件を理解しておくことが重要です。まず、下位ストレージのスケーラビリティ自体が前提となります。Cassandraのように水平スケーリングに優れたデータベースを使用している場合はScalarDBのスケーラビリティも高くなりますが、RDB(MySQLやPostgreSQLの単一インスタンス)をバックエンドとする場合はストレージ層がボトルネックになります。また、ワークロードの特性(読み取り中心か書き込み中心か、ホットキーの有無など)もスケーラビリティに大きく影響します。自社の本番ワークロードに近い条件で小規模(3〜10ノード)のベンチマークを実施し、ノード追加に伴うスループットの伸び率を確認してから、スケーリング計画を策定する進め方が推奨されます。