向客户端公开 DynamoDb 乐观锁定版本以防止更高级别的竞争条件是否可能并且是一种好的做法?
Is it possible and is it good practice to expose DynamoDb Optimistic Locking Version to clients to prevent race conditions at a higher level?
这是一般的竞争条件问题
- 资源是用列表创建的
- ServiceA 和 ServiceB 想要在 Resource 中的列表中添加一些东西
- ServiceA 获取资源(列表=[])
- ServiceB 获取资源(列表=[])
- ServiceA 更新资源 (list=[A]) 并成功
- ServiceB 更新资源 (list=[B]) 并成功
预期:资源 (list=[A,B]) 或异常
实际:资源(列表=[B])
更糟糕的是,这是一个无声的失败
使用DynamoDB's Optimistic Locking with Version Number,我们可以解决这个问题,场景如下所示。
- 资源是用列表创建的(并且版本=1)
- ServiceA 和 ServiceB 想要在 Resource 中的列表中添加一些内容
- ServiceA 获取资源(列表=[],版本=1)
- ServiceB 获取资源(列表=[],版本=1)
- ServiceA更新资源(列表=[A],版本=1)并成功(版本变为2)
- ServiceB 更新资源(列表=[B],版本=1)失败,因为版本落后
因此 ServiceB 收到失败通知,可以决定通过重新获取资源(版本=2 和列表=[A])并更新资源(列表=[A,B],版本= 2).
DynamoDB 为您管理版本。它在创建资源时将版本设置为 1,在每次更新时自动递增,如果版本不匹配则抛出异常。
我的问题是,是否可以在客户获取请求期间将该版本公开给他们(假设客户不是我们的代码,而是我们组织拥有的其他一些服务)并允许他们在期间提供它他们的更新请求?
- 该问题的第一部分是,这在技术上是否可行?
- 该问题的第二部分是,这是好的做法吗? (即,即使我们在技术上可以这样做,这样做有什么问题吗?)
首先,DynamoDB 并没有真正的记录版本控制的概念。这个概念是由一些添加版本字段并在 PutItem
调用中利用 Condition Expressions 的库引入的。因此,在这方面,您并没有真正暴露 DynamoDB 值,而是暴露了您选择添加到数据中的值(尽管是通过 SDK)。
其次,很可能有更好的方法来解决这个问题。考虑使用 UpdateItem and take advantage of some of the more advanced UpdateExpressions,特别是 ADD
操作。
If the existing data type is a set and if Value is also a set, then Value is added to the existing set. For example, if the attribute value is the set [1,2], and the ADD action specified [3], then the final attribute value is [1,2,3]. An error occurs if an ADD action is specified for a set attribute and the attribute type specified does not match the existing set type.
这可以让您进行部分更新,而不用担心多个请求会更改相同的数据。它有其局限性,但在您的确切情况下,我相信这会起作用。
这是一般的竞争条件问题
- 资源是用列表创建的
- ServiceA 和 ServiceB 想要在 Resource 中的列表中添加一些东西
- ServiceA 获取资源(列表=[])
- ServiceB 获取资源(列表=[])
- ServiceA 更新资源 (list=[A]) 并成功
- ServiceB 更新资源 (list=[B]) 并成功
预期:资源 (list=[A,B]) 或异常
实际:资源(列表=[B]) 更糟糕的是,这是一个无声的失败
使用DynamoDB's Optimistic Locking with Version Number,我们可以解决这个问题,场景如下所示。
- 资源是用列表创建的(并且版本=1)
- ServiceA 和 ServiceB 想要在 Resource 中的列表中添加一些内容
- ServiceA 获取资源(列表=[],版本=1)
- ServiceB 获取资源(列表=[],版本=1)
- ServiceA更新资源(列表=[A],版本=1)并成功(版本变为2)
- ServiceB 更新资源(列表=[B],版本=1)失败,因为版本落后
因此 ServiceB 收到失败通知,可以决定通过重新获取资源(版本=2 和列表=[A])并更新资源(列表=[A,B],版本= 2).
DynamoDB 为您管理版本。它在创建资源时将版本设置为 1,在每次更新时自动递增,如果版本不匹配则抛出异常。
我的问题是,是否可以在客户获取请求期间将该版本公开给他们(假设客户不是我们的代码,而是我们组织拥有的其他一些服务)并允许他们在期间提供它他们的更新请求?
- 该问题的第一部分是,这在技术上是否可行?
- 该问题的第二部分是,这是好的做法吗? (即,即使我们在技术上可以这样做,这样做有什么问题吗?)
首先,DynamoDB 并没有真正的记录版本控制的概念。这个概念是由一些添加版本字段并在 PutItem
调用中利用 Condition Expressions 的库引入的。因此,在这方面,您并没有真正暴露 DynamoDB 值,而是暴露了您选择添加到数据中的值(尽管是通过 SDK)。
其次,很可能有更好的方法来解决这个问题。考虑使用 UpdateItem and take advantage of some of the more advanced UpdateExpressions,特别是 ADD
操作。
If the existing data type is a set and if Value is also a set, then Value is added to the existing set. For example, if the attribute value is the set [1,2], and the ADD action specified [3], then the final attribute value is [1,2,3]. An error occurs if an ADD action is specified for a set attribute and the attribute type specified does not match the existing set type.
这可以让您进行部分更新,而不用担心多个请求会更改相同的数据。它有其局限性,但在您的确切情况下,我相信这会起作用。