Écritures

Cette page répertorie les types de requêtes d'écriture que vous pouvez envoyer à Bigtable, et indique dans quels cas les utiliser ou non.

L'API Bigtable Data et les bibliothèques clientes vous permettent d'écrire des données dans vos tables de manière automatisée. Bigtable renvoie une réponse ou un accusé de réception pour chaque écriture.

Chaque bibliothèque cliente offre la possibilité d'envoyer les types de requêtes d'écriture suivants :

  • Écritures simples
  • Incréments et ajouts
  • Écritures conditionnelles
  • Écritures par lot

Les bibliothèques clientes Bigtable disposent d'une fonctionnalité intégrée de nouvelles tentatives d'exécution intelligentes pour les écritures simples et par lot, ce qui signifie qu'elles gèrent les indisponibilités temporaires de manière fluide. Par exemple, si votre application tente d'écrire des données et rencontre une panne ou un problème de réseau temporaires, elle procède automatiquement à une nouvelle tentative d'exécution, jusqu'à ce que l'écriture soit effective ou que l'échéance de la requête soit atteinte. Cette résilience fonctionne à la fois avec les instances à cluster unique et les instances répliquées, avec un routage à cluster unique ou un routage multicluster.

Pour les opérations d'écriture par lot et en flux continu, vous pouvez utiliser le [connecteur Bigtable Beam Pour en savoir plus, consultez la section Écritures par lot.

Pour en savoir plus sur les limites qui s'appliquent aux requêtes d'écriture, consultez la section Quotas et limites.

Des exemples de chaque type d'écriture sont disponibles pour chaque bibliothèque cliente Cloud Bigtable.

Pour en savoir plus sur l'ajout de données à des cellules agrégées, consultez Valeurs agrégées au moment de l'écriture (Aperçu).

Types d'écritures et cas d'utilisation

Toutes les requêtes d'écriture incluent les composants de base suivants :

  • Le nom de la table sur laquelle écrire
  • Un ID de profil d'application, qui indique à Bigtable comment acheminer le trafic
  • Une ou plusieurs mutations. Une mutation se compose des quatre éléments suivants :
    • Nom de la famille de colonnes
    • Le qualificatif de colonne
    • Code temporel
    • La valeur que vous écrivez dans la table.

Le code temporel d'une mutation possède la valeur par défaut de la date et de l'heure actuelles, mesurée comme le temps écoulé depuis l'epoch Unix, soit le 1er janvier 1970 à 00:00:00 UTC.

Un horodatage que vous envoyez à Bigtable doit être une valeur de l'ordre de la microseconde avec une précision maximale de la milliseconde. Un horodatage d'une précision de l'ordre de la microseconde, tel que 3023483279876543, est refusé. Dans cet exemple, la valeur d'horodatage acceptable est 3023483279876000.

Toutes les mutations d'une même requête d'écriture ont le même horodatage, sauf si vous les remplacez. Vous pouvez définir l'horodatage de toutes les mutations d'une requête d'écriture pour qu'elles soient identiques ou différentes les unes des autres.

Écritures simples

Vous pouvez écrire une seule ligne dans Bigtable à l'aide d'une requête MutateRow incluant le nom de la table, l'ID du profil d'application à utiliser, une clé de ligne et jusqu'à 100 000 mutations pour cette ligne. Une écriture sur une seule ligne est atomique. Utilisez ce type d'écriture lorsque vous effectuez plusieurs mutations sur une seule ligne.

Pour obtenir des exemples de code montrant comment envoyer des requêtes d'écriture simples, consultez la section Effectuer une écriture simple.

Cas pour lesquels les écritures simples ne sont pas recommandées

Les écritures simples ne sont pas le meilleur moyen d'écrire des données pour les cas d'utilisation suivants :

  • Lorsque vous écrivez un lot de données qui aura des clés de ligne contiguës. Dans ce cas, il est recommandé d'utiliser des écritures par lot plutôt que des écritures simples consécutives, car un lot contigu peut être appliqué dans un seul appel de backend.

  • Lorsque vous souhaitez un débit élevé (en lignes par seconde ou octets par seconde) et n'avez pas besoin d'une latence faible. Les écritures par lot seront plus rapides dans ce cas.

Incréments et ajouts

Dans de nombreux cas, l'utilisation d'agrégats (Preview), qui vous permettent de mettre à jour une valeur au moment de l'écriture, constitue la meilleure option lorsque vous souhaitez augmenter ou incrémenter une valeur. Toutefois, les agrégats ne sont pas compatibles avec les opérations d'ajout. Pour en savoir plus, consultez la section Valeurs agrégées au moment de l'écriture.

Si vous souhaitez ajouter des données à une valeur existante ou si vous devez incrémenter une valeur numérique existante et que vous ne pouvez pas utiliser d'agrégations, vous pouvez envoyer une requête ReadModifyWriteRow. Cette requête inclut le nom de la table, l'ID du profil d'application à utiliser, une clé de ligne et un ensemble de règles à utiliser lors de l'écriture des données. Chaque règle inclut le nom de la famille de colonnes, le qualificatif de colonne, ainsi qu'une valeur d'ajout ou un montant d'incrément.

Les règles sont appliquées dans l'ordre. Par exemple, si votre requête inclut une requête d'incrémentation de la valeur d'une colonne de deux, et qu'une règle ultérieure comprise dans la même requête incrémente cette même colonne de un, la colonne est incrémentée de trois dans cette écriture atomique unique. La règle ultérieure ne remplace pas la règle précédente.

Une valeur ne peut être incrémentée que si elle est codée sous la forme d'un entier signé en mode big-endian de 64 bits. Bigtable procède à l'incrémentation d'une valeur vide, ou qui n'existe pas, comme si la valeur était zéro. Les requêtes ReadModifyWriteRow sont atomiques. Si elles échouent pour une raison quelconque, elles ne peuvent pas faire l'objet de nouvelles tentatives d'exécution.

Pour obtenir des exemples de code montrant comment ajouter une valeur dans une cellule, consultez la section Incrémenter une valeur existante.

Dans quels cas ne pas utiliser ReadModifyWriteRow ?

Vous ne devez pas envoyer de requêtes ReadModifyWriteRow dans les situations suivantes:

  • Votre cas d'utilisation peut être traité à l'aide d'agrégations (Preview).

  • Lorsque vous utilisez un profil d'application comportant un routage multicluster.

  • Lorsque vous utilisez plusieurs profils d'application comportant un seul cluster et que vous envoyez des écritures susceptibles d'entrer en conflit avec des données écrites sur la même ligne et la même colonne dans d'autres clusters de l'instance. Avec le routage à un seul cluster, une requête d'écriture est envoyée à un seul cluster, puis répliquée.

  • Lorsque vous vous basez sur la fonctionnalité de nouvelles tentatives d'exécution intelligentes fournie par les bibliothèques clientes. Les incréments et les ajouts ne peuvent pas faire l'objet de nouvelles tentatives d'exécution.

  • Lorsque vous écrivez de grandes quantités de données et que vous avez besoin que ces écritures soient effectives rapidement. Une requête qui lit, puis modifie une ligne est plus lente qu'une requête d'écriture simple. En conséquence, ce type d'écriture ne constitue généralement pas la meilleure approche à grande échelle. Par exemple, si vous souhaitez comptabiliser des éléments se chiffrant en millions, comme les pages vues, vous devez utiliser des agrégations pour mettre à jour vos décomptes au moment de l'écriture. Vous pouvez également envisager d'enregistrer chaque vue en tant qu'écriture simple plutôt que d'incrémenter une valeur, puis d'utiliser une tâche Dataflow pour agréger les données.

Écritures conditionnelles

Si vous souhaitez rechercher une condition dans une ligne, puis, en fonction du résultat, écrire des données dans cette ligne, envoyez une requête CheckAndMutateRow. Ce type de requête comprend une clé de ligne et un filtre de ligne. Un filtre de ligne est un ensemble de règles utilisé pour vérifier la valeur des données existantes. Les mutations ne sont ensuite attribuées à des colonnes spécifiques de la ligne que lorsque certaines conditions, vérifiées par le filtre, sont remplies. Ce processus de vérification puis d’écriture s'effectue en une seule action atomique.

Une requête de filtre doit inclure au moins l'un de ces types de mutations :

  • Les vraies mutations, à appliquer si le filtre renvoie une valeur
  • Les fausses mutations, qui sont appliquées si le filtre ne renvoie rien

Vous pouvez fournir jusqu'à 100 000 mutations de chaque type (vraies et fausses) en une seule écriture, et vous devez en envoyer au moins une. Bigtable envoie une réponse lorsque toutes les mutations sont terminées.

Pour obtenir des exemples de code montrant comment envoyer des écritures conditionnelles, consultez la section Écrire une valeur de manière conditionnelle.

Cas pour lesquels les écritures conditionnelles ne sont pas recommandées

Vous ne pouvez pas utiliser les écritures conditionnelles dans les cas suivants :

  • Lorsque vous utilisez un profil d'application comportant un routage multicluster.

  • Lorsque vous utilisez plusieurs profils d'application comportant un seul cluster et que vous envoyez des écritures susceptibles d'entrer en conflit avec des données écrites sur la même ligne et la même colonne dans d'autres clusters de l'instance. Avec le routage à un seul cluster, une requête d'écriture est envoyée à un seul cluster, puis répliquée.

Écritures par lot

Vous pouvez écrire plusieurs lignes avec un seul appel à l'aide d'une requête MutateRows. Les requêtes MutateRows contiennent un ensemble de 100 000 entrées au maximum, chacune appliquée de manière atomique. Chaque entrée se compose d'une clé de ligne et d'au moins une mutation à appliquer à la ligne. Une requête d'écriture par lot peut contenir jusqu'à 100 000 mutations réparties sur toutes les entrées. Par exemple, une écriture par lot peut inclure l'une des permutations suivantes :

  • 100 000 entrées avec une mutation dans chaque entrée
  • Une entrée avec 100 000 mutations
  • 1 000 entrées avec 100 mutations chacune

Chaque entrée d'une requête MutateRows est atomique, mais la requête dans son ensemble ne l'est pas. Si nécessaire, Bigtable relance toutes les entrées du lot qui n'aboutissent pas, jusqu'à ce que toutes les écritures aient abouti ou que le délai de la requête soit atteint. Il renvoie ensuite une réponse identifiant chaque écriture dans le lot et indiquant si l'écriture a réussi ou non.

Pour obtenir des exemples de code montrant comment envoyer des écritures par lot, consultez la page Effectuer des écritures par lot.

Cas pour lesquels les écritures par lot ne sont pas recommandées

  • Lorsque vous écrivez des données groupées sur des lignes qui ne sont pas proches les unes des autres. Bigtable stocke les données de manière lexicographique par clé de ligne, l'équivalent binaire de l'ordre alphabétique. Par conséquent, lorsque les clés de ligne d'une requête ne sont pas similaires, Bigtable les traite de manière séquentielle, et non en parallèle. Le débit sera élevé, mais le temps de latence le sera également. Pour éviter cela, utilisez MutateRows lorsque les clés de ligne sont similaires afin que Bigtable écrive des lignes proches les unes des autres. Utilisez MutateRow, ou les écritures simples, pour les lignes qui ne sont pas à proximité les unes des autres.

  • Lorsque vous demandez plusieurs mutations sur une même ligne. Dans ce cas, vous obtiendrez de meilleures performances si vous effectuez toutes les mutations dans une seule requête d'écriture simple. En effet, dans une écriture simple, toutes les modifications sont appliquées dans une seule action atomique, tandis qu'une écriture par lot force à sérialiser les mutations sur la même ligne, ce qui entraîne une latence.

Contrôle de flux d'écriture par lot

Si vous envoyez vos écritures par lot à l'aide de l'un des outils suivants, vous pouvez activer le contrôle de flux d'écriture par lot dans votre code.

Lorsque le contrôle de flux d'écriture par lot est activé pour une tâche Dataflow, Bigtable effectue automatiquement les opérations suivantes :

  • Limite le débit du trafic pour éviter de surcharger votre cluster Bigtable
  • Il garantit que le cluster est sous une charge suffisante pour déclencher l'autoscaling Bigtable (s'il est activé), afin que davantage de nœuds soient automatiquement ajoutés au cluster en cas de besoin

Ces actions combinées empêchent la surcharge du cluster et l'échec des tâches. Vous n'avez pas besoin de faire évoluer manuellement votre cluster en anticipant l'exécution de l'écriture par lot. Lorsque le contrôle de flux est activé, le scaling du cluster s'effectue pendant la tâche Dataflow plutôt qu'avant celle-ci. Par conséquent, la tâche peut prendre plus de temps que si vous effectuiez le scaling manuel de votre cluster.

Vous devez utiliser un profil d'application configuré pour le routage vers un cluster unique. L'activation de l'autoscaling Bigtable pour le cluster de destination n'est pas obligatoire, mais l'autoscaling vous permet de tirer pleinement parti du contrôle du flux d'écriture par lot. Vous pouvez utiliser l'autoscaling de Dataflow comme vous le feriez pour n'importe quelle autre tâche.

Pour en savoir plus sur l'autoscaling Bigtable, consultez la page Autoscaling. Pour comprendre les règles de routage du profil d'application, consultez Présentation des profils d'application.

Pour obtenir un exemple de code montrant comment activer le contrôle de flux d'écriture par lot à l'aide du connecteur Bigtable HBase Beam, consultez la section Écrire dans Bigtable.

Écrire des données dans une vue autorisée

Pour écrire des données dans une vue autorisée, vous devez utiliser l'un des éléments suivants:

  • gcloud CLI
  • Client Bigtable pour Java

Les autres bibliothèques clientes Bigtable ne sont pas encore compatibles avec l'accès aux vues autorisées.

Lorsque vous écrivez des données dans une vue autorisée, vous devez fournir l'ID de la vue autorisée en plus de l'ID de la table.

Toutes les écritures dans une vue autorisée sont directement appliquées à la table sous-jacente.

Limites de la définition des vues autorisées

Dans une vue autorisée, les lignes ou les colonnes dans lesquelles vous pouvez écrire des données sont limitées par la définition de la vue autorisée. En d'autres termes, vous ne pouvez écrire que dans les lignes et les colonnes qui répondent aux mêmes critères que ceux spécifiés pour la vue autorisée.

Par exemple, si la vue autorisée est définie par le préfixe de clé de ligne examplepetstore1, vous ne pouvez pas écrire de données à l'aide de la clé de ligne examplepetstore2. Le début de la valeur de clé de ligne doit inclure la chaîne complète examplepetstore1.

De même, si la vue autorisée est définie par le préfixe de qualificatif de colonne order-phone, vous pouvez écrire des données à l'aide du qualificatif de colonne order-phone123, mais vous ne pouvez pas utiliser le qualificatif de colonne order-tablet.

Votre requête d'écriture ne peut pas non plus référencer de données en dehors de la vue autorisée, par exemple lorsque vous vérifiez une valeur dans une requête d'écriture conditionnelle.

Pour toute requête qui écrit ou référence des données en dehors de la vue autorisée, un message d'erreur PERMISSION_DENIED est renvoyé.

Réplication

Lorsqu'un cluster d'une instance répliquée reçoit une écriture, celle-ci est immédiatement répliquée sur les autres clusters de l'instance.

Atomicité

Chaque requête MutateRows que vous envoyez à une instance répliquée est validée en tant qu'action atomique unique sur le cluster vers lequel la requête est acheminée. Lorsque l'écriture est répliquée sur les autres clusters de l'instance, ces clusters reçoivent chacun l'écriture sous la forme d'une opération atomique. Les clusters ne reçoivent pas de mutations partielles. Une mutation réussit ou échoue de manière atomique pour toutes les cellules qu'elle modifie.

Cohérence

Le délai nécessaire avant que les données écrites soient disponibles dépend de plusieurs facteurs, tels que le nombre de clusters dans votre instance et le type de routage utilisé par votre profil d'application. Avec une instance à un seul cluster, les données peuvent être lues immédiatement, mais si une instance dispose de plusieurs clusters, et qu'elle utilise alors la réplication, Bigtable est cohérent à terme. Vous pouvez obtenir une cohérence de type "lecture de vos écritures" en acheminant les requêtes vers un même cluster.

Vous pouvez créer et utiliser un jeton de cohérence, puis appeler CheckConsistency en mode StandardReadRemoteWrites après avoir envoyé des requêtes d'écriture. Le jeton vérifie la cohérence de la réplication. En général, vous créez un jeton de cohérence après l'envoi d'un lot d'écritures ou après un certain intervalle, par exemple une heure. Vous pouvez ensuite transmettre le jeton pour qu'il soit utilisé par un autre processus, tel qu'un module effectuant une requête de lecture, qui utilise le jeton pour vérifier que toutes les données ont été répliquées avant de tenter de lire.

Si vous utilisez un jeton juste après sa création, quelques minutes peuvent être nécessaires pour vérifier la cohérence lors de sa première utilisation. Ce délai est dû au fait que chaque cluster vérifie tous les autres afin de s'assurer qu'il ne reste plus de données qui arrivent. Après la première utilisation, ou si vous attendez plusieurs minutes pour utiliser le jeton pour la première fois, le jeton réussit immédiatement sa vérification à chaque utilisation.

Résolution de conflits

Chaque valeur de cellule d'une table Bigtable est identifiée de manière unique par le quatre-tuple (clé de ligne, famille de colonnes, qualificatif de colonne, horodatage). Pour en savoir plus sur ces identifiants, consultez la section Modèle de stockage de Bigtable. Dans les rares cas où deux écritures avec exactement le même quatre-tuple sont envoyées à deux clusters différents, Bigtable résout automatiquement le conflit à l'aide d'un algorithme interne qui stipule que la dernière écriture l'emporte, en se basant sur l'heure du serveur. La mise en œuvre de "la dernière écriture l'emporte" de Bigtable est déterministe. Lorsque la réplication rattrape le retard, tous les clusters ont la même valeur pour le quatre-tuple.

Étapes suivantes