我正在为社交网络设计一个系统,在用户(如 Instagram)和他们可以发布的帖子之间建立“关注”关系。
如果用户 A 关注了用户 B,则用户 A 可以在其时间线上看到 B 的所有内容,而不管 B 是否也关注了 A。 但是,如果 B 决定将他的隐私设置设置为私有(private),用户 A 应该不能再看到用户 B 的内容。
我想为用户 Feeds/Timelines 使用扇出写入方法(推送方法),即:在 Redis 中存储他们关注的所有人的最新帖子。因此,当用户 A、B 和 C 都关注了用户 D,并且用户 D 发布了新帖子时,我更新了用户 A、B 和 C 的提要列表。这有助于在 O(1) 中为他们每个人获取提要,这很好。
但是,如果用户 D 将他的隐私设置设置为“私有(private)”,并且他只关注用户 B,这意味着现在应该只有用户 B 能够看到他的内容。所以我需要从redis中的用户A和C的列表中删除用户D的内容。
但是这样是不是太不靠谱了?如果我们有很多用户和很多关注者,我们是否可以得到一个边缘案例,在 Redis 完成更新他们的提要列表之前,用户仍然可以看到他们在一段时间内不应该看到的内容?
另外,这意味着如果用户相互关注或只有一个用户关注另一个,我也应该将信息存储在redis中。
它是如何在“现实世界”(twitter、facebook、instagram ....)中实现的,我是否遗漏了什么?
最佳答案
简单的答案:
这是完全可靠的,因为 redis 操作是原子操作,如果您正确使用它,则没有用户能够看到被隐私设置隐藏的内容。
更长的答案:
不可扩展: 如果以后你的网络增长,这个不行,redis是单线程的,redis会把所有的东西都存到内存里。
空间效率不高:如果您在图形中思考,您建议将内容列表存储在边缘而不是节点上。假设一个人平均有 f
个关注者,您的方法将存储 f
倍的数据,对于典型的社交网络,它可能是 100 倍以上。
它会降低写入速度:您正试图通过避免读取所有关注者来加快访问速度。现在,当有人发布内容时,您平均必须编写 f
个副本。如果这锁定了一些可能会延迟一切的表。
这可以通过 isomg 数据库有效地完成:如果您有一个带有主键 (u1, u2) 的表连接,表明 u1 跟在 u2 之后。包含列 (u, p) 的表 user_privacy,主键在 u 上,表示你有隐私设置 one
你可以让我没有关注的用户关注我
select t1.u2 from connections e1 -- I follow
-- e2 Follows me back
left join connections e2 on e2.u1 = e1.u2 and e2.u2 = e1.u1
inner join user_privacy up on up.u = e1.u2
where e1.u2 = (myself) and (e2.u1 is NULL or up.p)
-- e2.u1 is null if user does not follows me back
从这个用户列表中,如果您有一个包含 (post_id, user, date) 和索引 (user, date) 的帖子表,您可以轻松地在一个时间间隔内获取日期的帖子。 然后你不断改变间隔,直到你加载足够的帖子和滚动。
关于您对时间的担忧,我认为没关系,如果内容曾经对用户 A 可用,出于多种原因,它仍然可以看到它。例如它没有重新加载提要、缓存,或者他甚至可以复制内容。
关于database - 使用扇出写入方法根据隐私设置(PostgreSQL、Redis)更新 Feed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58035152/