rus*_*042 1 python google-app-engine entity-framework data-structures google-cloud-datastore
作为这篇文章的延续,这是一个顶点式的问题,以巩固我对gae-datastore的理解,并对我的数据建模决策进行一些批评.我将修改由@Jimmy Kane创建的Jukebox示例,以更好地反映我的真实案例.
在原始设置中,
想象一下,每个房间都有一个带有队列的自动点唱机.人们将歌曲排队到每个点唱机的每个队列.
J=Jukebox, Q=queue, S=Song
Jukebox
/ | \
Q1 Q2 Q3
/ | \ | \
S1 S2 S3 S4 S5
Run Code Online (Sandbox Code Playgroud)
首先,填写Song模型:
Song(ndb.Model):
user_key = ndb.KeyProperty()
status = ndb.StringProperty()
datetime_added = ndb.DateTimeProperty()
Run Code Online (Sandbox Code Playgroud)
我的修改是将UserCUD歌曲添加到任何队列中.在前端,用户将访问UI以在每个队列中查看他们的歌曲,并进行更改.在后端,应用程序需要知道每个队列中的哪些歌曲,从每个队列中播放正确的歌曲,并在播放后从队列中删除歌曲.
为了让用户能够在队列中看到它的歌曲我假设每个用户都是一个根实体并且需要存储一个Song键列表
User(ndb.Model):
song_keys = ndb.KeyProperty(kind='Song', repeated=True)
Run Code Online (Sandbox Code Playgroud)
然后,要检索用户的歌曲,应用程序将(假设user_id已知)
user = User.get_by_id(user_id)
songs = ndb.get_multi(user.song_keys)
Run Code Online (Sandbox Code Playgroud)
并且,由于gets非常一致,用户总是会看到非陈旧数据
然后,当队列1完成播放歌曲时,应用程序可以执行以下操作:
current_song.status = "inactive"
current_song.put()
query=Song.query(ancestor=ndb.Key('Jukebox', '1', 'Queue', '1')).filter(Song.status=="active").order(Song.datetime_added)
next_song = query.get()
Run Code Online (Sandbox Code Playgroud)
我是否正确地认为祖先查询确保了当前歌曲的先前停用以及来自用户的任何CUD的一致表示?
最后一步是在事务中更新用户的song_keys列表
user = current_song.user_key.get()
user.song_keys.remove(current_song.key)
user.put()
Run Code Online (Sandbox Code Playgroud)
总结和一些优点/缺点
Jukebox实体组的争用吗?
queues 相似的s 数量user,可能user比sx多2倍 - 5倍queue秒.如果整个组限制为1个写/秒,并且许多用户以及每个队列可能正在创建和更新歌曲,这可能是一个瓶颈Jukebox根实体,并使每个实体Queue都是自己的根实体User.song_keys可能很长,比如100 song.key秒.本文建议"避免在ListProperty中存储过大的键列表".这里有什么问题?这是一个db概念,并且使用ndb以repeated=True属性选项处理列表的方式没有实际意义吗?关于这种方法的意见或对我从根本上误解的事情的批评?
User- >
Song并song_keys在Queue模型中存储列表我认为你应该重新考虑你的用例的强一致性有多重要.从我所看到的,所有这些实体都具有很强的一致性并不重要.在我看来,最终的一致性会很好.大多数情况下,您会看到最新数据,有时只读(真的很少),您会看到一些陈旧的数据.想想你总能获得最新数据与惩罚应用程序的程度有多重要.需要强一致性的实体不会以每秒读取次数的最有效方式存储.
此外,如果您查看文档" 构建数据以获得强一致性",您将看到它提到在使用该方法时每秒不能超过1次写入.
根据AppEngine Model Class文档,实体组也会影响数据位置.
如果您还阅读了Google Spanner上着名的Google文档,请参阅第2部分,了解它们如何处理具有相同父密钥的实体.基本上,它们更紧密地联系在一起.我假设Google可能会使用与AppEngine Datastore类似的方法.在某些时候,根据这个消息来源,Google可能会在将来使用Spanner for AppEngine Datastore.
还有一点,没有更便宜的更快获得然后通过密钥获得.话虽如此,如果你能以某种方式避免查询,这可以降低运行应用程序的成本.假设您正在开发Web应用程序,您可以将歌曲密钥存储在JSON /文本对象中,然后使用Prospective Search API获取最新结果.这种方法需要更多的工作,并且需要您接受最终的一致性模型,因为数据到达客户端时可能会略微过时.根据您的使用情况(这显然不适用于小型应用程序和小型用户群),节省的成本可能会超出成本.当我说成本时,我的意思是数据可能会略微过时.
根据我的经验,强大的一致性不是大量应用程序的要求.可以使用稍微过时的数据的应用程序数量似乎超过了不能使用的应用程序数量.以YouTube为例,如果我没有立即看到所有视频,我真的不介意(因为有这么大的数字,如果我看到所有这些视频,我甚至都不知道).当你设计这样的东西时,首先问自己一个问题,是否真的有必要提供最新的数据或一些陈旧的数据是否足够好?用户甚至可以分辨出来吗?最新的数据要贵得多,有点陈旧.
| 归档时间: |
|
| 查看次数: |
288 次 |
| 最近记录: |