Gestion des versions des objets et contrôle de simultanéité

Présentation

Les buckets pour lesquels la gestion des versions est activée gèrent les versions d'objets obsolètes. Ils vous permettent d'annuler la suppression des données que vous avez accidentellement supprimées ou de récupérer d'anciennes versions de vos données. Vous pouvez activer ou désactiver à tout moment la gestion des versions pour un bucket. Si vous désactivez la gestion des versions, les versions existantes de l'objet sont conservées et entraînent simplement la suppression de la version active existante de l'objet chaque fois qu'une nouvelle version est importée.

Que vous ayez activé ou non la gestion des versions sur un bucket, chaque objet est associé à deux champs d'entiers positifs :

  • La génération, qui est mise à jour lorsqu'un nouvel objet remplace un objet existant portant le même nom.
  • La métagénération, qui identifie la génération de métadonnées. Sa valeur est initialement égale à 1 et augmente à chaque fois que les métadonnées (par exemple, LCA ou Content-Type) d'une génération de contenu donnée sont mises à jour. Cette propriété est réinitialisée lors de la modification du numéro de génération.

Parmi ces deux entiers, seule la génération est utilisée lorsque vous exploitez des données avec des versions gérées. La génération et la métagénération peuvent être utilisées avec le contrôle de simultanéité (décrit dans une section ultérieure).

Pour gérer les versions d'objets dans gsutil, vous pouvez utiliser un type d'URL de stockage qui intègre la génération d'objets, que nous appelons des URL spécifiques à une version. Par exemple, l'URL d'objet sans version :

gs://bucket/object

peut disposer de deux versions, avec les URL spécifiques suivantes :

gs://bucket/object#1360383693690000
gs://bucket/object#1360383802725000

Les sections suivantes décrivent comment utiliser la gestion des versions et le contrôle de simultanéité.

Gestion des versions des objets

Vous pouvez afficher, activer et désactiver la gestion des versions d'objets sur un bucket à l'aide des commandes "versioning get" et "versioning set". Exemple :

gsutil versioning set on gs://bucket

Cette commande active la gestion des versions pour le bucket désigné. Pour en savoir plus, consultez la page sur gsutil help versioning.

Pour afficher toutes les versions d'objets d'un bucket pour lequel la gestion des versions est activée, ainsi que leurs informations generation.metageneration, exécutez la commande "gsutil ls -a" :

gsutil ls -a gs://bucket

Vous pouvez également définir des objets spécifiques pour lesquels vous souhaitez rechercher la ou les URL spécifiques à une version, ou utiliser des caractères génériques :

gsutil ls -a gs://bucket/object1 gs://bucket/images/*.jpg

Les valeurs de génération constituent une séquence qui augmente de façon monotone à mesure que vous créez des versions d'objets supplémentaires. De ce fait, la version d'objet la plus récente est toujours la dernière répertoriée dans le résultat de la commande "gsutil ls" associée à un objet particulier. Par exemple, si un bucket contient les trois versions suivantes de l'objet gs://bucket/object :

gs://bucket/object#1360035307075000
gs://bucket/object#1360101007329000
gs://bucket/object#1360102216114000

alors gs://bucket/object#13601022161114000 est la version la plus récente et gs://bucket/object#1360035307075000 la version la plus ancienne disponible.

Si vous spécifiez des URL sans version avec gsutil, vous n'agissez que sur la version active d'un objet. Exemple :

gsutil cp gs://bucket/object ./dir

ou :

gsutil rm gs://bucket/object

Il en va de même si vous utilisez des caractères génériques, tels que * et **. Ceux-ci ne fonctionnent que sur la version active des objets correspondants. Par exemple, cette commande supprime la version active et crée une version obsolète pour chaque objet d'un bucket :

gsutil rm gs://bucket/**

Pour effectuer une opération sur une version d'objet spécifique, utilisez une URL propre à cette version. Par exemple, supposons que le résultat de la commande "gsutil ls -a" ci-dessus soit le suivant :

gs://bucket/object#1360035307075000
gs://bucket/object#1360101007329000

Dans ce cas, la commande :

gsutil cp gs://bucket/object#1360035307075000 ./dir

récupère la deuxième version la plus récente de l'objet.

Notez que les URL spécifiques à une version ne peuvent pas être la cible de la commande "gsutil cp" (si vous tentez de le faire, une erreur se produit), car l'écriture dans un objet avec une version gérée crée toujours une version.

Notez également que certaines interfaces système considèrent "#" comme un caractère spécial (par exemple, zsh avec l'option "extendedglob" activée). Si vous utilisez une interface système qui traite "#" comme un caractère spécial, vous devez placer l'argument entre guillemets. Exemple :

gsutil cp 'gs://bucket/object#1360035307075000' ./dir

Si un objet a été supprimé, il ne s'affiche pas dans une liste "gsutil ls" standard (par exemple, la commande "ls" sans l'option -a). Pour restaurer un objet supprimé, exécutez la commande "gsutil ls -a" afin de rechercher les versions disponibles, puis copiez l'une des URL spécifiques à la version dans l'URL sans version. Exemple :

gsutil cp gs://bucket/object#1360101007329000 gs://bucket/object

Notez que cette opération crée une version d'objet, ce qui entraîne des frais supplémentaires. Vous pouvez vous débarrasser de la copie supplémentaire en supprimant l'ancien objet spécifique à la version :

gsutil rm gs://bucket/object#1360101007329000

Vous pouvez également combiner les deux étapes à l'aide de la commande "gsutil mv" :

gsutil mv gs://bucket/object#1360101007329000 gs://bucket/object

Si vous supprimez la version active d'un objet dans un bucket pour lequel la gestion des versions est activée, une version obsolète est conservée :

gsutil rm gs://bucket/object

Si vous supprimez une URL spécifique à une version d'objet (même s'il s'agit de la version active), cette version est définitivement supprimée :

gsutil rm gs://bucket/object#1360101007329000

Si vous souhaitez supprimer toutes les versions d'un objet, utilisez l'option "gsutil rm -a" :

gsutil rm -a gs://bucket/object

Si vous souhaitez supprimer toutes les versions des objets d'un bucket (et le bucket lui-même), utilisez l'option "rm -r" (-r implique l'option -a) :

gsutil rm -r gs://bucket

Notez que le nombre d'anciennes versions que vous pouvez créer pour un objet est illimité si vous continuez d'importer cet objet dans un bucket pour lequel la gestion des versions est activée. Il est de votre responsabilité de supprimer les versions au-delà de celles que vous souhaitez conserver.

Copier des buckets avec des versions gérées

Vous pouvez copier des données entre deux buckets avec des versions gérées à l'aide d'une commande telle que la suivante :

gsutil cp -r -A gs://bucket1/* gs://bucket2

Lorsqu'elle est exécutée avec des buckets disposant de versions gérées, cette commande entraîne la copie de chaque version d'objet. Les copies effectuées dans gs://bucket2 ont des numéros de génération différents (car une nouvelle génération est attribuée lors de la copie de l'objet), mais l'ordre de tri des objets reste cohérent. Par exemple, gs://bucket1 peut contenir les éléments suivants :

% gsutil ls -la gs://bucket1 10  2013-06-06T02:33:11Z
53  2013-02-02T22:30:57Z  gs://bucket1/file#1359844257574000  metageneration=1
12  2013-02-02T22:30:57Z  gs://bucket1/file#1359844257615000  metageneration=1
97  2013-02-02T22:30:57Z  gs://bucket1/file#1359844257665000  metageneration=1

Une fois la copie effectuée, gs://bucket2 peut contenir les éléments suivants :

% gsutil ls -la gs://bucket2
53  2013-06-06T02:33:11Z  gs://bucket2/file#1370485991580000  metageneration=1
12  2013-06-06T02:33:14Z  gs://bucket2/file#1370485994328000  metageneration=1
97  2013-06-06T02:33:17Z  gs://bucket2/file#1370485997376000  metageneration=1

Notez que les versions d'objets sont dans le même ordre (comme le montre la même séquence de tailles dans les deux listes), mais les numéros de génération (et les horodatages) sont plus récents dans gs://bucket2.

Contrôle de simultanéité

Si vous créez une application à l'aide de Cloud Storage, vous devrez peut-être faire attention au contrôle de simultanéité. En principe, gsutil n'est pas utilisé à cette fin, mais il est possible d'écrire des scripts qui effectuent le contrôle de simultanéité.

Par exemple, supposons que vous souhaitiez mettre en œuvre un système de "mise à jour progressive" à l'aide de gsutil, dans lequel une tâche périodique effectue des calculs sur certaines données et les importe dans le cloud. À chaque exécution, la tâche démarre avec les données qu'elle a calculées lors de la dernière exécution et calcule une nouvelle valeur. Pour que ce système soit fiable, vous devez disposer de plusieurs machines sur lesquelles exécuter la tâche, ce qui augmente la possibilité que deux exécutions simultanées tentent de mettre à jour un objet en même temps. Cela peut potentiellement entraîner la condition de concurrence suivante :

  • La tâche 1 calcule la nouvelle valeur à écrire.
  • La tâche 2 calcule la nouvelle valeur à écrire.
  • La tâche 2 écrit la nouvelle valeur.
  • La tâche 1 écrit la nouvelle valeur.

Dans ce cas, la valeur que la tâche 1 a lue n'est plus à jour au moment d'écrire l'objet mis à jour. À ce stade, l'écriture peut donner lieu à des données non actualisées (ou, selon l'application, à leur corruption).

Pour éviter cela, vous pouvez rechercher le nom spécifique de la version de l'objet créé, puis utiliser les informations contenues dans cette URL pour spécifier un en-tête x-goog-if-generation-match dans une commande "gsutil cp" ultérieure. Vous pouvez effectuer cette opération en deux étapes. Tout d'abord, utilisez l'option "gsutil cp -v" lors de l'importation afin d'obtenir le nom spécifique de la version de l'objet créé. Par exemple :

gsutil cp -v file gs://bucket/object

peut générer le résultat suivant :

Created: gs://bucket/object#1360432179236000

Vous pouvez extraire la valeur de génération de cet objet, puis exécuter une commande gsutil ultérieure comme suit :

gsutil -h x-goog-if-generation-match:1360432179236000 cp newfile \
    gs://bucket/object

Cette commande demande à Cloud Storage de tenter d'importer un nouveau fichier, mais de faire échouer la requête si la génération du nouveau fichier actif au moment de l'importation ne correspond pas à celle spécifiée.

Si la commande que vous exécutez met à jour les métadonnées de l'objet, vous devez rechercher la métagénération actuelle de l'objet. Pour ce faire, utilisez les options "gsutil ls -a" et "-l". Par exemple, la commande :

gsutil ls -l -a gs://bucket/object

génère le résultat suivant :

  64  2013-02-12T19:59:13Z  gs://bucket/object#1360699153986000  metageneration=3
1521  2013-02-13T02:04:08Z  gs://bucket/object#1360721048778000  metageneration=2

Compte tenu de ces informations, vous pouvez exécuter la commande suivante pour demander la définition de la LCA sur l'ancienne version de l'objet, de sorte que la commande échoue, sauf s'il s'agit de la version actuelle des données et des métadonnées :

gsutil -h x-goog-if-generation-match:1360699153986000 -h \
  x-goog-if-metageneration-match:3 acl set public-read \
  gs://bucket/object#1360699153986000

Sans l'ajout de ces en-têtes, la mise à jour remplace simplement la LCA existante. En revanche, notez que la commande "gsutil acl ch" utilise ces en-têtes automatiquement, car elle effectue un cycle lecture-modification-écriture pour modifier les LCA.

Si vous souhaitez tester le fonctionnement des générations et des métagénérations, suivez la procédure suivante. Pour commencer, importez un objet. Exécutez ensuite la commande "gsutil ls -l -a" pour répertorier toutes les versions de l'objet, ainsi que la métagénération de chaque version. Importez à nouveau l'objet, puis réexécutez la commande "gsutil ls -l -a". Deux versions d'objet doivent s'afficher, chacune disposant d'une valeur de métagénération égale à 1. Essayez maintenant de définir la LCA et réexécutez la commande "gsutil ls -l -a". La génération d'objet la plus récente qui s'affiche doit maintenant disposer d'une valeur de métagénération égale à 2.

Pour plus d'informations

Pour en savoir plus sur l'utilisation de la gestion des versions et des conditions préalables, consultez la page https://cloud.google.com/storage/docs/object-versioning.