在 Dynamo 中写入冲突

Write conflict in Dynamo

假设有两个客户端client1和client2,都写了同一个key。这个key有三个replicas,分别是A,B,C。A先接收到client1的请求,再接收到client2',B接收到client2的请求,再接收到client1的请求。现在A和B肯定是不一致的,用Vector Clock也解决不了冲突。我对吗?

如果是这样的话,好像是dynamo中容易发生写冲突。为什么有这么多基于 dynamo 设计的开源项目?

不能谈论 HBase,但我可以谈论受 Dynamo 启发的 Cassandra。

如果在 Cassandra 中发生这种情况,则最近的密钥获胜。

Cassandra 使用协调器节点(可以是任何节点)接收客户端请求并将它们重新发送到所有副本节点。这意味着每个请求都有自己的时间戳。

假设 Client2 有最近的请求,比 Client1 晚几毫秒。

  • 副本 A 接收保存的 Client1,然后接收保存在 Client1 之上的 Client2,因为 Client2 是该密钥的最新信息。

  • 副本 B 收到已保存的 Client2,然后收到已被拒绝的 Client1,因为它具有较旧的时间戳。

副本A和副本B都有Client2,是最新的信息,因此是一致的。

如果您正在使用 Dynamo 并且担心竞争条件(如果您正在使用 lambda,您应该担心)

如果条件失败,您可以检查 putItem 或 updateItem 的条件

例如在 getItem 期间,时间戳为 12345,添加时间戳必须等于 12345 的条件,但另一个进程更新它,将时间戳更改为 12346,您的 put/update 现在应该失败,例如,在 java 中,您可以捕获 ConditionalCheckFailedException ,您可以再执行一次获取项目,在顶部应用您的更改,然后重新提交 put/update


要防止新项目替换现有项目,请使用包含 attribute_not_exists 函数的条件表达式,并将属性名称用作 table 的分区键。由于每条记录都必须包含该属性,因此 attribute_not_exists 函数只有在不存在匹配项目时才会成功。

有关 PutItem 的更多信息,请参阅 Amazon DynamoDB 开发人员指南中的使用项目。

参数: putItemRequest - 表示 PutItem 操作的输入。 Returns: 服务返回的 PutItem 操作的结果。 投掷: ConditionalCheckFailedException - 无法评估操作中指定的条件。

https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/dynamodbv2/AmazonDynamoDB.html#putItem-com.amazonaws.services.dynamodbv2.model.PutItemRequest-