翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
Amazon QLDBドライバーのレコメンデーション
重要
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了QLDBまで Amazon を使用できます。詳細については、「Amazon Ledger QLDB を Amazon Aurora Postgre に移行するSQL
このセクションでは、サポートされている言語の Amazon QLDBドライバーを設定および使用するためのベストプラクティスについて説明します。提供されているコード例は Java 専用です。
これらの推奨事項は、ほとんどの一般的なユースケースに適用されますが、1 つのサイズがすべてのサイズに適合するとは限りません。アプリケーションに適した以下の推奨事項を使用してください。
QldbDriver オブジェクトの設定
この QldbDriver
は、トランザクション間で再利用されるセッションのプールを維持することによって、台帳への接続を管理します。セッションは、台帳との 1 つの接続を表します。QLDB は、セッションごとに 1 つのアクティブに実行されているトランザクションをサポートします。
重要
古いドライバーバージョンのセッションプール機能は、現在も、QldbDriver
ではなく PooledQldbDriver
にあります。次のいずれかのバージョンを使用している場合、このトピックに記載の QldbDriver
は、PooledQldbDriver
に置き換えてください。
ドライバー | Version |
---|---|
Java | 1.1.0 以前 |
.NET | 0.1.0-beta |
Node.js | 1.0.0-rc.1 以前 |
Python | 2.0.2 以前 |
PooledQldbDriver
オブジェクトは、ドライバーの最新バージョンでは廃止されています。最新バージョンにアップグレードして、PooledQldbDriver
のすべてのインスタンスを QldbDriver
に変換することをお勧めします。
グローバルオブジェクト QldbDriver として を設定する
ドライバーとセッションの使用を最適化するには、アプリケーションインスタンスにドライバーのグローバルインスタンスが 1 つのみあるようにします。例えば Java では、SpringQldbDriver
をシングルトンとして設定する方法を示しています。
@Singleton public QldbDriver qldbDriver (AWSCredentialsProvider credentialsProvider, @Named(LEDGER_NAME_CONFIG_PARAM) String ledgerName) { QldbSessionClientBuilder builder = QldbSessionClient.builder(); if (null != credentialsProvider) { builder.credentialsProvider(credentialsProvider); } return QldbDriver.builder() .ledger(ledgerName) .transactionRetryPolicy(RetryPolicy .builder() .maxRetries(3) .build()) .sessionClientBuilder(builder) .build(); }
再試行を設定する
ドライバーは、一般的な一時例外 (SocketTimeoutException
や NoHttpResponseException
など) が発生すると、自動的にトランザクションを再試行します。QldbDriver
のインスタンスを作成するときに transactionRetryPolicy
設定オブジェクトの maxRetries
パラメータを使用すると、最大再試行回数を設定できます。(前のセクションで説明した古いドライバーバージョンの場合は、PooledQldbDriver
の retryLimit
パラメータを使用します)。
maxRetries
の初期値は 4
です。
InvalidParameterException
などのクライアント側のエラーは再試行できません。これらが発生すると、トランザクションが中止され、セッションがプールに戻され、例外がドライバーのクライアントにスローされます。
同時セッションと同時トランザクションの最大数を設定する
トランザクションを実行する QldbDriver
インスタンスによって使用される台帳セッションの最大数は、その maxConcurrentTransactions
パラメータで定義します。(前のセクションで説明した古いドライバーバージョンの場合は、PooledQldbDriver
の poolLimit
パラメータで定義します)。
この制限は 0 より大きく、特定の で定義されているように、セッションクライアントが許可するオープンHTTP接続の最大数以下である必要があります AWS SDK。例えば、Java では、 ClientConfiguration オブジェクトで接続の最大数を設定します。
のデフォルト値maxConcurrentTransactions
は、 の最大接続設定です AWS SDK。
アプリケーションで QldbDriver
を設定するときは、スケーリングに関する以下の点を考慮してください。
-
プールには常に、同時に実行する予定のトランザクションの数と同数以上のセッションが必要です。
-
スーパバイザースレッドがワーカースレッドに委任するマルチスレッドモデルでは、そのドライバーにワーカースレッドの数と同数以上のセッションが必要です。それ以外の場合、ピーク負荷時に、スレッドはセッションが使用可能になるまで待機中になります。
-
台帳ごとの同時アクティブセッションのサービス制限は、「Amazon のクォータと制限 QLDB」で定義されています。すべてのクライアントで 1 つの台帳に使用される同時セッションの数は、この制限を超えないように設定してください。
例外発生時の再試行
で発生した例外を再試行する場合はQLDB、次の推奨事項を考慮してください。
で再試行する OccConflictException
オプティミスティック同時実行制御 (OCC) の競合例外は、トランザクションがアクセスしているデータがトランザクションの開始後に変更されたときに発生します。QLDB は、トランザクションのコミット中にこの例外をスローします。ドライバーは、maxRetries
に設定されている回数だけトランザクションを再試行します。
インデックスを使用してOCC競合を制限する方法の詳細OCCとベストプラクティスについては、「」を参照してくださいAmazon QLDB 同時実行モデル。
の外部で他の例外を再試行する QldbDriver
アプリケーション定義のカスタム例外が実行中にスローされたときにこのドライバーの外部でトランザクションを再試行するには、トランザクションをラップする必要があります。例えば、Java では、次のコードは Reslience4J
private final RetryConfig retryConfig = RetryConfig.custom() .maxAttempts(MAX_RETRIES) .intervalFunction(IntervalFunction.ofExponentialRandomBackoff()) // Retry this exception .retryExceptions(InvalidSessionException.class, MyRetryableException.class) // But fail for any other type of exception extended from RuntimeException .ignoreExceptions(RuntimeException.class) .build(); // Method callable by a client public void myTransactionWithRetries(Params params) { Retry retry = Retry.of("registerDriver", retryConfig); Function<Params, Void> transactionFunction = Retry.decorateFunction( retry, parameters -> transactionNoReturn(params)); transactionFunction.apply(params); } private Void transactionNoReturn(Params params) { try (driver.execute(txn -> { // Transaction code }); } return null; }
注記
QLDB ドライバーの外部でトランザクションを再試行すると、乗数効果があります。例えば、QldbDriver
が 3 回再試行するように設定されていて、カスタム再試行ロジックも 3 回再試行する場合、同じトランザクションを最大 9 回再試行できます。
トランザクションをべき等にする
ベストプラクティスとして、再試行の場合に予期しない結果を避けるために、書き込みトランザクションをべき等にしてください。トランザクションは、複数回実行して毎回同じ結果を生成できる場合、idempotent です。
詳細については、「Amazon QLDB 同時実行モデル」を参照してください。
パフォーマンスの最適化
このドライバーを使用してトランザクションを実行するときにパフォーマンスを最適化するには、以下の点を考慮してください。
-
execute
オペレーションは、次のコマンドを含むQLDB、常に に対して最低 3 回のSendCommand
API呼び出しを行います。-
StartTransaction
-
ExecuteStatement
このコマンドは、
execute
ブロックで実行する PartiQL ステートメントごとに呼び出されます。 -
CommitTransaction
アプリケーションの全体的なワークロードを計算するときに行われるAPI呼び出しの合計数を考慮してください。
-
-
一般的に、シングルスレッドのライターから始め、1 つのトランザクション内で複数のステートメントをバッチ処理することでトランザクションを最適化することをお勧めします。「Amazon のクォータと制限 QLDB」で定義されているように、トランザクションサイズ、ドキュメントサイズ、トランザクションごとのドキュメント数のクォータを最大に設定します。
-
大量のトランザクション負荷に対してバッチ処理では不十分な場合は、ライターを追加してマルチスレッドを試すことができます。ただし、ドキュメントとトランザクションの順序付けに関するアプリケーション要件と、これにより生じる複雑さを慎重に検討する必要があります。
トランザクションごとに複数のステートメントを実行する
前のセクションで説明したように、トランザクションごとに複数のステートメントを実行して、アプリケーションのパフォーマンスを最適化できます。次のコード例では、トランザクション内で、テーブルをクエリし、そのテーブルのドキュメントを更新しています。そのために、Lambda 式を execute
オペレーションに渡しています。
ドライバーの execute
オペレーションは、セッションとそのセッション内のトランザクションを暗黙で開始します。Lambda 式で実行する各ステートメントは、トランザクションでラップされます。すべてのステートメントが実行されると、ドライバーはトランザクションを自動的にコミットします。自動的な再試行の制限を超えたためにステートメントが失敗すると、トランザクションは中止されます。
トランザクションでの例外の伝播
トランザクションごとに複数のステートメントを実行する場合、通常、トランザクション内で例外をキャッチして続行することはお勧めしません。
たとえば、Java の場合、次のプログラムは RuntimeException
のインスタンスをキャッチしてエラーをログに記録し、続行します。このコード例は、UPDATE
ステートメントが失敗してもトランザクションが成功するため、推奨されません。クライアントは、更新が失敗しても成功したと思い込む可能性があります。
警告
このコード例は、使用しないでください。これは、推奨されない悪いパターンの例として提供されています。
// DO NOT USE this code example because it is considered bad practice
public static void main(final String... args) {
ConnectToLedger.getDriver().execute(txn -> {
final Result selectTableResult = txn.execute("SELECT * FROM Vehicle WHERE VIN ='123456789'");
// Catching an error inside the transaction is an anti-pattern because the operation might
// not succeed.
// In this example, the transaction succeeds even when the update statement fails.
// So, the client might assume that the update succeeded when it didn't.
try {
processResults(selectTableResult);
String model = // some code that extracts the model
final Result updateResult = txn.execute("UPDATE Vehicle SET model = ? WHERE VIN = '123456789'",
Constants.MAPPER.writeValueAsIonValue(model));
} catch (RuntimeException e) {
log.error("Exception when updating the Vehicle table {}", e.getMessage());
}
});
log.info("Vehicle table updated successfully.");
}
その代わりに例外を伝播 (バブルアップ) します。トランザクションのいずれかの部分が失敗した場合は、execute
オペレーションにトランザクションを中止させて、クライアントが適切に例外を処理できるようにします。