ScalarDB JDBC を使用して共有 ScalarDB Cluster 環境でマイクロサービストランザクションをサポートするアプリケーションを作成する
このページは英語版のページが機械翻訳されたものです。英語版との間に矛盾または不一致がある場合は、英語版を正としてください。
このチュートリアルでは、マイクロサービストランザクションをサポートし、ScalarDB JDBC を使用して ScalarDB Cluster の共有クラスタパターンに従うサンプル電子商取引アプリケーションの作成方法について説明します。
共有クラスタパターンの詳細については、マイクロサービスにおける ScalarDB Cluster のデプロイパターンを参照してください。
サンプルマイクロサービスアプリケーションの概要
サンプル電子商取引アプリケーションでは、ユーザーがクレジットラインを使用してアイテムを注文し、支払いを行う方法を示します。
サンプルアプリケーションには、database-per-service パターンに基づく Customer Service と Order Service という2つのマイクロサービスがあります。
- Customer Service は、クレジットライン情報、クレジット制限、クレジット合計を含む顧客情報を管理します。
- Order Service は、注文の配置や注文履歴の取得などの注文操作を担当します。
各サービスには gRPC エンドポイントがあります。クライアントはエンドポイントを呼び出し、サービスも各エンドポイントを呼び出します。
サンプルアプリケーションで使用するデータベースは Cassandra と MySQL です。Customer Service と Order Service は、ScalarDB Cluster を通じてそれぞれ Cassandra と MySQL を使用します。

図に示すように、ScalarDB Cluster には、Consensus Commit プロトコルに使用される小さなコーディネータデータベースがあります。データベースはサービスに依存せず、可用性の高い方法で Consensus Commit のトランザクションメタデータを管理するために存在します。
サンプルアプリケーションでは、セットアップと説明を簡単にするために、コーディネータデータベースを Order Service の同じ Cassandra インスタンスに共同配置します。また、コーディネータデータベースを別のデータベースとして管理することもできます。
サンプルアプリケーションの焦点は ScalarDB Cluster の使用を実演することであるため、アプリケーション固有のエラー処理、認証処理、および同様の機能はサンプルアプリケーションには含まれていません。
サービスエンドポイント
サービスで定義されているエンドポイントは次のとおりです。
-
Customer Service
getCustomerInfopaymentrepayment
-
Order Service
placeOrdergetOrdergetOrders
このサンプルアプリケーションでできること
サンプルアプリケーションは、次のタイプのトランザクションをサポートします。
- Customer Service の
getCustomerInfoエンドポイントを通じて顧客情報を取得します。 - Order Service の
placeOrderエンドポイントと Customer Service のpaymentエンドポイントを使用してクレジットラインを使用して注文します。- 注文のコストが顧客のクレジット制限を下回っているかどうかを確認します。
- チェックに合格した場合、注文履歴を記録し、顧客が使用した金額を更新します。
- Order Service の
getOrderエンドポイントと Customer Service のgetCustomerInfoエンドポイントを通じて注文 ID で注文情報を取得します。 - Order Service の
getOrdersエンドポイントと Customer Service のgetCustomerInfoエンドポイントを通じて顧客 ID で注文情報を取得します。 - Customer Service の
repaymentエンドポイントを通じて支払いを行います。- 顧客が使用した金額を減らします。
getCustomerInfo エンドポイントは、コーディネータからトランザクション ID を受信するときにパーティシパントサービスエンドポイントとして機能します。
前提条件
- 以下のいずれかの Java Development Kit (JDK):
- Oracle JDK: 8、11、17、または 21 (LTS バージョン)
- OpenJDK ディストリビューション (Eclipse Temurin、Amazon Corretto、または Microsoft Build of OpenJDK): 8、11、17、または 21 (LTS バージョン)
- Docker 20.10 以降と Docker Compose V2 以降
上記の LTS バージョンの使用をお勧めしますが、他の非 LTS バージョンでも機能する可能性があります。
また、他の JDK も ScalarDB で動作するはずですが、テストしていません。
また、ScalarDB Cluster のライセンスキー (試用版ライセンスまたは商用ライセンス) が必要です。ライセンスキーをお持ちでない場合は、お問い合わせください。
ScalarDB Cluster のセットアップ
次のセクションでは、ScalarDB Cluster でマイクロサービストランザクションをサポートするサンプルアプリケーションをセットアップする方法について説明します。
ScalarDB サンプルリポジトリのクローン
ターミナルを開いて、次のコマンドを実行して ScalarDB サンプルリポジトリをクローンします。
git clone https://github.com/scalar-labs/scalardb-samples
次に、以下のコマンドを実行して、サンプルアプリケーションを含むディレクトリに移動します。
cd scalardb-samples/microservice-transaction-sample-with-shared-cluster-with-jdbc/
ライセンスキーの設定
ScalarDB Cluster デプロイメント用のライセンスキー (試用版ライセンスまたは商用ライセンス) を設定ファイル scalardb-cluster-node.properties に設定します。詳細については、ライセンスキーの設定方法を参照してください。
Cassandra、MySQL、および ScalarDB Cluster の起動
ScalarDB Cluster の設定ファイルは scalardb-cluster-node.properties です。
設定に示されているように、Cassandra と MySQL はすでにマ ルチストレージ設定で設定されています。ScalarDB でマルチストレージトランザクション機能を設定する詳細については、マルチストレージトランザクションをサポートするように ScalarDB を設定する方法を参照してください。
このサンプルアプリケーションを迅速にセットアップするために、ScalarDB Cluster をスタンドアロンモードで実行します。スタンドアロンモードでの ScalarDB Cluster の実行の詳細については、ScalarDB Cluster スタンドアロンモードを参照してください。
また、各マイクロサービスのアクセス制御を実装するために、ScalarDB Auth が有効になっています。ScalarDB Auth の詳細については、ユーザーの認証と認可 を参照してください。
このサンプルアプリケーションを迅速にセットアップするために、ワイヤ暗号化は有効になっていません。ただし、本番環境では、クライアントと ScalarDB Cluster ノード間、および ScalarDB Cluster ノード間の通信を保護するためにワイヤ暗号化を有効にすることをお勧めします。ワイヤ暗号化の詳細については、ワイヤ通信の暗号化を参照してください。
サンプルアプリケーション用の Docker コンテナに含まれている Cassandra、MySQL、および ScalarDB Cluster を開始するには、次のコマンドを実行します。
docker compose up -d mysql cassandra scalardb-cluster-node
開発環境によっては、Docker コンテナの起動に1分以上かかる場合があります。
スキーマの読み込み
サンプルアプリケーションのデータベーススキーマ (データがどのように整理されるかの方法) は、すでに schema.sql で定義されています。
スキーマを適用するには、ScalarDB のリリースに移動し、使用する ScalarDB Cluster のバージョンの SQL CLI ツール (scalardb-cluster-sql-cli-<VERSION>-all.jar) をダウンロードします。
次に、ダウンロードした SQL CLI ツールのバージョンと <VERSION> を置き換えて、次のコマンドを実行します。
java -jar scalardb-cluster-sql-cli-<VERSION>-all.jar --config scalardb-cluster-sql-cli.properties --file schema.sql
スキーマの詳細
サンプルアプリケーションの schema.sql に示されているように、Customer Service のすべてのテーブルは customer_service 名前空間に作成されます。
customer_service.customers: 顧客情報を管理するテーブルcredit_limit: 貸し手がクレジットラインを使用するときに各顧客が使用できる最大金額credit_total: 各顧客がクレジットラインを使用してすでに使用した金額
また、Order Service のすべてのテーブルは order_service 名前空間に作成されます。
order_service.orders: 注文情報を管理するテーブルorder_service.statements: 注文明細書情報を管理するテーブルorder_service.items: 注文するアイテムの情報を管理するテーブル
スキーマのエンティティ関係図は次のとおりです。

サービスのユーザーを作成し、権限 を付与する
各マイクロサービスのアクセス制御を実装するには、サービスのユーザーを作成し、権限を付与する必要があります。
ダウンロードした SQL CLI ツールのバージョンと <VERSION> を置き換えて、次のコマンドを実行します。
java -jar scalardb-cluster-sql-cli-<VERSION>-all.jar --config scalardb-cluster-sql-cli.properties --file user-privileges.sql
user-privileges.sql に示されているように、Customer Service と Order Service のユーザーを作成し、権限を付与します。
マイクロサービスの開始
Customer Service と Order Service の設定ファイルは、それぞれ customer-service.properties と order-service.properties です。
マイクロサービスを開始する前に、次のコマンドを実行してサンプルアプリケーションの Docker イメージをビルドします。
./gradlew docker
次に、以下のコマンドを実行してマイクロサービスを開始します。
docker compose up -d customer-service order-service
マイクロサービスを開始し、初期データが読み込まれた後、次のレコードが customer_service.customers テーブルに保存されているはずです。
| customer_id | name | credit_limit | credit_total |
|---|---|---|---|
| 1 | Yamada Taro | 10000 | 0 |
| 2 | Yamada Hanako | 10000 | 0 |
| 3 | Suzuki Ichiro | 10000 | 0 |
また、次のレコードが order_service.items テーブルに保存されているはずです。
| item_id | name | price |
|---|---|---|
| 1 | Apple | 1000 |
| 2 | Orange | 2000 |
| 3 | Grape | 2500 |
| 4 | Mango | 5000 |
| 5 | Melon | 3000 |
サンプルアプリケーションでのトランザクションの実行とデータの取得
次のセクションでは、サンプル電子商取引アプリケーションでトランザクションを実行し、データを取得する方法について説明します。
顧客情報の取得
まず、次のコマンドを実行して、ID が 1 の顧客に関する情報を取得します。
./gradlew :client:run --args="GetCustomerInfo 1" -q
次の出力が表示されます。
{
"id": 1,
"name": "Yamada Taro",
"creditLimit": 10000
}
この時点では、credit_total は表示されません。これは、credit_total の現在の値が 0 であることを意味します。
注文の配置
次に、以下のコマンドを実行して、顧客 ID 1 にリンゴ3個とオレンジ2個の注文をします。
このコマンドの注文形式は ./gradlew run --args="PlaceOrder <CUSTOMER_ID> <ITEM_ID>:<COUNT>,<ITEM_ID>:<COUNT>,..." です。
./gradlew :client:run --args="PlaceOrder 1 1:3,2:2" -q
注文が成功したことを確認する order_id の UUID が異なる、以下のような出力が表示されます。
{
"orderId": "2dab1af1-a008-45b2-92e3-f30ff2a4ae3e"
}
注文詳細の確認
前のコマンドを実行した後に表示された order_id の UUID と <ORDER_ID_UUID> を置き換えて、次のコマンドを実行して注文の詳細を確認します。
./gradlew :client:run --args="GetOrder <ORDER_ID_UUID>" -q
order_id と timestamp の UUID が異なる、以下のような出力が表示されます。
{
"order": {
"orderId": "2dab1af1-a008-45b2-92e3-f30ff2a4ae3e",
"timestamp": "1708566933602",
"customerId": 1,
"customerName": "Yamada Taro",
"statement": [{
"itemId": 1,
"itemName": "Apple",
"price": 1000,
"count": 3,
"total": 3000
}, {
"itemId": 2,
"itemName": "Orange",
"price": 2000,
"count": 2,
"total": 4000
}],
"total": 7000
}
}
別の注文の配置
次のコマンドを実行して、顧客 ID 1 の credit_total の残り金額を使用してメロン1個の注文をします。
./gradlew :client:run --args="PlaceOrder 1 5:1" -q
注文が成功したことを確認する order_id の UUID が異なる、以下のような出力が表示されます。
{
"orderId": "abc6ed14-ac3d-4d4c-9a83-7fa0e70c1d4e"
}
注文履歴の確認
次のコマンドを実行して、顧客 ID 1 のすべての注文の履歴を取得します。
./gradlew :client:run --args="GetOrders 1" -q
タイムスタンプの降順で顧客 ID 1 のすべての注文の履歴を示す、order_id と timestamp の UUID が異なる以下のような出力が表示されます。
{
"order": [{
"orderId": "2dab1af1-a008-45b2-92e3-f30ff2a4ae3e",
"timestamp": "1708566933602",
"customerId": 1,
"customerName": "Yamada Taro",
"statement": [{
"itemId": 1,
"itemName": "Apple",
"price": 1000,
"count": 3,
"total": 3000
}, {
"itemId": 2,
"itemName": "Orange",
"price": 2000,
"count": 2,
"total": 4000
}],
"total": 7000
}, {
"orderId": "abc6ed14-ac3d-4d4c-9a83-7fa0e70c1d4e",
"timestamp": "1708566978052",
"customerId": 1,
"customerName": "Yamada Taro",
"statement": [{
"itemId": 5,
"itemName": "Melon",
"price": 3000,
"count": 1,
"total": 3000
}],
"total": 3000
}]
}