【问题标题】:JPA: Message + Notification DB ArchitectureJPA:消息+通知数据库架构
【发布时间】:2026-02-24 08:15:02
【问题描述】:

所以我正在为办公室、前端、后端、移动性、客户帐户、在线注册、员工帐户、管理员帐户构建一个 Web 应用程序......整个九码。

我主要关心的一个问题(因为我以前没有做过)是用户实体交互。 目前我已经定义了 4 种方法,用户实体可以通过这些方法与其他用户进行交互。

1) 消息(来自用户...到单个或多个用户)

2) 通知(从后端到用户)

3) 任务(到和从用户...到单个或多个用户)

4) 邀请(来自用户...对单个或多个用户)

(将引入一个 XMPP 聊天引擎,需要记录,但那将在稍后说明)

我认为为每种类型实现一个 com 协议会很离谱,所以我创建了一个抽象层(请不要因为那个而杀了我,但这就是我的感受)

所以在每个用户中都会有 2 个密钥列表

 private <Key> Sent_Parcels;
 private <Key> Received_Parcels;

这些只是指向包裹实体(抽象层)的数组列表,其中将包含

private Key Sender;   // Key of Sender User Entity
private List<Key>Recipients;   // List of Keys of Recipients
private Type type;   // Enum of Type : Message, Notification, Task, Invitation
private Key Payload;   // Key of the payload object: Message Entity, Notification Entity ...

现在标准的创建、持久性、通知的东西......完全不用担心,因为它是一个单一的 com 协议,适用于不同的有效负载......从这一点开始不关心,因为我可以按 Parcel Type 过滤所以......

但是,这里有一些主要问题(记住大规模实施):

1) 假设发件人和所有收件人决定删除有效负载。这意味着创建指向此有效负载的所有 Parcel 实体都已消失……我如何找到任何人都不再需要的有效负载来删除它们并在 GAE 数据存储上节省宝贵、昂贵的存储空间。

2) 我很确定在用户之间实现一个 com 系统并不是那么简单,所以如果某个该主题的专家能过来告诉我这完全是垃圾,我会很高兴,这就是它的完成方式。

3) 我之所以选择这种方法,是因为对于 com 操作中的每个用户参与者而言,具有重复的小包裹实体、单个有效负载优于具有重复的 LARGE 有效负载(完全相同)。但是,拥有重复的有效载荷将意味着如果用户删除它,很好,很好,不必去挖掘仍然拥有有效载荷的人,因为他是唯一拥有它的实体,另一方面,我觉得这太浪费了空间

欢迎所有 cmets 和建议...非常感谢大家的一切!

【问题讨论】:

  • 忘记了重要的事情!! ...实现之前阅读/仍然是新的东西会非常好......比如电子邮件。因此,关于如何完成该主题的任何想法......将是超级超级好添加在包裹打开时向发件人发送通知的功能
  • 发送通知:这只是在收件人打开“包裹”时以编程方式创建新通知

标签: java entity-framework google-app-engine jpa google-cloud-datastore


【解决方案1】:

虽然我无论如何都不是“com 系统专家”,但我可能会在数据存储方面为您提供帮助。

您现在正在做的是将关系数据模型放入数据存储区 -> 有什么意义? 数据存储在“连接”方面并不比 RDBMS 快,实际上您将不得不花费大部分时间来获取“关系”。

根据您使用的数据库系统,您需要从两个不同的角度看待您的问题:

  • 关系数据库:包裹是您的基础实体,您可以创建将其与用户关联的关系。只有当有人删除包裹时,您才会删除包裹和用户之间的“链接”。

  • Datastore:User 是您的基本实体,Parcels 仅从用户的角度存在:已发送包裹,已收到包裹。将其视为您的 Gmail 客户端:发件人的“已发送邮件”和收件人的“收件箱”中实际上重复出现了相同的“电子邮件”。如果发件人删除了邮件,对收件人没有影响,反之亦然。

在我看来,您处于明确的“SQL”和“NoSQL”之间的这个奇怪区域,如果不彻底考虑同样的老问题,我不会提交数据存储区:您的用例是什么? :)


如果您正在制作一个面向用户的消息应用程序,例如 whatsapp 或 doodle

由于可扩展性,数据存储是一个不错的选择。 您的观点 3) 是最好的方法:您需要复制您的数据,这样您就可以为给定的用户快速检索它,而无需加入。

/** Root entity : user */
@Entity
class User {
   @Id
   Key key;

   @Basic
   String name;

   @OneToMany
   List<UserReceivedParcel> inbox;

   @OneToMany
   List<UserSentParcel> sent;
}

/** User's child entity : Received parcels */
class UserReceivedParcel {
   @Id
   Key userReicevedParcelKey;

   /** Sender key AND duplicate properties to prevent running another query */
   @Persistent String senderKey;
   @Persistent String senderName;


   @Persistent String parcelType;
   /** Message data */
   @Persistent String messageContent;
   @Persistent Date sentDate;
}

/** User's child entity : Sent parcels */
class UserSentParcel {

   /** Recipient Key AND Attributes */
   @Persistent String recipientKey;
   @Persistent String recipientName;

   /** ... (message data) */

}

如果您正在制作公司消息系统

您可能需要运行查询并建立各个方向的关系。 Google Cloud SQL(或任何其他 RDBMS)实际上可能更合适……尤其是因为可以通过良好的设计来处理规模。不要低估在没有对数据存储区进行 SQL 查询的情况下生成报告的成本。

【讨论】:

  • 非常感谢您的宝贵意见!!考虑到您的建议,我可能会坚持用户通信的数据存储选项,但由于您似乎比我对 SQL 与 NoSQL 的掌握更牢固,我真正的噩梦是业务分析。还将有一个在线商店,它将根据个人资料标准、人口统计数据等向用户展示广告。还有用于电子邮件分析的智能系统(通过电子邮件传单发送的产品的成功率),它应该根据以前的经验填充最佳配置文件以针对某些产品。
  • 所以我真的很想讨论一些细节并获得有关一般架构方面的建议。我在这里不需要火箭科学 NASA 的东西,只需一个足够体面的模型即可开始,而无需从 IBM 获得现场解决方案
  • 这是一项艰巨的任务,我希望你有一个很好的团队!井分析和“NoSQL”数据存储是“大数据”问题的核心。您需要意识到的是,您在数据存储(以及大多数所谓的“NoSQL”数据库)上的数据处理的主要部分将是手动的:为了清楚起见,您必须将某种工作放在一起以编程方式查询您的实体,解析,处理,求和,无论你需要什么。也许看看 MapReduce:code.google.com/p/appengine-mapreduce
【解决方案2】:

您似乎在重新发明一个名为电子邮件的*,带有附件和协作软件;-)

1) 考虑将删除实现为移动到“垃圾箱”收件人,以简化要删除的跟踪项目。 Blobstore 更适合大型“包裹”(附件),为元数据留出充足的 Datastore 空间。

2) 不知道你所说的 com 协议是什么意思。沟通?零件? REST 和 JSON 在客户端-服务器链接中越来越流行。频道将是 AppEngine 提供实时推送通知的方式。

3) 除了视频文件等极端情况外,空间比处理时间或带宽更便宜。 NoSQL 方法是将数据复制到每个收件人的副本中,以避免查找或连接操作。实施每个收件人的存储配额,以防止他们的空间使用量无休止地增长。

【讨论】:

  • 首先感谢您的洞察力!我喜欢垃圾桶的想法(老实说,因为没有单独解决这个问题而感到有点愚蠢)。还想知道是否有一个可定制的 java 框架来运行本地电子邮件服务器(不通过外部服务器,也不接收外部服务器的邮件......你明白我的意思)
  • 第三,我提到通信操作,它只是我正在使用的进程名称(对不起,如果它意味着其他东西)......我正在使用REST和JSON,但是我不确定Channels是否提供上游(是吗??)我虽然首先使用 strophe 实现客户端 xmpp 用于实时通知,然后作为聊天的基础......第三,所有 3 个(用户 A 与用户 B 和我的通知服务器聊天)可能是登录到第三方免费的 jabber/xmpp 服务器,从而减少了我的账单,而不是全部本地化(所以基本上是外包聊天)......你怎么看??