Trong lược đồ db của tôi, tôi cần một khóa chính autoincrement. Làm thế nào tôi có thể nhận ra tính năng này?Làm thế nào để tạo UUID trong DynamoDB?
PS Để truy cập vào DynamoDB, tôi sử dụng dynode, mô-đun cho Node.js.
Trong lược đồ db của tôi, tôi cần một khóa chính autoincrement. Làm thế nào tôi có thể nhận ra tính năng này?Làm thế nào để tạo UUID trong DynamoDB?
PS Để truy cập vào DynamoDB, tôi sử dụng dynode, mô-đun cho Node.js.
Disclaimer: Tôi là nhà duy trì của dự án Dynamodb-mapper
workflow trực quan của một chìa khóa tự động tăng:
Đây chỉ là để giải thích ý tưởng cơ bản. Không bao giờ làm theo cách này bởi vì nó không phải nguyên tử. Theo khối lượng công việc nhất định, bạn có thể phân bổ cùng một ID cho 2+ đối tượng khác nhau vì nó không phải là nguyên tử. Điều này sẽ dẫn đến mất dữ liệu.
Các giải pháp là sử dụng Thanh nguyên tử hoạt động cùng với ALL_NEW của UpdateItem:
Trong trường hợp xấu nhất, ứng dụng treo trước khi đối tượng được lưu nhưng không bao giờ có nguy cơ phân bổ cùng một ID hai lần.
Có một vấn đề còn lại: nơi lưu trữ giá trị ID cuối cùng? Chúng tôi đã chọn:
{
"hash_key"=-1, #0 was judged too risky as it is the default value for integers.
"__max_hash_key__y"=N
}
Tất nhiên, bạn phải ghi đè dữ liệu.
bước cuối cùng là tự động hóa quy trình. Ví dụ:
When hash_key is 0:
atomically_allocate_ID()
actual_save()
Để biết chi tiết thi hành (Python, xin lỗi), xem https://bitbucket.org/Ludia/dynamodb-mapper/src/8173d0e8b55d/dynamodb_mapper/model.py#cl-67
Để cho bạn biết sự thật, công ty của tôi không sử dụng nó trong sản xuất vì, hầu hết thời gian nó là tốt hơn để tìm phím khác như thế nào, cho người dùng, ID, cho một giao dịch, một datetime, ...
tôi đã viết một số ví dụ trong dynamodb-mapper's documentation và nó có thể dễ dàng suy luận để Node.js
Nếu bạn có bất kỳ câu hỏi , hãy hỏi.
Thật tuyệt, nhưng bây giờ tôi đang sử dụng dấu thời gian và số ngẫu nhiên. Cảm ơn PS lớn vì câu trả lời tuyệt vời này và cảm ơn vì đã cải tiến DynamoDB. – NiLL
Một cách giải quyết khác là sử dụng bộ đếm Redis, vì vậy bạn giảm A LOT sự căng thẳng và hoạt động của DynamoDB. Khi bạn làm một chèn, bạn yêu cầu Redis bộ đếm hiện tại và tăng nó. Nếu redis không có bộ đếm, nó sẽ hỏi DynamoDB ID mới nhất, và sau đó lưu nó. –
Tôi không tin rằng có thể tự động tăng kiểu SQL vì các bảng được phân đoạn trên nhiều máy. Tôi tạo ra UUID của riêng tôi trong PHP mà không công việc, tôi chắc chắn bạn có thể đến với một cái gì đó tương tự like this trong javascript.
Tôi đã gặp sự cố tương tự và đã tạo một dịch vụ web nhỏ chỉ nhằm mục đích này. Xem bài viết trên blog này, giải thích làm thế nào tôi đang sử dụng stateful.co với DynamoDB để mô phỏng chức năng auto-increment: http://www.yegor256.com/2014/05/18/cloud-autoincrement-counters.html
Về cơ bản, bạn đăng ký một quầy nguyên tử tại stateful.co và tăng nó mỗi khi bạn cần một giá trị mới, thông qua API RESTful. Dịch vụ này miễn phí.
Nếu bạn đồng ý với khoảng trống trong id gia tăng của mình và bạn không sao với nó chỉ tương ứng với thứ tự các hàng được thêm vào, bạn có thể cuộn riêng: Tạo bảng riêng biệt có tên NextIdTable, với một khóa chính (số), gọi nó là Counter.
Mỗi khi bạn muốn tạo một id mới, bạn sẽ làm như sau:
Tất nhiên, nếu quá trình của bạn bị treo trước khi thực sự áp dụng ID đó ở bất kỳ đâu, bạn sẽ "rò rỉ" và có khoảng trống trong chuỗi ID của bạn. Và nếu bạn đang làm điều này đồng thời với một số quy trình khác, một trong số bạn sẽ nhận được giá trị 39 và một trong số bạn sẽ nhận được giá trị 40 và không có đảm bảo về thứ tự nào sẽ thực sự được áp dụng trong bảng dữ liệu của bạn; người có 40 người có thể viết nó trước khi anh chàng có 39. Nhưng nó cho bạn một thứ tự thô.
Các tham số cho một điều kiện PutItem trong node.js được nêu chi tiết tại đây. http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/frames.html#!AWS/DynamoDB.html. Nếu trước đây bạn đã đọc giá trị 38 từ Counter, yêu cầu PutItem có điều kiện của bạn có thể trông như thế này.
var conditionalPutParams = {
TableName: 'NextIdTable',
Item: {
Counter: {
N: '39'
}
},
Expected: {
Counter: {
AttributeValueList: [
{
N: '38'
}
],
ComparisonOperator: 'EQ'
}
}
};
Tạo mới file.js
và đặt mã này:
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,"");
}
Sau đó, bạn có thể áp dụng chức năng này để id khóa chính. Nó sẽ tạo ra UUID.
bổ sung @ yadutaf của câu trả lời
AWS hỗ trợ Atomic Counters.
Tạo một bảng riêng biệt (order_id
) với một hàng giữ ORDER_NUMBER mới nhất:
+----+--------------+
| id | order_number |
+----+--------------+
| 0 | 5000 |
+----+--------------+
này sẽ cho phép để tăng ORDER_NUMBER bởi 1
và nhận được kết quả tăng lên trong một callback từ 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
}
});
Xin lưu ý rằng trong một số trường hợp hiếm hoi trường hợp của họ có thể là sự cố với kết nối giữa điểm người gọi và API AWS của bạn.Nó sẽ dẫn đến hàng dynamodb được tăng lên, trong khi bạn sẽ nhận được một lỗi kết nối. Do đó, có thể xuất hiện một số giá trị tăng dần không sử dụng.
Bạn có thể sử dụng số tăng thêm data.Attributes.order_number
trong bảng của mình, ví dụ: để chèn {id: data.Attributes.order_number, otherfields:{}}
vào bảng order
.
Cách tiếp cận khác là sử dụng trình tạo UUID
cho khóa chính, vì đây là cao không thể đụng độ.
IMO bạn có nhiều khả năng gặp lỗi khi hợp nhất các bộ đếm khóa chính trên bảng DynamoDB
có sẵn cao hơn so với các xung đột trong số UUID
s được tạo.
Ví dụ, trong Node:
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'
Taken từ SO answer.
Đối với những mã này trong Java, DynamoDBMapper hiện có thể tạo UUID duy nhất nhân danh bạn.
DynamoDBAutoGeneratedKey
Đánh dấu một chìa khóa phân vùng hoặc tài sản loại chìa khóa như là tự động tạo ra. DynamoDBMapper sẽ tạo ra một UUID ngẫu nhiên khi lưu các thuộc tính này. Chỉ các thuộc tính Chuỗi có thể được đánh dấu là các khóa được tạo tự động.
Sử dụng DynamoDBAutoGeneratedKey chú thích như thế này
@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; }
Như bạn có thể thấy trong ví dụ trên, bạn có thể áp dụng cả DynamoDBAutoGeneratedKey và DynamoDBHashKey chú thích vào thuộc tính tương tự để tạo ra một chìa khóa băm độc đáo.
Hãy xem thuật toán [twitters snowflake] (https://github.com/twitter/snowflake) –