社交网络通知逻辑
Posted
技术标签:
【中文标题】社交网络通知逻辑【英文标题】:Social network notifications logic 【发布时间】:2014-09-14 02:59:22 【问题描述】:我正在开发某种社交网络。类似于twitter/instagram,有用户,可以互相关注,发帖,写cmets,点赞。
我已经实现了一个通知系统,用户可以在其中获取有关他关注的人的活动的信息(他们喜欢什么和评论什么)。
我为此使用了 mysql 查询。 这是查询的简化版本:
SELECT t.type, t.param1, t.param2, t.date_time FROM (
SELECT 'like' as type,
likes.user_id as param1,
likes.user_name as param2,
likes.date_time as date_time,
FROM likes
WHERE (SOME CONDITION GOES HERE)
UNION ALL
SELECT 'comment' as type,
comments.user_id as param1,
comments.user_name as param2,
comments.date_time as date_time,
FROM comments
WHERE (SOME CONDITION GOES HERE)
) as t ORDER BY t.date_time ASC
一切正常。
我下一步要做的是向用户显示他收到了多少新通知。
为此,我有一个解决方案,我想问您它是否可行/有效,或者您是否知道如何更好地实施它。
所以,解决方案是: 我将在用户表中创建一个字段“total_notifications”。 每次用户访问网站时,我都会获取 mysql 计数所有通知和 如果通知多于用户字段,我会将它们之间的差异显示为“新”。
换句话说,每次用户访问网站时都会调用上面编写的那种查询,但SELECT t.type
将不是SELECT count(*)
。
我知道这对数据库来说是一项繁重的工作,所以有没有其他解决方案或者这样可以吗?
【问题讨论】:
【参考方案1】:好吧,创建一个名为 notification 的新表,存储用户 id、通知类型、内容、seen 字段(bool)
然后,当任何事情发生时,将所需的值添加到此表中。
然后在用户检查网站时做一个
SELECT COUNT(*) WHERE user_id= current user id AND seen = 0.
然后将所有这些字段的值设为 1,以将它们标记为用户可见。
我希望我能理解你的问题。
【讨论】:
【参考方案2】:首先,带有 WHERE 的 SELECT count(*) 将扫描整个表/索引以返回计数。如果表有一个适合查询的覆盖索引,它基本上会非常快,因为它只扫描索引。否则,它会扫描整个表然后非常糟糕。对于您的 total_notifications 问题,您必须进行 2 次查询并比较值以获得“新”。问题是你只想得到“新的”,它假设是所有活动的一小部分,但如果你明白我的意思,它必须获取这个查询中的所有活动行。我建议您添加一个新字段名称“status”,其值如(“new”、“read”)。你也应该在覆盖索引中索引这个字段。为了获得“新”,您只能运行 1 个查询来过滤具有状态 ='new' 的行。有一个好的索引,这个查询会非常快,它假设扫描索引的一小部分。
SELECT count(*) as t_new FROM (
SELECT 'like' as type
FROM likes
WHERE (SOME CONDITION GOES HERE) AND status='New'
UNION ALL
SELECT 'comment' as type
FROM comments
WHERE (SOME CONDITION GOES HERE) AND status='New'
) as t
我相信您甚至可以通过将“date_time > timestamp_of_last_activity_user_seen”添加到 WHERE 来改进此查询。
【讨论】:
由于您没有特别提及,您应该将状态创建为枚举,以便与 char/varchar(扫描时间更长)相比,将其存储为字节值。 是的,作为 ENUM 的状态更好,谢谢@trick。更适合索引 非常感谢您的回复。我理解你,但你看,所有这些活动都是伪通知,表中的这些记录(cmets,likes)只是用户的活动,不能有“新”或“读”这样的字段,因为如果一个用户阅读它们将影响关注此用户的所有其他用户,并且他们不会收到这些新通知。另一种方法是按照 Ramy Tamer 的建议创建表“通知”(谢谢顺便说一句),但我认为这对 DB 来说更重,因为如果一个用户进行活动,我需要为每个关注他的人创建记录. 所以它不仅会增加数据库数据的大小,还会增加它。 @wolfdale 我现在看到你的问题了。您可能需要每个用户的每个表,其中包含 activity_id 和状态。 InnoDB 最多允许 4B 表,应该可以工作并且负载性能应该没问题。读取时将数据交易与性能相乘。不过我建议你也试试 redis。每个用户都有自己的 redis 列表,这就是 Twitter 的做法,他们有一个扇出进程,可以写入所有后续用户的 redis 列表。以上是关于社交网络通知逻辑的主要内容,如果未能解决你的问题,请参考以下文章