Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Recommandations pour les QLDB chauffeurs Amazon
Important
Avis de fin de support : les clients existants pourront utiliser Amazon QLDB jusqu'à la fin du support le 31 juillet 2025. Pour plus de détails, consultez Migrer un Amazon QLDB Ledger vers Amazon Aurora SQL Postgre
Cette section décrit les meilleures pratiques en matière de configuration et d'utilisation du QLDB pilote Amazon pour toutes les langues prises en charge. Les exemples de code fournis sont spécifiques à Java.
Ces recommandations s'appliquent à la plupart des cas d'utilisation courants, mais une solution unique ne convient pas à tous. Utilisez les recommandations suivantes comme bon vous semble pour votre application.
Rubriques
Configuration de l' QldbDriver objet
L'QldbDriver
objet gère les connexions à votre registre en gérant un pool de sessions qui sont réutilisées dans les transactions. Une session représente une connexion unique au registre. QLDBprend en charge une transaction active par session.
Important
Pour les anciennes versions du pilote, la fonctionnalité de regroupement de sessions se trouve toujours dans l'PooledQldbDriver
objet au lieu deQldbDriver
. Si vous utilisez l'une des versions suivantes, remplacez toute mention de QldbDriver
par PooledQldbDriver
dans le reste de cette rubrique.
Pilote | Version |
---|---|
Java | 1.1.0 ou plus tôt |
.NET | 0.1.0-beta |
Node.js | 1.0.0-rc.1 ou plus tôt |
Python | 2.0.2 ou plus tôt |
L'PooledQldbDriver
objet est obsolète dans la dernière version des pilotes. Nous vous recommandons de passer à la dernière version et de convertir toutes les instances de PooledQldbDriver
versQldbDriver
.
Configuration QldbDriver en tant qu'objet global
Pour optimiser l'utilisation des pilotes et des sessions, assurez-vous qu'une seule instance globale du pilote existe dans votre instance d'application. Par exemple, en Java, vous pouvez utiliser des frameworks d'injection de dépendances tels que SpringQldbDriver
en tant que singleton.
@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(); }
Configurer les tentatives de nouvelle tentative
Le conducteur réessaie automatiquement les transactions lorsque des exceptions transitoires courantes (telles que SocketTimeoutException
ouNoHttpResponseException
) se produisent. Pour définir le nombre maximal de tentatives, vous pouvez utiliser le maxRetries
paramètre de l'objet de transactionRetryPolicy
configuration lors de la création d'une instance deQldbDriver
. (Pour les anciennes versions du pilote répertoriées dans la section précédente, utilisez le retryLimit
paramètre dePooledQldbDriver
.)
La valeur par défaut de maxRetries
est 4
.
Erreurs côté client, telles que l'impossibilité InvalidParameterException
de réessayer. Lorsqu'elles se produisent, la transaction est abandonnée, la session est renvoyée au pool et l'exception est renvoyée au client du pilote.
Configurer le nombre maximum de sessions et de transactions simultanées
Le nombre maximum de sessions de registre utilisées par une instance de QldbDriver
pour exécuter des transactions est défini par son maxConcurrentTransactions
paramètre. (Pour les anciennes versions du pilote répertoriées dans la section précédente, cela est défini par le poolLimit
paramètre dePooledQldbDriver
.)
Cette limite doit être supérieure à zéro et inférieure ou égale au nombre maximum de HTTP connexions ouvertes autorisé par le client de session, tel que défini par le spécifique AWS SDK. Par exemple, en Java, le nombre maximum de connexions est défini dans l'ClientConfigurationobjet.
La valeur par défaut de maxConcurrentTransactions
est le paramètre de connexion maximal de votre AWS SDK.
Lorsque vous configurez le QldbDriver
dans votre application, tenez compte des considérations de dimensionnement suivantes :
-
Votre pool doit toujours comporter au moins autant de sessions que le nombre de transactions simultanées que vous prévoyez d'avoir.
-
Dans un modèle multithread où un thread de supervision délègue aux threads de travail, le pilote doit avoir au moins autant de sessions que le nombre de threads de travail. Sinon, au pic de charge, les threads feront la queue pour une session disponible.
-
La limite de service des sessions actives simultanées par registre est définie dansQuotas et limites sur Amazon QLDB. Assurez-vous de ne pas configurer plus que cette limite de sessions simultanées à utiliser pour un seul registre pour tous les clients.
Réessayer des exceptions
Lorsque vous réessayez d'effectuer des exceptions survenant dansQLDB, tenez compte des recommandations suivantes.
Réessayer OccConflictException
Des exceptions de conflit liées au contrôle de simultanéité optimiste (OCC) se produisent lorsque les données auxquelles la transaction accède ont changé depuis le début de la transaction. QLDBlance cette exception lors de la tentative de validation de la transaction. Le pilote tente de nouveau la transaction autant de fois que cela maxRetries
est configuré.
Pour plus d'informations OCC et les meilleures pratiques relatives à l'utilisation des index afin de limiter OCC les conflits, consultezModèle de QLDB simultanéité Amazon.
Réessayer d'autres exceptions en dehors de QldbDriver
Pour réessayer une transaction en dehors du pilote lorsque des exceptions personnalisées définies par l'application sont émises pendant l'exécution, vous devez encapsuler la transaction. Par exemple, en Java, le code suivant montre comment utiliser la bibliothèque 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; }
Note
Réessayer une transaction en dehors du QLDB driver a un effet multiplicateur. Par exemple, si elle QldbDriver
est configurée pour réessayer trois fois et que la logique de nouvelle tentative personnalisée tente également trois fois, la même transaction peut être réessayée jusqu'à neuf fois.
Rendre les transactions idempotentes
Il est recommandé de rendre vos transactions d'écriture idempotentes afin d'éviter tout effet secondaire inattendu en cas de nouvelle tentative. Une transaction est idempotente si elle peut être exécutée plusieurs fois et produire des résultats identiques à chaque fois.
Pour en savoir plus, veuillez consulter la section Modèle de QLDB simultanéité Amazon.
Optimisation des performances
Pour optimiser les performances lorsque vous exécutez des transactions à l'aide du pilote, tenez compte des points suivants :
-
L'
execute
opération effectue toujours au moins troisSendCommand
API appels àQLDB, y compris les commandes suivantes :-
StartTransaction
-
ExecuteStatement
Cette commande est invoquée pour chaque instruction partiQL que vous exécutez dans le
execute
bloc. -
CommitTransaction
Tenez compte du nombre total d'APIappels effectués lorsque vous calculez la charge de travail globale de votre application.
-
-
En général, nous recommandons de commencer par un rédacteur à fil unique et d'optimiser les transactions en regroupant plusieurs instructions au sein d'une seule transaction. Maximisez les quotas relatifs à la taille des transactions, à la taille des documents et au nombre de documents par transaction, comme défini dansQuotas et limites sur Amazon QLDB.
-
Si le traitement par lots n'est pas suffisant pour des charges de transactions importantes, vous pouvez essayer le multithreading en ajoutant des rédacteurs supplémentaires. Cependant, vous devez examiner attentivement les exigences de votre demande en matière de séquençage des documents et des transactions et la complexité supplémentaire que cela entraîne.
Exécution de plusieurs relevés par transaction
Comme décrit dans la section précédente, vous pouvez exécuter plusieurs instructions par transaction afin d'optimiser les performances de votre application. Dans l'exemple de code suivant, vous interrogez une table, puis vous mettez à jour un document de cette table dans le cadre d'une transaction. Pour ce faire, transmettez une expression lambda à l'execute
opération.
L'execute
opération du pilote démarre implicitement une session et une transaction au cours de cette session. Chaque instruction que vous exécutez dans l'expression lambda est intégrée à la transaction. Une fois toutes les instructions exécutées, le pilote valide automatiquement la transaction. Si une instruction échoue une fois la limite de tentatives automatique épuisée, la transaction est abandonnée.
Propager les exceptions dans une transaction
Lorsque vous exécutez plusieurs relevés par transaction, nous vous déconseillons généralement de détecter et d'avaler les exceptions au sein de la transaction.
Par exemple, en Java, le programme suivant détecte n'importe quelle instance deRuntimeException
, enregistre l'erreur et continue. Cet exemple de code est considéré comme une mauvaise pratique car la transaction réussit même en cas d'échec de l'UPDATE
instruction. Le client peut donc supposer que la mise à jour a réussi alors que ce n'est pas le cas.
Avertissement
N'utilisez pas cet exemple de code. Il est fourni pour montrer un exemple d'anti-modèle considéré comme une mauvaise pratique.
// 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.");
}
Propagez plutôt l'exception (bulle vers le haut). Si une partie de la transaction échoue, laissez l'execute
opération abandonner la transaction afin que le client puisse gérer l'exception en conséquence.