通常,如果我想确定当多个线程对DynamoDB中的同一项目进行并发更新时会发生什么,我应该使用条件更新(即“乐观锁定”)。我知道。但是我想知道是否还有其他情况可以确保对同一项目的并发更新能够继续存在。
例如,在Cassandra中,对同一项目的不同属性进行并发更新是可以的,并且最终可以读取这两个更新。 DynamoDB中是否一样?还是这些更新中只有一个能够生存?
一个非常相似的问题是,如果我将两个不同的值同时添加到同一项目的集合或列表中,将会发生什么。我是否保证我最终会在阅读此集合或列表时看到两个值,或者在某种DynamoDB“冲突解决”协议期间,其中一个添加项可能会掩盖另一个值?
我看到在过去的Are DynamoDB "set" values CDRTs?中已经有人问过我的第二个问题,但是答案指向的是不是很清楚的FAQ条目,该条目不再存在。作为问题的答案,我最想看到的是DynamoDB的官方文档,该文档说明了当不涉及“条件更新”或“事务”时,DynamoDB如何处理并发更新,尤其是上述两个示例中发生的情况。没有这样的官方文档,有人对这种并发更新有任何实际经验吗?
答案 0 :(得分:1)
我只是遇到了同样的问题,并且遇到了这个问题。鉴于没有答案,我决定自己进行测试。
据我所知,答案是,只要您更新不同的属性,它将最终成功。我向项目推送的更新越多,它的确花费的时间就越长,因此它们似乎是按顺序而不是并行编写的。
我还尝试并行更新单个List属性,这可能会失败,一旦所有查询完成,结果列表将被破坏,并且只有一些条目被推入其中。
我进行的测试非常基本,可能会遗漏一些东西,但我认为结论是正确的。
为完整起见,这是我使用的脚本,nodejs。
const aws = require('aws-sdk');
const ddb = new aws.DynamoDB.DocumentClient();
const key = process.argv[2];
const num = process.argv[3];
run().then(() => {
console.log('Done');
});
async function run() {
const p = [];
for (let i = 0; i < num; i++) {
p.push(ddb.update({
TableName: 'concurrency-test',
Key: {x: key},
UpdateExpression: 'SET #k = :v',
ExpressionAttributeValues: {
':v': `test-${i}`
},
ExpressionAttributeNames: {
'#k': `k${i}`
}
}).promise());
}
await Promise.all(p);
const response = await ddb.get({TableName: 'concurrency-test', Key: {x: key}}).promise();
const item = response.Item;
console.log('keys', Object.keys(item).length);
}
像这样运行:
node index.js {key} {number}
node index.js myKey 10
时间:
值得一提的是,这些指标显示了很多受限制的事件,但是这些事件是由nodejs sdk在内部使用指数退避进行处理的,因此一旦尘埃落定,所有内容都将按预期写入。