我尝试在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 /秒!
谢谢,最诚挚的问候。
答案 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
。