社交网站如何处理通知

时间:2014-06-05 21:03:07

标签: ruby-on-rails facebook notifications social-networking

我正在实施一个小型社交网站,我正在尝试实施通知。

通知具有以下要求

  • 所有用户都会在他们关注的用户执行某些活动时收到通知(更改个人资料图片,如帖子,创建帖子,发表评论等等)
  • 通知状态为已读或未读(如facebook和stackoverflow)。当用户的一组通知未读时,就像Facebook一样,用户将继续在其导航栏上看到阅读通知图标

以下是我想用MySQL实现的方法:

通知表type_of_eventevent_idmessage Notification_read表格user_idnotification_idread

  • 每当用户执行触发要发送通知的事件时 对于所有关注者,该通知存储在Notification
  • 将为新创建的通知填写Notification_read表格,其中包含新通知的ID&应收到通知的每个用户的ID(通知创建者的关注者)
  • 每当用户收到通知并阅读通知时,通知都会标记为read

这个解决方案对我来说效率似乎非常低,因为每次发生通知时,通知都会多次写入notification_read表(取决于用户拥有多少关注者)

有人可以告诉我是否有更好的解决方案来解决这个问题

4 个答案:

答案 0 :(得分:5)

由于存在这些问题,通常需要权衡与写作。

在这种情况下,写入可以表示将通知写入数据库所需的时间和存储成本。

对于阅读,它是关于您为特定用户获取通知的速度。

在@kecebongsoft的例子中,你的写作效率非常高(因为相对较少的字段),但是读取需要花费很多时间。在数据库的文本字段中搜索通常很慢。对于用户,如果列出了用户,则必须检查所有通知及其检查字段,如果是,则状态是什么。

通过为每个用户存储单独的通知,可以增加存储空间,但是您在阅读方面获得了很多收益。也就是说,因为您可以使用用户ID搜索索引表,并快速查找任何通知及其状态。

当然,有非常复杂的混合方法。但一般来说,大型网站并不想告诉这些秘密:)

如果您从一个网站开始,我不会担心写作费用。使用许多通知填充表格并不昂贵。最后,他们可能都相对较小。你甚至可以考虑修剪旧的通知。

更重要的是阅读速度。发现您网站的人不会对您的高效存储适配器留下深刻印象,但会在收到通知时注意到照明速度。

我的建议:现在关注读取速度,以及何时扩大对存储效率的担忧。

最后注意:如果您在创建通知时创建了大量数据库条目,请查看从主Web服务器线程调度的解决方案。这样,创建通知的人可以快速继续,您可以在后台执行昂贵的SQL工作。速度更快!

答案 1 :(得分:2)

您可以序列化活动的收件人并将其存储在字段中。这样,无论追随者多少,一个事件的通知总是一个。

Actor   ObjectType    ObjectID  Date        Recipients
--------------------------------------------------------------------------------------
UserA   Post          1         2014-03-02  [
                                            {'u': 1, 'r': False, 'dr': None},
                                            {'u': 2, 'r': True, 'dr': '2013-03-02'},
                                            {'u': 3, 'r': False, 'dr': None},
                                            {'u': 4, 'r': False, 'dr': None},
                                            ]
UserB   Photo         2         2014-03-02  [
                                            {'u': 4, 'r': False, 'dr': None},
                                            {'u': 5, 'r': True, 'dr': '2013-03-02'},
                                            {'u': 6, 'r': False, 'dr': None},
                                            {'u': 8, 'r': False, 'dr': None},
                                            ]

u是收件人ID,r是读取标志,dr是读取日期。这样你仍然可以进行一些查找(例如:显示UserB的通知),而不需要做很多I / O,但你必须创建帮助程序类来对你的通知进行后期处理,这可能不会花费太多的时间。 LOC和CPU资源。

但是在你这样做之前,再想一想你的“低效率”问题,是关于阅读?如果是的话,正确的索引读取应该不是问题,如果你有适当的索引和查询,像MySQL和Postgres这样的数据库可以处理数百万(甚至数千万)行。如果关注的是写作,您可以将其作为后台任务,让用户继续他们的活动而不被进程阻止。上面的解决方案可能会给你较少的I / O,但它会牺牲简单性,特别是当你想在将来重新访问或扩展该功能时。

答案 2 :(得分:0)

您可以使用has_many through关联。它完全符合这种情况。此外,您可以将模型通知belongs_to :event和事件类型存储在事件模型中。您可以在http://guides.rubyonrails.org/association_basics.html

查看更多相关信息

答案 3 :(得分:0)

像您正在谈论的大型网站通常使用异步消息代理和协议,如ActiveMQ,RabbitMQ等,使用JMS,STOMP,AMQP,MQTT等协议,列表就是这样等等。

无论如何,我可能会如何实现这样的事情,即每个用户会话都有一种订阅其相应用户通知队列的消息监听器。根据所讨论的协议将决定一个人将如何做到这一点,但最简单的方法是让每个用户获得自己的队列。消息代理倾向于通过文件系统和日志文件的组合来处理消息持久性,这些文件系统和日志文件比关系数据库快得多(考虑一下;这些数据不是关系)。

由于这是Ruby而你并没有说你正在使用JRuby,你选择的消息可能属于STOMP或MQTT,因为其他人往往更重量级。