Python
AWS
S3
boto
DynamoDB

DynamoDBをロックマネージャーとして使う

More than 3 years have passed since last update.

このポストは個人の意見/メモであり、私が所属する会社を代表するものではありません。


DynamoDBのConditional Update

DynamoDBには Conditional Updateという機能があり、これを利用することによりアトミックな更新オペレーションができる。

例えば下記のような感じだ。

- 特定のキーのアイテムがなければPut

- 特定のアイテムの特定のアトリビュートがある値であればUpdate

詳細が知りたい人はDynamoDBのDeveloper Guideを。


Conditional Updateでロック管理

この 「特定のキーのアイテムがなければPut」を応用して、アイテムの有無を以下のように読み替えるとロック管理を実装することができる。

DynamoDBにAというキーでアイテムをPutしにいく。このときにキーAのアイテムが

- 存在する:既に他の誰かがロック済み。Putオペレーションは失敗する(させる)。

- 存在しない:誰もロックしていない。ロックのためのマーキングとしてキーAのアイテムをPutする。

Pythonとbotoで実装するならこんな感じ。


lock_key

def lock_key(key):

try:
dynamodb.put_item(
'TABLE_NAME',
{'key' : { "S" : key }},
expected = {
'key' : { "Exists" : False }
}
)
return True
except Exception,e:
return False

ファイル名をキーにしてテーブルにアイテムをPutしに行く。既存アイテムが存在せずにPutに成功したらTrueを返し、そうでなければFalseを返している。


S3へのファイルアップロードの管理に応用する

この仕組を利用してS3へのファイルアップロードを管理するツールを書いてみた。

https://gist.github.com/imaifactory/6132f8a60461584b4613

一度アップロード済みのファイルが再度アップロードされる心配がないので、大量のファイルを並列でアップロードしたり、途中で処理が失敗したときにも何度でもやり直しをすることができる。実際、この仕組みを使って1日に約8,000〜10,000くらいのログファイルをS3に転送する、というのを3〜4ヶ月運用してたことがあるが、漏れも重複もゼロで運用できたよ。

awscliのs3 syncは便利だけど、プロダクションに利用するには漏れ/重複対策が心配、という人はこんな感じに実装してみるといいかも。

冪等!冪等!