使用可以在GAE数据存储区中相互发送消息的用户对系统建模

时间:2014-12-13 06:29:06

标签: java performance google-app-engine modeling

我想知道您是否可以帮我找到一种方法来在GAE数据存储区中对以下内容进行建模,使其具有可扩展性并且可以经常更新。我以为我有一个解决方案,我在 this question中表达过,但在等待回复的过程中,我意识到它可能过于复杂。我在下面解释了为什么我将它作为一个单独的问题保留。

问题: 构建一个系统,用户可以相互发送许多消息。每个用户都必须能够检索他们的消息 - 例如在线聊天。当用户可能在短时间内收到许多消息时,希望避免争用。

解决方案1: 如上所述here我想知道是否可以使用分片列表来实现这一点。我的意思是将消息存储为实体对象,发送者和接收者将这些对象的密钥(它们之间发送的消息)存储在列表中。我想到了分片,因为收到许多消息的用户必须经常更新列表,而分片方法可能会阻止数据存储争用。

问题 - 当说出用户收到的消息的密钥列表变大时会发生什么?会不会变得缓慢?我可以将列表分成几个实体,但这需要仔细考虑分配方案和检索方法。如果这是最好的方式,愿意这样做。

替代方法: 将消息存储为实体对象(如上所述),但这次让它们存储索引的属性(date,from,to等)。使用查询(日期大于...,来自= ...等)为用户检索消息。这可能会很好,但我担心 - 所有索引都会降级,因为它们会变得非常大,许多用户会发送许多消息吗?似乎它会降级为类似SQL的系统。

有什么想法吗?

我已经阅读了如何在GAE文档中建模复杂关系,但是他们使用python作为示例,我在抽象整体设计模式时遇到了问题。

非常感谢任何有此输入的人

PS目前直接使用低级数据存储区。

1 个答案:

答案 0 :(得分:0)

我之前创建了一个类似于此的系统。我选择实现它的方式是我创建了一个Conversation实体,它是许多Message实体的父实体。对话有两个参与者(尽管你可以做更多),每个参与者都是User实体的关键。

像这样(假设是)

@Entity public class Conversation {
    @Id Long id;
    @Index Key<User> participant1;
    @Index Key<User> participant2;
    @Index String participant1ExternalId;
    @Index String participant2ExternalId;
}

@Entity public class Message {
    @Id Long id;
    @Parent Ref<Conversation> conversation;
    @Index String senderExternalId;
    @Index String recipientExternalId;
    String message;        
}

通过这种方式,您可以以最一致的方式查询参与者的所有会话,以及以强烈一致的方式接收或发送(或两者)对话的所有消息。我有一个额外的要求,即用户无法识别彼此,因此使用的消息生成了UUID(externalId属性)。

因此,通过这种方式,分片和1写/秒限制适用于会话级别。您可以将未读的计数器放在每个用户的会话对象上,或者如果需要,可以在每条消息上放置(在争用级别它没有真正的区别,所以无论什么都是最有意义的。)

如果您的用户每次会话每秒定期超过1条消息,那么除了数据存储区争用之外,您还需要解决许多其他问题,因此它可能是一个很好的起点。在一般情况下,最终的一致性对于这种操作(即检查新消息)非常有效,因此您可以严重依赖它。