python - 使用 google-cloud-ndb 进行交易的不同实体组
问题描述
我想使用 google-cloud-ndb 在 Google App Engine 中运行事务操作。我部署了这个应用程序。
这是我的代码。
# -*- coding: utf-8 -*-
from flask import Flask
from google.cloud import ndb
import time
app = Flask(__name__)
class Book(ndb.Model):
hoge = ndb.IntegerProperty()
class Book2(ndb.Model):
hoge = ndb.IntegerProperty()
@ndb.transactional()
def test1():
ent = ndb.Key(Book, "a").get()
print("after get: %s", ent)
ent.hoge = ent.hoge + 1
ent.put()
print("after put: %s", ent)
print("wakeup")
@ndb.transactional()
def test2():
ent = ndb.Key(Book2, "a").get()
print("after get: %s", ent)
ent.hoge = ent.hoge + 1
ent.put()
print("after put: %s", ent)
time.sleep(10)
print("wakeup")
@app.route('/piyo')
def piyo():
print("before transaction")
try:
with ndb.Client().context():
print("enter transaction")
test1()
except Exception as e:
print(e)
print("completed")
return '', 204
@app.route('/foo')
def foo():
print("before transaction")
try:
with ndb.Client().context():
print("enter transaction")
test2()
except Exception as e:
print(e)
print("completed")
return '', 204
if __name__ == "__main__":
app.run()
运行它的尝试对我来说将是意想不到的结果。不同实体组的数据存储不冲突(据我所知)。但他们似乎有冲突,等待完成前面的操作。
为什么这行得通?
记录:
2020-01-30 21:23:18.878 GET 204 116B 10.3s /foo
2020-01-30 21:23:18.882 before transaction
2020-01-30 21:23:18.887 enter transaction
2020-01-30 21:23:19.061 after get: %s Book2(key=Key('Book2', 'a'), hoge=33)
2020-01-30 21:23:19.062 after put: %s Book2(key=Key('Book2', 'a'), hoge=34)
★ sleep
2020-01-30 21:23:29.062 wakeup
2020-01-30 21:23:29.130 completed
2020-01-30 21:23:22.699 GET 204 116B 6.6s Android /piyo
★ confrict and wait completing "Book2" transaction
2020-01-30 21:23:29.132 before transaction
2020-01-30 21:23:29.136 enter transaction
2020-01-30 21:23:29.221 after get: %s Book(key=Key('Book', 'a'), hoge=30)
2020-01-30 21:23:29.221 after put: %s Book(key=Key('Book', 'a'), hoge=31)
2020-01-30 21:23:29.221 wakeup
2020-01-30 21:23:29.285 completed
我正在使用 Python 3.7。我在我的环境中安装了这些工具:
Flask==1.0.3
google-cloud-ndb==0.2.2
请帮我解决我的问题。之前谢谢
解决方案
从技术上讲,您没有冲突,因为您在不同的实体组上进行操作。
然而,当两个跨组事务调用仍在进行时,存在潜在冲突的空间——您还不知道它们中的任何一个是否不会访问另一个触及的实体。顺便说一句,访问不必只是实体写入(导致冲突),它们也可以是实体读取(导致争用),请参阅Google App Engine 中的争用问题。
但是,一旦事务调用结束,我希望它的事务完成(一种或另一种方式,在这种情况下并不真正相关),而无需等待仍在进行中的其他一些事务调用也结束,无论它是否更早开始或不。观察到的行为 - 准备完成的事务调用一直等待其他仍在进行中的事务调用的事实 - 可能导致严重的应用程序性能下降。除非遗漏了什么,否则它可能表明存在某种错误。
可以尝试的一件事(仅作为实验)是通过在文件中配置 set 为 1 来强制 2 个事务由不同的 GAEautomatic_scaling
实例max_concurrent_requests
执行app.yaml
:
可选的。在调度程序生成新实例之前,自动扩展实例可以接受的并发请求数(默认值:10,最大值:80)。
...
我们建议您不要设置
max_concurrent_requests
为小于 10 ,除非您需要单线程。小于 10 的值可能会导致创建的实例数量超过线程安全应用程序所需的数量,这可能会导致不必要的成本。
在单独的实例中执行将确保客户端上下文的完全隔离。如果症状消失,问题出在客户端,可能在云 ndb 库中 - 可能是一些(不希望的)序列化?我会在https://github.com/googleapis/python-ndb提交问题(我扫描了过去几个月提交的问题,那些仍然开放的问题以及最近合并的 PR,我没有注意到任何明显相关的问题)。
如果来自不同的、隔离的客户端的事务的症状仍然存在,那么问题出在数据存储端的某个地方。可能与在数据存储模式下从旧数据存储到 Firestore 的转换有关?- 我想我会注意到旧数据存储的这种行为,我在转换之前对我的事务繁重的应用程序进行了广泛的测试。我会在https://issuetracker.google.com/提出问题。
推荐阅读
- c++ - C++如何找到外部程序指针地址中的值?
- html - DataTables 导出按钮与右下角对齐
- kotlin - Kotlin - 在初始化 lateinit 属性之前不要运行单元测试
- r - R: quantmod - getSymbols 参数
- python - Python 瓶为所有不同的用户提供相同的输出
- python - 从json格式中提取数据并粘贴到column_python
- informatica - 如何将特定记录类型从源映射到目标中的特定记录类型
- node.js - Docker 构建失败 ERR CONREFUSSED,MERN
- oauth - 将 session_state 存储在客户端的本地存储中可以吗?
- laravel - laravel 没有发送请求就关闭了;这可能只是一个未使用的投机预连接