LoginSignup
29
17

More than 5 years have passed since last update.

DynamoDBでアトミックカウンタを使ってシーケンスを管理する

Last updated at Posted at 2018-01-10

DynamoDBを用いていると、IDなんかをシーケンシャルに扱いたくなってくることがよくあります。
いわゆる連番IDというやつですね。

一見DynamoDBでシーケンシャルなIDを管理しようと思うと、シーケンステーブルを作って最大値を保存するレコードを作成して、それを get して += 1 して update すれば実現出来る……と考えてしまいますが、それではトランザクションの原子性を保証することが出来なくて不安になってしまいます。同時に別のユーザがこの処理を実行してしまったらどうなってしまうのでしょうか!
問題ありません! DynamoDBではアトミックカウンタを使って一つのクエリでレコードの現在の値を更新しつつ結果を取得する事が出来ます!

公式ドキュメントは次の通りです。
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.AtomicCounters

Node.jsでの実装の一例を以下に示します。
実装例のシーケンステーブルは、パーティションキーにシーケンスID、 value に実際の最大値を想定しています。

  /**
   * @param {string} tableName
   * @param {Object<string, *>} key
   * @param {number} incr
   * @return {Promise.<DocumentClient.AttributeMap>}
   */
  function incrementalUpdate(tableName, key, incr) {
    /**
     *
     * @type {DocumentClient.UpdateItemInput}
     */
    const params = {
      TableName: tableName,
      Key: key,
      ReturnValues: "ALL_NEW",
      UpdateExpression: "SET #value = #value + :incr",
      ExpressionAttributeNames: {
        ["#value"]: "value"
      },
      ExpressionAttributeValues: {
        [":incr"]: incr
      }
    };
    console.log("INCREMENTAL_UPDATE", params);
    return new Promise((resolve, reject) => {
      dynamoDBDocumentClient.update(params, (err, data) => {
        if (err) {
          return reject(err);
        } else {
          return resolve(data.Attributes);
        }
      });
    });
  }
29
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
17