NDB 层次结构和实体组的 GAE 含义
Posted
技术标签:
【中文标题】NDB 层次结构和实体组的 GAE 含义【英文标题】:GAE Implications of NDB hierarchy and entity groups 【发布时间】:2013-12-29 18:47:04 【问题描述】:我试图更好地理解GAE NDB docs 中描述的深层层次结构的含义
“例如,“属于”所有者的消息的修订版可能有一个看起来像“的键”
rev_key = ndb.Key('Account', 'Sandy', 'Message', 'greeting', 'Revision', '2')
我将此解释为,如果我执行Revision(parent=rev_key).put()
,那么我将有一个 Revision=2 级别的实体组,这意味着 ancestor=rev_key
将具有强一致性的祖先查询并写入 parent=rev_key
将限制为 1 /秒。
但是,在层级结构中更进一步的含义是什么?
比如说我有
rev_key_B = ndb.Key('Account', 'Sandy', 'Message', 'greeting', 'Revision', '3')
写入速度在rev_key_B
级别限制为 1/秒,或者,由于它们共享父级的父级,即ndb.Key('Account', 'Sandy', 'Message', 'greeting')
,写入速度在祖先路径的更高级别以及最终限制到整个实体组一直到ndb.Key('Account', 'Sandy')
?
同样的问题:强一致性。 Revision.query(ancestor=ndb.Key('Account', 'Sandy', 'Message', 'greeting'))
会有强一致性吗?
【问题讨论】:
我发誓曾经有文字说明“实体组”始终是根实体加上所有后代(这意味着 1/秒的限制适用于每个根实体和所有后代,无论您的祖先查询是否在层次结构中更远)。不过,我现在找不到任何参考资料,所以也许我误解了,或者它已经改变了。 @Daniel Roseman 对this post 的评论声称实体组是“根实体下的所有内容”,但我也没有在文档中找到它。我对答案的评论是专门针对这个的。 【参考方案1】:让我们看看
rev_key = ndb.Key('Account', 'Sandy', 'Message', 'greeting', 'Revision', '2')
表示每个实体都遵循实体路径具有强一致性。所以你是对的。
让我们看看它的实际效果:创建实体
account_sandy = Account.get_or_insert('Sandy')
sandy_message = Message.get_or_insert('greeting', parent=account_sandy.key)
sandy_message_rev = Revision.get_or_insert('2', parent=sandy_message.key)
这将为您提供强大的一致性,并授予您查询事务中所有上述实体的能力。
我正在使用get_or_insert
,如果提供的密钥不存在,它会在事务中有效地创建实体。这要求 key 或 id 是唯一的。所以这样你就不能有Greeting
和Sandy as parent
的2条消息。
键的工作方式就像二叉树。
S = 桑迪,M=消息,R=修订
Sandy
/ | \
M1 M2 M3
/ | \ | \
R1 R2 R1 R1 R2
每条到达终点或更短的路径都可以在事务中运行并提供强一致性*。
在评论中回复:
由于这个例子不足以显示 GAE 和 NDB 的效率,所以下面可能会。
假设您有一个自动点唱机,每个房间都有队列。人们正在将歌曲排队到每个点唱机的每个队列中。
J=点唱机,Q=队列,S=歌曲
Jukebox
/ | \
Q1 Q2 Q3
/ | \ | \
S1 S2 S3 S4 S5
在这个例子中,使用路径很方便,因此用户的每次操作,在知道 wich jukebox,queue 的情况下,可以 CUD 歌曲实体与 jukebox,queue 和歌曲一致。
*顺便说一句,您也可以锁定不是从根目录开始的路径
还要记住Queries inside transactions must include ancestor filters
【讨论】:
也许这只是 GAE 为展示功能而设计的一个示例,但我不认为有这样的层次结构有什么意义。如果在根级别强制执行一致性,即共享account_sandy.key
祖先的所有内容,那么拥有消息和修订层会获得什么?为什么不让revision
成为Message
的属性,并让所有消息直接成为account_sandy.key
的子级?
@diddleboo 您也可以按照您在消息修订示例中的描述拥有它。但是,每次您想编辑消息时,您也会锁定所有修订。拥有路径的意义在于以一种不会阻塞其余流程的方式隔离一致性。
我想这仍然是我的困惑。给定你制作的 Jukebox 树,我更新了一首歌曲,比如 S1,究竟什么是是和不是锁定的?
@diddleboo 随便你,只要它在路径中。例如,您可以锁定队列和特定歌曲,以更新播放计数或将歌曲存档到另一个队列。所以这真的取决于。在大规模情况下,您甚至可以将所有数据锁定在根实体中。此外,路径不需要从根开始,但可能知道密钥是。
@diddleboo 1) 是 2) 是 3) 1/秒我对此一无所知。关于规模总是取决于操作。例如,如果您正在谈论不经常发生的写入,那么是的,这很好。如果您谈论的是每分钟数千次或每分钟读取/写入的次数,例如计数器,那么应用引擎 不适合您。应用引擎需要针对其中最少的部分进行优化。写入中的每个操作大约需要 5 次写入,因此 1000 次将是 4000 次,路径中的每个节点将花费 1 次,依此类推。以具有太多读取或写入的长路径结束。简化您的观点...以上是关于NDB 层次结构和实体组的 GAE 含义的主要内容,如果未能解决你的问题,请参考以下文章