GAE Implications of NDB hierarchy and entity group

2020-06-25 04:45发布

I'm trying to better understand the implications of the deep hierarchy described in the GAE NDB docs

"For example, a revision of a message that "belongs to" an owner, might have a key that looks like"

rev_key = ndb.Key('Account', 'Sandy', 'Message', 'greeting', 'Revision', '2')

I interpret this to mean that if I do Revision(parent=rev_key).put() then I will have an entity group at the Revision=2 level meaning ancestor queries where ancestor=rev_key will have strong consistency and writes where parent=rev_key will be limited to 1/sec.

But what are the implications further up the hierarchy?

For instance, say I have

rev_key_B = ndb.Key('Account', 'Sandy', 'Message', 'greeting', 'Revision', '3')

Is write speed limited to 1/sec at the rev_key_B level or, since they share a parent's parent, i.e. ndb.Key('Account', 'Sandy', 'Message', 'greeting'), is write speed limited even higher up the ancestor path and, ultimately, to the entire entity group all the way up to ndb.Key('Account', 'Sandy')?

Same questions re: strong consistency. Would Revision.query(ancestor=ndb.Key('Account', 'Sandy', 'Message', 'greeting')) have strong consistency?

1条回答
太酷不给撩
2楼-- · 2020-06-25 05:10

Let's see

rev_key = ndb.Key('Account', 'Sandy', 'Message', 'greeting', 'Revision', '2')

Means that every entity has strong consistency following the entity path. So you are correct.

Lets see it in action: Create the entities

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)

That will give you strong consistency and grant you the ability to query all the above entities inside transactions as well.

I am using the get_or_insert which does what it says inside a transaction efficiently creating an entity if it does not exist with the key provided. This requires the key or id to be unique. So this way you cannot have 2 messages with Greeting and Sandy as parent.

The way keys work is like a binary tree.

S = Sandy, M=Message, R=Revision

    Sandy
   / |   \
  M1 M2   M3 
 / |  \   | \
R1 R2  R1 R1 R2

Each path to the end or shorter can be run in transaction and provide strong consistency*.

Reply in comment:

As this example is not sufficient to show the efficiency of GAE and NDB maybe the below will.

Imagine that you have a jukebox with queues per room let's say. And people are queueing songs to each queue of each jukebox.

J=Jukebox, Q=queue, S=Song

   Jukebox       
   / |   \        
  Q1 Q2   Q3     
 / |  \   | \
S1 S2  S3 S4 S5

In this example it is convenient to use paths, so each operation by a user, knowing wich jukebox, queue can CUD the song entity with consistency to jukebox, queue and song.

*Btw you can also lock paths not starting from root

Also keep in mind that Queries inside transactions must include ancestor filters

查看更多
登录 后发表回答