[初心者向け]Cloud Storageの世代番号、メタ世代番号、バージョニングについて調べてみた

Google CloudのサービスであるCloud Storageで世代番号(generation)、メタ世代番号(metageneration)、バージョニングについて調べてみました。
2023.04.11

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

クラスメソッド株式会社データアナリティクス事業本部所属のニューシロです。
クラスメソッドにジョインして1週間経ちました。今回はGoogle CloudのサービスであるCloud Storage(GCS)へオブジェクトをアップロードする際につけられる世代番号、メタ世代番号、そしてバージョニングについて調べてみました。

DevelopersIOでは2本目の記事、技術ブログとしては初記事です。1本目のジョインブログは入社初日でバタバタしている中投稿したので、今回はゆっくり書いていきたいと思います。

前提として私はクラスメソッドが初めて就職したIT企業ですので、技術については今現在学習中であり、もちろんこのような技術ブログを書くことにも全く慣れておりません。しかしながらクラスメソッドのカルチャーの一つに「やってみる」があります。DevelopersIOはレベルの高い記事ばかり挙げられておりハードルが大変高いのですが、それでもまずは記事を書くということを「やってみる」ことにします。至らない点もあるかと思いますが、どうぞよろしくお願いいたします。

きっかけ

Cloud Functionsを用いてCloud Storageへファイルをアップロードするコードについて学習した際、少し気になったことがきっかけでこの記事を執筆することにしました。 以下は公式ドキュメントからの引用で、Pythonのコードです。

from google.cloud import storage

def upload_blob(bucket_name, source_file_name, destination_blob_name):
    """Uploads a file to the bucket."""
    # The ID of your GCS bucket
    # bucket_name = "your-bucket-name"
    # The path to your file to upload
    # source_file_name = "local/path/to/file"
    # The ID of your GCS object
    # destination_blob_name = "storage-object-name"

    storage_client = storage.Client()
    bucket = storage_client.bucket(bucket_name)
    blob = bucket.blob(destination_blob_name)

    # Optional: set a generation-match precondition to avoid potential race conditions
    # and data corruptions. The request to upload is aborted if the object's
    # generation number does not match your precondition. For a destination
    # object that does not yet exist, set the if_generation_match precondition to 0.
    # If the destination object already exists in your bucket, set instead a
    # generation-match precondition using its generation number.
    generation_match_precondition = 0

    blob.upload_from_filename(source_file_name, if_generation_match=generation_match_precondition)

    print(
        f"File {source_file_name} uploaded to {destination_blob_name}."
    )

このコードだと、既に同名のオブジェクトがバケットにある場合、上書きしてアップロードすることができません。 理由はblob.upload_from_filenameという関数の第2引数にif_generation_match=generation_match_preconditionが設定されているためです。これによって、既に同名のオブジェクトがバケットにある場合、そのオブジェクトの世代番号を参照して上書きするかどうかを判断しています。しかしgeneration_match_precondition = 0 という変数が設定されている場合は上書きできないようになっています。よって、このコードではオブジェクトの上書きはできません。

しかし、そもそも世代番号とは何でしょうか。

本題

世代番号・メタ世代番号とは

世代番号とは何でしょうか。世代というようには同名オブジェクトを上書きするごとに 1 → 2 → 3 ・・・ と増えていく番号のように思えますが、実際は違います。

世代番号(generation)はオブジェクトごとに一意に定められる番号です。データを上書きするごとに、全く別の値に変わります。なので、世代という単語からイメージされるものとは少し違うことがわかります。

一方、メタ世代番号(metageneration)はメタデータのバージョンを識別する数字で、イメージ通り 1 → 2 → 3 ・・・ と増加していく数字です。ただし、あくまでメタデータを更新すると増えていく値です。オブジェクトを上書きし世代番号が変わると、メタ世代番号は1に戻ります。ちなみにメタ世代番号はCloud Shell(CLI)上でgcloud storage objects describe gs://BUCKET_NAME/OBJECT_NAMEと入力することで表示できます。

バージョニングとは

では、私が最初にイメージした、同名オブジェクトを上書きすることに増えていくものは何でしょうか。それはバージョン(バージョニング)です。

バージョニングとは、削除または置換されたオブジェクトを取得できるようにするための機能です。 よって、 1 → 2 → 3 ・・・ と上書きの回数を記録した数字等ではなく、上書き前のオブジェクトのデータが履歴として残ります。 バージョニングは自分で設定しないと使用できません。バケット作成時に設定できますが、作成後でも「保護」タブから変更が可能です。

試しにバージョン上限数を3に設定します。この上限数は、ライブバージョン(現在のバージョン)を含めて残す数です。設定後、同名オブジェクトを4回アップロードします。

バージョニングを有効にしているので、ライブバージョンだけでなく過去のアップロード分もそれぞれダウンロードが可能です。もちろん、内容もそれぞれアップロードした際のものになっています。4回アップロードしたのですが、バージョン上限数を3に設定したので、3つまでしか残らないはずです。あれ、、、全て残ってる、、、

~ 少し待つ ~

時間が経って覗いて見たら消えていました。どうやら時間差があるようです。過去のバージョンはそれぞれダウンロードしたり、ライブオブジェクトに戻したりすることが可能です。誤ってデータを上書きしてしまった際も、これで安心ですね。

まとめ・補足

まとめ

  • 世代番号(generation)はオブジェクトを一意に特定するための数字です。世代という言葉に気をつけましょう。
  • メタ世代番号(metageneration)は、メタデータのバージョンを識別する数字です。
  • 大切なデータが含まれたオブジェクトを扱う際は、バージョニングは有効にしておきましょう。

補足

補足ですが、記事の初めにあげたコードでは、

- blob.upload_from_filename(source_file_name, if_generation_match=generation_match_precondition)
+ blob.upload_from_filename(source_file_name)

と第2引数を削除すると、世代番号を参照しないためオブジェクトの上書き保存ができるようになります。

以上です。ここまでお読みいただきありがとうございました。

引用・参照まとめ