【アップデート】S3 Express One Zoneでオブジェクトの追記が可能になりました!
リテールアプリ共創部@大阪の岩田です。
少し前になりますが2024/11/21付けのアップデートでストレージクラスがExpress One ZoneのS3バケット上のオブジェクトへの追記が可能になりました。
さっそく触ってみたので簡単に紹介させて頂きます。
アップデート概要
S3を使っているとあるあるだと思いますが、ちょっとオブジェクトの中身を追記したいというようなケースでも以下のような手順を踏む必要がありました。
- GetObjectでオブジェクトをローカルにダウンロードする
- ダウンロードしたオブジェクトの中身を追記する
- 再度PutObjectで追記後のオブジェクトをアップロードする
それが今回のアップデートによってS3上のオブジェクトに対して直接データが追記できるようになりました!これは熱い!!
公式ドキュメントの記載によるとログファイルへの新しいエントリの追記や動画ファイルへの新しいセグメントの追記といったユースケースを想定しているようです。
制限事項など
以下の制限事項が存在します。
- 追記が可能なのはストレージクラスがS3 Express One Zoneの場合のみです。他のストレージクラスではオブジェクトの追記はサポートされていません。
- 1回のリクエストで追記可能なデータの最大サイズは5GBです。これはS3 APIを使用してデータをアップロードする際の最大リクエストサイズと同じです。
- 追記操作の度にオブジェクトのパートが作成されます。1つのオブジェクトには最大で10,000のパートを含むことができます。
- つまり1つのオブジェクトに対して最大9,999回の追記が可能です。
- 新規作成で1パート + 追記で9,999パート
- マルチパートアップロードを利用した場合、アップロードした各パートそれぞれが1つのパートとしてカウントされます。
- つまり1つのオブジェクトに対して最大9,999回の追記が可能です。
やってみる
実際にオブジェクトへの追記を試してみます。
ディレクトリバケットを作成
まずストレージクラスがExpress One ZoneのS3バケットを作成します。
BASE_NAME='<バケット名のベースとして利用する文字列>'
AZ_NAME='apne1-az4'
BUCKET_NAME="${BASE_NAME}--${AZ_NAME}--x-s3"
aws s3api create-bucket \
--bucket ${BUCKET_NAME} \
--create-bucket-configuration "Location={Type=AvailabilityZone,Name=${AZ_NAME}},Bucket={DataRedundancy=SingleAvailabilityZone,Type=Directory}"
作成に成功すると以下のようなレスポンスが返却されます。
{
"Location": "https://<バケット名のベースとして使用する文字列>--apne1-az4--x-s3.s3express-apne1-az4.ap-northeast-1.amazonaws.com/"
}
普通にPutObjectしてみる
ディレクトリバケットが作成できたのでPutObjectしてみます。
echo "0123456789" > hoge.txt
aws s3api put-object \
--bucket ${BUCKET_NAME} \
--key sample/hoge.txt \
--body hoge.txt
この例ではsample/hoge.txt
というキーで0123456789
という文字列のデータをPutObjectしています。--body
にはファイルパスを指定する必要があるため、最初にechoコマンドを実行してファイルを作成し、作成したファイルをオプションに渡しています。
成功すると以下のようなレスポンスが返却されます。
{
"Expiration": "NotImplemented",
"ETag": "\"d11e5385b7ad4d9bbcc19eaee027bf1c\"",
"ChecksumCRC32": "QHbl0Q==",
"ServerSideEncryption": "AES256"
}
マネコンも確認しておきましょう。
オブジェクトが作成されていることが分かります。
先ほどPutObjectしたファイルをGetObjectして中身を標準出力に出力してみましょう。
aws s3 cp s3://${BUCKET_NAME}/sample/hoge.txt -
0123456789
最初にPutObjectしたファイルの中身である0123456789
が出力されました。
PutObjectしたオブジェクトに追記してみる
ここからが本題です。今回のアップデートによって可能になったオブジェクトの追記を試してみます。基本的な流れは初回のPutObjectと同様ですが、オプションの--write-offset-bytes
で追記開始するオフセット位置を指定します。最初にPutObjectしたデータは0123456789
+ 改行コードなので--write-offset-bytes
には11を指定します。
echo "9876543210" > hoge-append.txt
aws s3api put-object \
--bucket ${BUCKET_NAME} \
--key sample/hoge.txt \
--body hoge-append.txt \
--write-offset-bytes 11
--write-offset-bytes
の指定が適切であればPutObjectに成功し、以下のようなレスポンスが返却されます。
{
"Expiration": "NotImplemented",
"ETag": "\"65ac0fe50eaf40139868dc90de7bab4a\"",
"ChecksumCRC32": "iV+cIA==",
"ServerSideEncryption": "AES256",
"Size": 22
}
再度GetObjectして中身を確認してみましょう。
aws s3 cp s3://${BUCKET_NAME}/sample/hoge.txt -
0123456789
9876543210
最初にPutObjectしたデータ0123456789
に加えて、後から追記した9876543210
も出力されています!追記成功です。
--write-offset-bytesの指定が誤っているとどうなるか確認してみた
先程は無事に追記成功しましたが、失敗するパターンも確認しておきましょう。まず--write-offset-bytes
の指定が誤っているとどうなるか確認してみました。
aws s3api put-object \
--bucket ${BUCKET_NAME} \
--key sample/hoge.txt \
--body hoge-append.txt \
--write-offset-bytes 11
すでに一度追記した後なので、--write-offset-bytes
に11は指定できなくなっているはずです。
レスポンスは以下の通りでした。
An error occurred (InvalidWriteOffset) when calling the PutObject operation: The write offset value that you specified does not match the current object size.
10,000回追記したらどうなるか確認してみた
さらに10,000回追記したらどうなるか確認してみましょう。以下のコードを実行してみます。
import boto3
import time
client = boto3.client('s3')
bucket_name='<対象のS3バケット名>'
key='sample/hoge2.txt'
data=b'0123456789'
client.put_object(Bucket=bucket_name,Key=key,Body=data)
# 9,999回追記オペレーションを実行
for i in range(9999):
offset=10 * (i +1 )
client.put_object(Bucket=bucket_name,Key=key,Body=data,WriteOffsetBytes=offset)
time.sleep(0.1)
# 10,000回目の追記オペレーション
client.put_object(Bucket=bucket_name,Key=key,Body=data,WriteOffsetBytes=100000)
9,999回追記オペレーションを実行した段階でのレスポンスは以下の通りでした。
{'ResponseMetadata': {'RequestId': '01b170d9850001936c824648070f6e9ee5b557a4', 'HostId': 'S3hKKAJ', 'HTTPStatusCode': 200, 'HTTPHeaders': {'date': 'Wed, 27 Nov 2024 07:24:57 GMT', 'server': 'AmazonS3', 'x-amz-request-id': '01b170d9850001936c824648070f6e9ee5b557a4', 'x-amz-id-2': 'S3hKKAJ', 'etag': '"52c9f45436254e388924875dd6421f31"', 'x-amz-expiration': 'NotImplemented', 'x-amz-object-size': '100000', 'x-amz-server-side-encryption': 'AES256', 'x-amz-checksum-crc32': 'poTHxg==', 'transfer-encoding': 'chunked'}, 'RetryAttempts': 0}, 'Expiration': 'NotImplemented', 'ETag': '"52c9f45436254e388924875dd6421f31"', 'ChecksumCRC32': 'poTHxg==', 'ServerSideEncryption': 'AES256', 'Size': 100000}
さらに10,000回目の追記オペレーションを実行すると...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
...略
botocore.errorfactory.TooManyParts: An error occurred (TooManyParts) when calling the PutObject operation: You have attempted to add more parts than the maximum of 10000 that are allowed for this object. You can use the CopyObject operation to copy this object to another and then add more data to the newly copied object.
TooManyParts
というエラーが発生しました。想定通りの挙動です。
まとめ
S3 Express One Zoneでオブジェクトの追記を試してみました。追記可能な回数に制限はありますが、ユースケースがハマれば非常に強力なアップデートだと思います。
将来的に他のストレージクラスでも追記可能になると最高ですね!