构建通知系统

我正在为我们的页面(社交游戏类型)构建一个 Facebook 风格的通知系统,现在我正在研究设计这种系统的最佳方法。我对如何向用户推送通知或类似的东西不感兴趣(现在甚至不感兴趣)。我正在研究如何在服务器上构建系统(如何存储通知,在哪里存储通知,如何获取通知等等)。.).

所以,我们有一些要求:

  • 在高峰时期,我们有大约1000个并发登录用户(还有更多的客户,但他们在这里并不重要,因为他们不会有通知) ,这将生成许多事件
  • 会有不同类型的通知(用户 A 加你为好友,用户 B 在你的个人资料上发表评论,用户 C 喜欢你的图片,用户 D 在游戏 X 上击败了你,...)
  • 大多数事件将为1个用户生成1个通知(用户 X 喜欢您的图像) ,但是在某些情况下,一个事件将生成多个通知(例如,用户 Y 的生日)
  • 通知应该组合在一起; 例如,如果四个不同的用户喜欢某个图像,该图像的所有者应该得到一个通知,说明四个用户喜欢该图像,而不是四个独立的通知(就像 FB 做的那样)

我想的是,我应该创建一个队列在事件发生的时候存储它们。然后我会有一个背景工作(Gearman?)它将查看该队列并根据这些事件生成通知。然后,这个作业将在数据库中为每个用户存储通知(因此,如果一个事件影响10个用户,将有10个单独的通知)。然后当用户打开一个有通知列表的页面时,我会为他阅读所有这些通知(我们正在考虑将其限制在100个最新通知) ,并将它们组合在一起,最后显示它们。

关于这种方法,我关心的是:

  • 非常复杂:)
  • 是数据库最好的存储在这里(我们正在使用 MySQL)或者我应该使用其他东西(重排似乎是一个很好的适合太)
  • 我应该存储什么作为通知?用户 ID,发起事件的用户 ID,事件的类型(这样我就可以将它们分组并显示适当的文本) ,但是我有点不知道如何存储通知的实际数据(例如,喜欢的图片的 URL 和标题)。当我生成通知时,我是应该“烘烤”这些信息,还是应该存储受影响的记录(图像、配置文件、 ...)的 ID,并在显示通知时从数据库中提取信息。
  • 这里的性能应该没问题,即使在显示通知页面时,我必须处理100个即时通知
  • 每个请求都可能出现性能问题,因为我必须向用户显示未读通知的数量(这本身就是一个问题,因为我要将通知分组在一起)。不过,如果我在后台生成通知视图(通知分组的位置) ,而不是动态生成,就可以避免这种情况

那么你对我提出的解决方案和我的担忧有什么看法?如果你认为我应该提及任何其他与此相关的事情,请予以评论。

哦,我们正在使用 PHP 作为我们的页面,但我认为这不应该是一个很大的因素。

63609 次浏览

这确实是一个抽象的问题,所以我想我们只需要讨论它,而不是指出你应该做什么或不应该做什么。

关于你的担忧,我是这么想的:

  • 是的,通知系统很复杂,但不是地狱。您可以使用许多不同的方法来建模和实现这样的系统,它们的复杂程度可以从中等到高等;

  • 就个人而言,我总是试图让东西数据库驱动。为什么?因为我可以保证完全控制正在发生的一切但那只是我,你可以控制没有数据库驱动的方法相信我,你会想要控制这个案子的

  • 让我给你举个真实的例子,这样你就可以从某个地方开始了。在过去的一年里,我已经在某种社交网络上建立并实现了一个通知系统(当然,不像 facebook)。就像我以前把通知存在那里一样?我有一个 notifications表,其中保存了 generator_user_id(生成通知的用户的 ID)和 target_user_id(很明显,不是吗?)notification_type_id(引用到具有通知类型的不同表) ,以及我们需要用来填充表的所有必要内容(时间戳、标志等)。我的 notification_types表过去与 notification_templates表有关联,notification_templates表存储每种通知类型的特定模板。例如,我有一个 POST_REPLY类型,它有一个类似于 {USER} HAS REPLIED ONE OF YOUR #POSTS的模板。从那里,我只是把 {}作为一个变量和 #作为一个参考链接;

  • 是的,性能 应该必须的是好的。当您想到通知时,您会想到服务器从头到脚的推动。不管你是用 Ajax 请求还是什么,你都要担心性能。但我认为这是第二次担心了;

我设计的这个模型,当然,不是你唯一可以遵循的,也不是最好的。我希望我的回答,至少能让你找到正确的方向。

通知是关于某事(对象 = 事件,友谊。.)被改变(动词 = 添加,请求)。.)由某人(演员)报告给用户(主体)。下面是一个规范化的数据结构(尽管我使用了 MongoDB)。您需要将更改通知给某些用户。所以这是每个用户的通知。.这意味着如果涉及到100个用户,您将生成100个通知。

╔═════════════╗      ╔═══════════════════╗      ╔════════════════════╗
║notification ║      ║notification_object║      ║notification_change ║
╟─────────────╢      ╟───────────────────╢      ╟────────────────────╢
║ID           ║—1:n—→║ID                 ║—1:n—→║ID                  ║
║userID       ║      ║notificationID     ║      ║notificationObjectID║
╚═════════════╝      ║object             ║      ║verb                ║
╚═══════════════════╝      ║actor               ║
╚════════════════════╝

(添加您认为合适的时间域)

这基本上是为了对每个对象的更改进行分组,因此您可以说“您有3个好友请求”。每个参与者分组是有用的,这样你就可以说“用户詹姆斯 · 邦德在你的床上做了改变”。这还提供了随心所欲地翻译和计算通知的能力。

但是,由于 object 只是一个 ID,所以您需要通过单独的调用获得所有关于 object 的额外信息,除非 object 实际上发生了变化,并且您希望显示该历史记录(例如“ user change title of event to...”)

由于通知对于站点上的用户来说几乎是实时的,所以我会将它们与 nodejs + websockets 客户端绑定,并且当添加更改时,php 会将更新推送到所有侦听器的 nodejs。

╔════════════════════╗
║notification        ║
╟────────────────────╢
║Username            ║
║Object              ║
║verb                ║
║actor               ║
║isRead              ║
╚════════════════════╝

这看起来是一个很好的答案,而不是有2个集合。你可以通过用户名、对象和 isRead 查询获取新事件(比如3个待处理的好友请求、4个问题等等)。.)

如果这个模式有问题,请告诉我。

我个人不太理解接受答案的图表,所以我将附上一个数据库图表基础上,我可以从接受答案和其他页面学到什么。

enter image description here

改进很受欢迎。