[新機能] Amazon S3 にETagによる既存オブジェクト更新時の競合防止が追加されたので試してみました

[新機能] Amazon S3 にETagによる既存オブジェクト更新時の競合防止が追加されたので試してみました

Clock Icon2024.11.26

AWS事業本部コンサルティング部の石川です。Amazon S3 にETagによる既存オブジェクト更新時の競合防止が追加されたので試してみました。

https://aws.amazon.com/jp/about-aws/whats-new/2024/11/amazon-s3-functionality-conditional-writes/

Amazon S3 ETagによる既存オブジェクト更新時の競合防止とは

Amazon S3の条件付き書き込み(conditional writes)は、オブジェクトの存在を確認してから書き込みを行う機能です。すでに、同じキー名のオブジェクト上書きを防ぐ機能は2024年の8月にリリース済みです。

https://dev.classmethod.jp/articles/s3-conditional-writes-awscli/

一方、今回追加された、Amazon S3 ETagによる既存オブジェクト更新時の競合防止は、オブジェクトのETagを確認してから書き込みを行う機能です。既存のオブジェクトの意図しない上書きを防ぎ、分散アプリケーションでのデータ整合性を向上させます。

PutObjectやCompleteMultipartUpload APIリクエストにHTTP if-matchヘッダーを追加することで利用でき、クライアント側での複雑な調整メカニズムや追加のAPI呼び出しが不要になります。

Amazon S3の条件付き書き込み(conditional writes)の機能をまとめると以下のとおりです。

リリース日 ヘッダー 機能 ユースケース
2024年8月20日 if-none-match オブジェクトの存在確認 新規オブジェクト作成時の上書き防止
2024年11月25日 if-match オブジェクトのETagによる変更確認 既存オブジェクト更新時の競合防止

指定したETagと一致しないオブジェクト上書きを防ぐことができるか検証

指定したETagと一致しないオブジェクトの上書きを防ぐことができるか検証します。(言い換えると、指定したETagと一致する場合のみ上書きが可能ということです。)以下のAWS CLIコマンドは、Amazon S3のバケットにオブジェクトをETag指定でアップロードする場合の例です。

aws s3api put-object --bucket cm-datalake-20241126 --key dir-2/my_data.csv --body ./my_data.csv --if-match "d41d8cd98f00b204e9800998ecf8427e" 

条件付きアップロードで --if-match "d41d8cd98f00b204e9800998ecf8427e" - これが今回のコマンドの特徴的な部分です。

条件付きアップロードの詳細

--if-match "6805f2cfc46c0f04559748bb039d69ae"を指定しています。このオプションは、指定されたETagと一致する場合にのみアップロードを実行するよう指示します。

  • ETag(Entity Tag)は、オブジェクトの内容を一意に識別するハッシュ値です。
  • この条件により、特定のバージョンのオブジェクトが存在する場合にのみアップロードが行われます。

動作の流れ

  1. S3は指定されたキー(dir-2/my_data.csv)で既存のオブジェクトを確認します。
  2. 既存のオブジェクトのETagが指定された値("6805f2cfc46c0f04559748bb039d69ae")と一致する場合、新しいオブジェクトがアップロードされます。
  3. ETagが一致しない場合、またはオブジェクトが存在しない場合、アップロードは中止され、エラーが返されます。

実行例

初回は普通に新規のオブジェクトのアップロードします。

% touch my_data.csv

% aws --version
aws-cli/1.36.10 Python/3.10.11 Darwin/23.6.0 botocore/1.35.69

% aws s3api put-object --bucket cm-datalake-20241126 --key dir-2/my_data.csv --body ./my_data.csv 
{
    "ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
    "ServerSideEncryption": "AES256"
}

% aws s3 ls s3://cm-datalake-20241126/dir-2/my_data.csv 
2024-11-26 11:37:28          0 my_data.csv

次に、ETagが異なる同じキーのオブジェクトのアップロードは失敗します。元のオブジェクトは、変更されないことを確認できました。

% aws s3api put-object --bucket cm-datalake-20241126 --key dir-2/my_data.csv --body ./my_data.csv --if-match "d111111111111111111111111111111111e"

An error occurred (PreconditionFailed) when calling the PutObject operation: At least one of the pre-conditions you specified did not hold

% aws s3 ls s3://cm-datalake-20241126/dir-2/my_data.csv
2024-11-26 11:37:28          0 my_data.csv

最後に、ETagが一致した同じキーのオブジェクトのアップロードは成功します。元のオブジェクトは、変更されたことを確認できました。ETagも変更されるため、同じキーのオブジェクトのアップロードするには、新しいETagを指定する必要があります。

% aws s3api put-object --bucket cm-datalake-20241126 --key dir-2/my_data.csv --body ./my_data.csv --if-match "d41d8cd98f00b204e9800998ecf8427e"
{
    "ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
    "ServerSideEncryption": "AES256"
}

% aws s3 ls s3://cm-datalake-20241126/dir-2/my_data.csv
2024-11-26 11:43:00          0 my_data.csv

注意点

  • ETagの値は、オブジェクトの内容が変更されるたびに変わります。
  • マルチパートアップロードの場合、ETagの計算方法が異なる可能性があるため注意が必要です。

最後に

Amazon S3 にETagによる既存オブジェクト更新時の競合防止機能は、オブジェクトの特定のバージョンの確認を行ってから書き込みを実行することが可能になりました。この機能は、特定のバージョンのオブジェクトを更新する場合や他のプロセスによって予期せず変更されていないことを確認してからアップロードする場合に有用です。

一方、ETagの値がオブジェクトの内容変更とともに変わることや、マルチパートアップロードの場合のETag計算方法の違いにご注意ください。

合わせて読みたい

https://dev.classmethod.jp/articles/amazon-s3-conditional-writes/

参考文献

https://docs.aws.amazon.com/AmazonS3/latest/userguide/conditional-writes.html

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.