私のdbスキームでは、自動インクリメントの主キーが必要です。この機能を実現するにはどうすればよいですか?
PS DynamoDBへのアクセスには、Node.js用のモジュール dynode を使用します。
免責事項:私はDynamodb-mapperプロジェクトのメンテナーです
自動インクリメントキーの直感的なワークフロー:
これは、根本的なアイデアを説明するためだけのものです。これはアトミックではないため、このようにしないでください。特定のワークロードでは、アトミックではないため、同じIDを2つ以上の異なるオブジェクトに割り当てることができます。これにより、データが失われます。
解決策は、atomic ADD操作をALL_NEWとともに使用することです。 pdateItem :
最悪のシナリオでは、オブジェクトが保存される前にアプリケーションがクラッシュしますが、同じ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に簡単に外挿できます
ご不明な点がございましたら、お気軽にお問い合わせください。
増分するIDのギャップに問題がなく、行が追加された順序にほぼ対応しているだけで問題がない場合は、独自のロールを作成できます。1つの主キーを使用して、NextIdTableという別のテーブルを作成します(数値)、それをカウンターと呼びます。
新しい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'
}
}
};
別のアプローチは、主キーにUUID
ジェネレーターを使用することです。これらはhighly衝突する可能性が低いためです。
IMOは、生成されたDynamoDB
sのクラッシュよりも、高可用性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 から取得。
@ 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
テーブルに挿入します。
テーブルが複数のマシンに分割されているため、SQLスタイルの自動インクリメントが可能とは思わない。私は自分のUUIDをPHPで生成します)で生成します。JavaScriptで同様の これのような を思い付くと思います。
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アノテーションの両方を同じ属性に適用して、一意のハッシュキーを生成できます。
私は同じ問題を抱えており、この目的のためだけに小さなWebサービスを作成しました。自動インクリメント機能をシミュレートするためにDynamoDBで stateful.co を使用する方法を説明しているこのブログ投稿を参照してください: http://www.yegor256.com/2014/05 /18/cloud-autoincrement-counters.html
基本的には、アトミックカウンターを stateful.co に登録し、RESTful APIを介して新しい値が必要になるたびにインクリメントします。サービスは無料です。
新しい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を生成します。
自動インクリメントは、他のアイドルを維持しながら特定のシャードをオーバーロードするため、パフォーマンスの観点からは良くありません。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
Go開発者は、これらのパッケージを GoogleのUUID 、 Pborman 、または Satori から使用できます。 Pbormanはパフォーマンスが優れています。詳細については、これらの 記事とベンチマーク を確認してください。
Universal Unique Identifier仕様の詳細については、 here を参照してください。