Cloud Datastore:避免竞争条件的方法
Cloud Datastore: ways to avoid race conditions
我有很多观点操纵同类实体:
def view1(request, key):
user = ndb.Key(urlsafe=key).get()
user.x = 1
user.put()
...
def view2(request, key):
user = ndb.Key(urlsafe=key).get()
user.y = 2
user.put()
...
显然,由于可能的竞争条件(最后获胜),这很容易出错:
- view1 读取整个用户实体数据 (x=None, y=None)
- view2 读取整个用户实体数据 (x=None, y=None)
- view1
user.x = 1
(x=1, y=None)
- view2
user.y = 2
(x=None, y=2)
- view1
user.put()
(x=1, y=None)
- view2
user.put()
(x=None, y=2)
解决此问题的最佳方法是什么?什么行为被认为是最体面的?交易(其中一个请求会失败,可以吗)?
包装您的 get 并放入交易中。这将确保您不会踩到不同的更新。
您可以阅读有关 transactions with the NDB Client Library 文档的更多信息。
在您的代码中,例如,您可以只使用 NDB 事务装饰器:
@ndb.transactional(retries=1)
def view1(request, key):
user = ndb.Key(urlsafe=key).get()
user.x = 1
user.put()
...
@ndb.transactional(retries=1)
def view2(request, key):
user = ndb.Key(urlsafe=key).get()
user.y = 2
user.put()
我有很多观点操纵同类实体:
def view1(request, key):
user = ndb.Key(urlsafe=key).get()
user.x = 1
user.put()
...
def view2(request, key):
user = ndb.Key(urlsafe=key).get()
user.y = 2
user.put()
...
显然,由于可能的竞争条件(最后获胜),这很容易出错:
- view1 读取整个用户实体数据 (x=None, y=None)
- view2 读取整个用户实体数据 (x=None, y=None)
- view1
user.x = 1
(x=1, y=None) - view2
user.y = 2
(x=None, y=2) - view1
user.put()
(x=1, y=None) - view2
user.put()
(x=None, y=2)
解决此问题的最佳方法是什么?什么行为被认为是最体面的?交易(其中一个请求会失败,可以吗)?
包装您的 get 并放入交易中。这将确保您不会踩到不同的更新。
您可以阅读有关 transactions with the NDB Client Library 文档的更多信息。
在您的代码中,例如,您可以只使用 NDB 事务装饰器:
@ndb.transactional(retries=1)
def view1(request, key):
user = ndb.Key(urlsafe=key).get()
user.x = 1
user.put()
...
@ndb.transactional(retries=1)
def view2(request, key):
user = ndb.Key(urlsafe=key).get()
user.y = 2
user.put()