客观化列表一个实体的一致性

时间:2015-06-04 14:27:32

标签: google-app-engine google-cloud-datastore objectify

我尝试在App Engine上为我的Android应用程序制作聊天解决方案。 决定不将保存所有消息发送到像ChatMessage这样的分离实体中的主题,而是将其保存在Topic实体内的字符串列表中,如下所示:

@Entity
public class Topic {
    @Id
    public String id;
    public List<Long> users = new ArrayList<Long>(2);
    public Long lastChangeTime;
    public LinkedList<String> messages = new LinkedList<String>();
}

我想到了这一点,因为通常为每条消息存储主题id比消息字符串本身更多的数据。 :S 我不知道的是,这个列表是否可以保持一致? 这是我向主题添加新消息的方式:

    // 2. get topic if it exists or create a new if not
    Topic topic = ofy().load().key(Key.create(Topic.class, topicId)).now();
    if (topic == null) {
        topic = new Topic(senderId, recipientId);
    }

    // 3. add message
    // this method adds the new string into the topic and update the 
    // last change time
    topic.addMessage(senderId, recipientId, send.message);

    // 4. save topic & the new message
    ofy().save().entity(topic).now();

因此,如果两个用户同时发送消息,是否会发生第一个用户加载主题,添加他的消息,但同时第二个用户已经加载了主题(没有第一个用户&#39; s消息)并添加他自己的新消息。首先保存主题。但是第二个覆盖了第一个用户的先前保存吗?或者会发生什么?

如果可能发生,我怎么能避免这种情况,请记住它是一个高写入率的实体,所以我需要更多的写入而不是1 /秒!

谢谢,最诚挚的问候。

1 个答案:

答案 0 :(得分:0)

  

我不知道的是,这个列表是否可以保持一致?

Consistency由实体组和查询决定,而不是属性。

  

因此,如果两个用户同时发送消息,是否会发生第一个用户加载主题,添加他的消息,但同时第二个用户已经加载了主题(没有第一个用户&#39; s消息)并添加他自己的新消息。首先保存主题。但是第二个覆盖了第一个用户的先前保存吗?或者会发生什么?

您需要在transaction内执行此操作。如果在事务中抛出ConcurrentModificationException(您的示例场景),Objectify将为您重试。

但是,为避免争用,您需要更改数据模型。您可以拥有Message类和Topic,如下所示:

@Entity
public class Topic {
    @Id
    String id;
    List<Long> users = new ArrayList<Long>(2);
    Long lastChangeTime;
}

引用一个或多个主题的消息(我在这里做出假设):

@Entity
public class Message {
    @Id
    Long id;
    Long lastChangeTime;
    @Index
    Ref<Topic> topic;
}

@Index上的topic注释将允许您通过Message查询topic。如果您的消息可以包含多个主题,则可以将Ref<Topic>更改为List