您将如何为Twitter等社交网站设计AppEngine数据存储?

Era*_*mpf 28 architecture google-app-engine google-cloud-datastore

我想知道什么是设计社交应用程序的最佳方式,其中成员使用Google AppEngine进行活动并关注其他成员的活动.

更具体一点,假设我们有这些实体:

  • 有朋友的用户
  • 表示用户所做操作的活动(假设每个用户都有一个字符串消息和一个ReferenceProperty给它的所有者用户,或者它可以通过appengine的密钥使用父关联)

困难的部分是关注您朋友的活动,这意味着汇总您所有朋友的最新活动.通常情况下,这将是活动表和你的朋友列表之间的连接,但这不是一个可行的appengine设计,因为没有连接模拟它将需要激活N个查询(其中N是朋友的数量)然后合并到内存中 - 非常昂贵,可能超过要求的截止日期......)

我目前正在考虑使用收件箱队列来实现这一点,其中创建新的Activity将触发后台进程,该进程将新活动的密钥放在每个后续用户的"收件箱"中:

  • 获取"所有关注X的用户"是一个可能的appengine查询
  • 对于基本上存储(用户,活动密钥)元组的新"收件箱"实体而言,不是非常昂贵的批量输入.

我很高兴听到有关这个设计或其他建议等的想法.

win*_*ngs 25

看看在App Engine构建可扩展的复杂应用程序(pdf),这是Brett Slatkin在Google I/O上给出的一个引人入胜的演讲.他解决了构建像Twitter这样的可扩展消息传递服务的问题.

这是他使用list属性的解决方案:

class Message(db.Model):
    sender = db.StringProperty()
    body = db.TextProperty()

class MessageIndex(db.Model):
    #parent = a message
    receivers = db.StringListProperty()

indexes = MessageIndex.all(keys_only = True).filter('receivers = ', user_id)
keys = [k.parent() for k in indexes)
messages = db.get(keys)
Run Code Online (Sandbox Code Playgroud)

此仅密钥查询查找具有接收方等于您指定的接收方的消息索引,而不反序列化和序列化接收方列表.然后,您使用这些索引仅捕获所需的消息.

这是错误的方法:

class Message(db.Model):
    sender = db.StringProperty()
    receivers = db.StringListProperty()
    body = db.TextProperty()

messages = Message.all().filter('receivers =', user_id)
Run Code Online (Sandbox Code Playgroud)

这样效率很低,因为查询必须解包查询返回的所有结果.因此,如果您在每个接收者列表中返回100条消息,其中包含1,000个用户,则必须反序列化100,000(100 x 1000)个列表属性值.数据存储延迟和CPU的方式太贵了.

起初我对所有这些感到非常困惑,所以我写了一篇关于使用list属性简短教程.请享用 :)

  • 'IN'是"查找包含其中一个值的任何实体",它将被拆分为n"查找包含此精确值的任何实体"查询.但是,列表上的相等过滤器是后者 - "查找具有此精确值的任何实体(可能在列表中)",因此与IN查询相同的方式效率不高. (5认同)

use*_*576 7

我不知道它是否是社交应用程序的最佳设计,但是jaiku在谷歌被公司收购时被原始创建者移植到App Engine,所以它应该是合理的.

参见演员和老虎和熊,哦,我的!design_funument.txt中.实体在common/models.py中定义,查询在common/api.py中.