如何在DynamoDB中创建UUID?

NiL*_*iLL 21 database nosql node.js amazon-dynamodb

在我的数据库方案中,我需要一个自动增量主键.我怎么能实现这个功能?

PS要访问DynamoDB,我使用倍增极了Node.js的,模块

yad*_*taf 20

免责声明:我是Dynamodb-mapper项目的维护者

自动增量键的直观工作流程:

  1. 得到最后的反位置
  2. 加1
  3. 使用新数字作为对象的索引
  4. 保存新的计数器值
  5. 保存对象

这只是为了解释潜在的想法.永远不要这样做,因为它不是原子的.在某些工作负载下,您可以为2个以上的不同对象分配相同的ID,因为它不是原子的.这将导致数据丢失.

解决方案是使用原子ADD操作以及UpdateItemALL_NEW:

  1. 原子地生成ID
  2. 使用新数字作为对象的索引
  3. 保存对象

在最坏的情况下,应用程序在保存对象之前崩溃,但绝不会冒两次分配相同ID的风险.

还有一个问题:在哪里存储最后一个ID值?我们选择了:

{
    "hash_key"=-1, #0 was judged too risky as it is the default value for integers.
    "__max_hash_key__y"=N
}
Run Code Online (Sandbox Code Playgroud)

当然,为了可靠地工作,所有插入数据的应用程序必须知道这个系统,否则你可能(再次)覆盖数据.

最后一步是自动化该过程.例如:

When hash_key is 0:
    atomically_allocate_ID()
actual_save()
Run Code Online (Sandbox Code Playgroud)

有关实现细节(Python,抱歉),请参阅https://bitbucket.org/Ludia/dynamodb-mapper/src/8173d0e8b55d/dynamodb_mapper/model.py#cl-67

说实话,我的公司不会在生产中使用它,因为在大多数情况下,最好找到另一个密钥,例如,用户,ID,交易,日期时间......

我在dynamodb-mapper的文档中写了一些例子,可以很容易地推断出Node.JS

如果您有任何疑问,请随时提出.

  • 另一种解决方法是使用Redis计数器,因此您可以减少对DynamoDB的压力和操作.当您执行插入操作时,您向Redis询问当前计数器并增加它.如果redis没有计数器,它会向DynamoDB询问最新的ID,然后存储它. (3认同)

Jam*_*mes 10

另一种方法是UUID为主键使用生成器,因为它们不可能发生冲突。

IMODynamoDB与生成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'
Run Code Online (Sandbox Code Playgroud)

取自 SO答案


pis*_*ado 5

如果您的增量ID中存在间隙,并且您只是粗略地对应于添加行的顺序,那么您可以自己滚动:创建一个名为NextIdTable的单独表,其中包含一个主键(数字),称之为计数器.

每次要生成新ID时,都会执行以下操作:

  • 在NextIdTable上执行GetItem以读取Counter - > curValue的当前值
  • 在NextIdTable上执行PutItem,将Counter的值设置为curValue + 1.将此值设置为条件PutItem,以便在Counter的值发生更改时失败.
  • 如果该条件PutItem失败,则意味着其他人正在与您同时执行此操作.重来.
  • 如果成功,则curValue是您的新唯一ID.

当然,如果您的进程在实际应用该ID之前崩溃,那么您将"泄漏"它并且在您的ID序列中存在间隙.如果你和其他一些过程同时进行,那么你们中的一个会获得价值39而你们其中一个会获得价值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'
        }
    }
};
Run Code Online (Sandbox Code Playgroud)


Art*_*tru 5

除了@yadutaf 的回答

AWS 支持原子计数器

创建一个单独的表 ( order_id),其中一行包含最新的 order_number:

+----+--------------+
| id | order_number |
+----+--------------+
|  0 |         5000 |
+----+--------------+
Run Code Online (Sandbox Code Playgroud)

这将允许增加 order_number1并从 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
    }
  });
Run Code Online (Sandbox Code Playgroud)

请注意,在极少数情况下,它们可能是您的调用方点和 AWS API 之间的连接出现问题。这将导致 dynamodb 行增加,同时您将收到连接错误。因此,可能会出现一些未使用的增量值。

您可以data.Attributes.order_number在表中使用 incremented ,例如插入{id: data.Attributes.order_number, otherfields:{}}order表中。


F_S*_*O_K 5

对于那些使用 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; } 
Run Code Online (Sandbox Code Playgroud)

正如您在上面的示例中看到的,您可以将 DynamoDBAutoGeneratedKey 和 DynamoDBHashKey 注释应用于同一属性以生成唯一的哈希键。