web-dev-qa-db-ja.com

DynamoDBでUUIDを作成する方法は?

私のdbスキームでは、自動インクリメントの主キーが必要です。この機能を実現するにはどうすればよいですか?

PS DynamoDBへのアクセスには、Node.js用のモジュール dynode を使用します。

21
NiLL

免責事項:私はDynamodb-mapperプロジェクトのメンテナーです

自動インクリメントキーの直感的なワークフロー:

  1. 最後のカウンター位置を取得
  2. 追加1
  3. 新しい番号をオブジェクトのインデックスとして使用する
  4. 新しいカウンター値を保存する
  5. オブジェクトを保存する

これは、根本的なアイデアを説明するためだけのものです。これはアトミックではないため、このようにしないでください。特定のワークロードでは、アトミックではないため、同じIDを2つ以上の異なるオブジェクトに割り当てることができます。これにより、データが失われます。

解決策は、atomic ADD操作をALL_NEWとともに使用することです。 pdateItem

  1. iDをアトミックに生成する
  2. 新しい番号をオブジェクトのインデックスとして使用する
  3. オブジェクトを保存する

最悪のシナリオでは、オブジェクトが保存される前にアプリケーションがクラッシュしますが、同じIDを2回割り当てるリスクはありません。

残っている問題が1つあります。最後のID値を保存する場所はどこですか。私たちは選びました:

{
    "hash_key"=-1, #0 was judged too risky as it is the default value for integers.
    "__max_hash_key__y"=N
}

もちろん、確実に機能するためには、データを挿入するすべてのアプリケーションがこのシステムを認識している必要があります。

最後のステップは、プロセスを自動化することです。例えば:

When hash_key is 0:
    atomically_allocate_ID()
actual_save()

実装の詳細(Python、申し訳ありません)については、 https://bitbucket.org/Ludia/dynamodb-mapper/src/8173d0e8b55d/dynamodb_mapper/model.py#cl-67 を参照してください

実を言うと、ほとんどの場合、ユーザー、ID、トランザクション、日時などの別のキーを見つける方が良いため、私の会社では本番環境では使用しません。

dynamodb-mapper's documentation にいくつかの例を書きましたが、Node.JSに簡単に外挿できます

ご不明な点がございましたら、お気軽にお問い合わせください。

20
yadutaf

増分するIDのギャップに問題がなく、行が追加された順序にほぼ対応しているだけで問題がない場合は、独自のロールを作成できます。1つの主キーを使用して、NextIdTableという別のテーブルを作成します(数値)、それをカウンターと呼びます。

新しいIDを生成するたびに、次のことを行います。

  • NextIdTableでGetItemを実行して、Counterの現在の値を読み取ります-> curValue
  • NextIdTableでPutItemを実行して、Counterの値をcurValue + 1に設定します。これを条件付きPutItemにして、Counterの値が変更された場合に失敗するようにします。
  • 条件付きのPutItemが失敗した場合は、他の誰かがあなたと同じ時間にこれを行っていたということです。最初からやり直してください。
  • 成功した場合、curValueが新しい一意のIDになります。

もちろん、実際にそのIDをどこかに適用する前にプロセスがクラッシュした場合、IDが「漏洩」し、IDのシーケンスにギャップが生じます。これを他のプロセスと同時に実行している場合、1つは値39を取得し、もう1つは値40を取得します。データテーブルで実際に適用される順序については保証されません。 40を獲得した人は39を獲得した人の前にそれを書くかもしれません。

Node.jsの条件付きPutItemのパラメーターについては、こちらをご覧ください。 http://docs.aws.Amazon.com/AWSJavaScriptSDK/latest/frames.html#!AWS/DynamoDB.html 。以前にCounterから値38を読み取っていた場合、条件付きのPutItemリクエストは次のようになります。

var conditionalPutParams = {
    TableName: 'NextIdTable',
    Item: {
        Counter: {
            N: '39'
        }
    },
    Expected: {
        Counter: {
            AttributeValueList: [
                {
                    N: '38'
                }
            ],
            ComparisonOperator: 'EQ'
        }
    }
};
5
pisomojado

別のアプローチは、主キーにUUIDジェネレーターを使用することです。これらはhighly衝突する可能性が低いためです。

IMOは、生成されたDynamoDBsのクラッシュよりも、高可用性UUIDテーブル全体で主キーカウンターを統合するときにエラーが発生する可能性が高くなります。

たとえば、ノードでは:

npm install uuid

var uuid = require('uuid');

// Generate a v1 (time-based) id
uuid.v1(); // -> '6c84fb90-12c4-11e1-840d-7b25c5ee775a'

// Generate a v4 (random) id
uuid.v4(); // -> '110ec58a-a0f2-4ac4-8393-c866d813b8d1'

SO answer から取得。

5
James

@ yadutafの回答への追加

AWSは Atomic Counters をサポートしています。

最新のorder_numberを保持する行を持つ別のテーブル(order_id)を作成します。

+----+--------------+
| id | order_number |
+----+--------------+
|  0 |         5000 |
+----+--------------+

これにより、order_numberを1だけインクリメントし、インクリメントした結果をAWS DynamoDBからのコールバックで取得できます。

config={
  region: 'us-east-1',
  endpoint: "http://localhost:8000"
};
const docClient = new AWS.DynamoDB.DocumentClient(config); 

let param = {
            TableName: 'order_id',
            Key: {
                "id": 0
            },
            UpdateExpression: "set order_number = order_number + :val",
            ExpressionAttributeValues:{
                ":val": 1
            },
            ReturnValues: "UPDATED_NEW"
        };


docClient.update(params, function(err, data) {
   if (err) {
                console.log("Unable to update the table. Error JSON:", JSON.stringify(err, null, 2));
   } else {
                console.log(data);
                console.log(data.Attributes.order_number); // <= here is our incremented result
    }
  });

????一部のrareケースでは、呼び出し元ポイントとAWS API間の接続に問題がある可能性があることに注意してください。接続エラーが発生する一方で、dynamodb行が増加します。したがって、いくつかの未使用の増分値が表示される場合があります。

テーブルでは、インクリメントされたdata.Attributes.order_numberを使用できます。 {id: data.Attributes.order_number, otherfields:{}}orderテーブルに挿入します。

3
Artru

テーブルが複数のマシンに分割されているため、SQLスタイルの自動インクリメントが可能とは思わない。私は自分のUUIDをPHPで生成します)で生成します。JavaScriptで同様の これのような を思い付くと思います。

3
greg

Javaでのコーディングの場合、 DynamoDBMapper がユーザーに代わって一意のUUIDを生成できるようになりました。

DynamoDBAutoGeneratedKey

パーティションキーまたは並べ替えキーのプロパティを自動生成としてマークします。 DynamoDBMapperは、これらの属性を保存するときにランダムなUUIDを生成します。自動生成キーとしてマークできるのは文字列プロパティのみです。

このように DynamoDBAutoGeneratedKey アノテーションを使用します

@DynamoDBTable(tableName="AutoGeneratedKeysExample")
public class AutoGeneratedKeys { 
    private String id;

    @DynamoDBHashKey(attributeName = "Id")
    @DynamoDBAutoGeneratedKey
    public String getId() { return id; }
    public void setId(String id) { this.id = id; } 

上記の例でわかるように、DynamoDBAutoGeneratedKeyアノテーションとDynamoDBHashKeyアノテーションの両方を同じ属性に適用して、一意のハッシュキーを生成できます。

3
F_SO_K

私は同じ問題を抱えており、この目的のためだけに小さなWebサービスを作成しました。自動インクリメント機能をシミュレートするためにDynamoDBで stateful.co を使用する方法を説明しているこのブログ投稿を参照してください: http://www.yegor256.com/2014/05 /18/cloud-autoincrement-counters.html

基本的には、アトミックカウンターを stateful.co に登録し、RESTful APIを介して新しい値が必要になるたびにインクリメントします。サービスは無料です。

2
yegor256

新しいfile.jsを作成し、次のコードを追加します。

exports.guid = function () {
    function _p8(s) {
        var p = (Math.random().toString(16)+"000000000").substr(2,8);
        return s ? "-" + p.substr(0,4) + "-" + p.substr(4,4) : p ;
    }
    return (_p8() + _p8(true) + _p8(true)+new Date().toISOString().slice(0,10)).replace(/-/g,"");
}

次に、この関数を主キーIDに適用できます。 UUIDを生成します。

0
Jivi

自動インクリメントは、他のアイドルを維持しながら特定のシャードをオーバーロードするため、パフォーマンスの観点からは良くありません。Dynamodbにデータを保存している場合は、均等に分散されません。

awsRequestIdは実際にはV.4 UUID(ランダム)のように見えます。以下のコードスニペットを試してみてください。

exports.handler = function(event, context, callback) {
    console.log('remaining time =', context.getRemainingTimeInMillis());
    console.log('functionName =', context.functionName);
    console.log('AWSrequestID =', context.awsRequestId);
    callback(null, context.functionName);
};

これを自分で生成したい場合は、 https://www.npmjs.com/package/uuid または lide を使用して、-に基づいて異なるバージョンのUUIDを生成できます。 RFC-4122

  • V1(タイムスタンプベース)
  • V3(名前空間)
  • V4(ランダム)

Go開発者は、これらのパッケージを GoogleのUUIDPborman 、または Satori から使用できます。 Pbormanはパフォーマンスが優れています。詳細については、これらの 記事とベンチマーク を確認してください。

Universal Unique Identifier仕様の詳細については、 here を参照してください。

0