我正在实施一个小型社交网站,我正在尝试实施通知。
通知具有以下要求
以下是我想用MySQL实现的方法:
通知表:type_of_event
,event_id
,message
Notification_read表格:user_id
,notification_id
,read
Notification
表Notification_read
表格,其中包含新通知的ID&应收到通知的每个用户的ID(通知创建者的关注者)read
这个解决方案对我来说效率似乎非常低,因为每次发生通知时,通知都会多次写入notification_read
表(取决于用户拥有多少关注者)
有人可以告诉我是否有更好的解决方案来解决这个问题
答案 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,因为其他人往往更重量级。