我正在开发的应用程序有一个活动源,每个用户都可以在其中看到他们朋友的活动(很像 Facebook)。我正在寻找一种适度可扩展的方式来动态显示给定用户的活动流。我说“适度”是因为我希望只用一个数据库(Postgresql)来做到这一点并且maybe内存缓存。例如,我希望此解决方案能够扩展到 20 万用户,每个用户有 100 个朋友。
目前,有一个主活动表,用于存储给定活动的渲染 html(Jim 添加了朋友,George 安装了应用程序等)。该主活动表保留源用户、html 和时间戳。
然后,有一个单独的(“连接”)表,它只保留一个指向应该在其朋友提要中看到此活动的人的指针,以及一个指向主活动表中的对象的指针。
因此,如果我有 100 个朋友,并且我进行 3 项活动,那么连接表将增长到 300 个项目。
显然这个表将会增长得非常快。不过,它有一个很好的特性,即向用户显示的获取活动需要单个(相对)便宜的查询。
另一种选择是只保留主活动表并通过如下方式查询它:
select * from activity where source_user in (1, 2, 44, 2423, ... my friend list)
这样做的缺点是您正在查询可能永远不会活跃的用户,并且随着您的朋友列表的增长,此查询可能会变得越来越慢。
我看到了双方的优点和缺点,但我想知道是否有一些人可以帮助我权衡选择并提出一种或另一种方式。我也愿意接受其他解决方案,尽管我想保持简单并且不安装 CouchDB 等之类的东西。
非常感谢!
我倾向于只拥有主活动表。如果你同意的话,这就是我会考虑实施的:
您可以创建多个活动表,并在从数据库获取数据时执行 UNION ALL。例如,每月滚动它们 - Activity_2010_02 等。仅以您的示例为例 - 20 万用户 x 100 个朋友 x 3 个活动 = 6000 万行。对于 PostgreSQL 来说,这不是性能方面的问题,但您可能会认为这纯粹是为了现在的方便,并最终是为了将来轻松扩展。
This has the disadvantage that you're querying for users who may never be active, and as your friend list grows, this query can get slower and slower.
您要显示entire活动提要,回到最初的时代?您在原始问题中没有提供太多详细信息,但我猜测您会显示按时间戳排序的最后 10/20/100 个项目。几个索引和 LIMIT 子句应该足以提供即时响应(因为我刚刚在包含大约 2000 万行的表上进行了测试)。在繁忙的服务器上它可能会变慢,但这应该通过硬件和缓存解决方案来解决,Postgres 不会成为那里的瓶颈。
即使您确实提供了可以追溯到黎明之时的活动源,paginate输出! LIMIT 子句将拯救你。如果带有 LIMIT 的基本查询还不够,或者您的用户有一长串不再活跃的朋友,您可以考虑将查找限制为最后一天/一周/一个月first and then提供好友 ID 列表:
select * from activity
where ts <= 123456789
and source_user in (1, 2, 44, 2423, ... my friend list)
如果您有一个跨越数月或数年的表,则好友 ID 的搜索将仅在第一个 WHERE 子句选择的行中执行。
这只是我在您现在考虑的两种解决方案之间进行选择的情况。我也会看看这样的事情:
重新考虑表的非规范化。存储预先生成的 HTML 输出真的是最好的方法吗?通过使用活动查找表并动态生成模板化输出,您的性能会更好吗?预生成的 HTML 乍一看似乎更好,但考虑到磁盘存储、API、未来的布局更改和存储 HTML 等因素可能毕竟没有那么有吸引力。查找表可以包含您可能的活动 - 添加朋友、更改状态等,如果另一个用户参与该活动,活动日志将引用该活动以及朋友的 ID。
Doing预生成 HTML,但不将其存储在数据库中。将内容保存在磁盘上作为预生成的页面。然而,这并不是灵丹妙药,很大程度上取决于网站上写入与读取的比率。 IE。公共论坛上的典型讨论线程可能有十几条消息,但可以被查看数百次 - 是缓存的良好候选者。然而,如果您的应用程序更适合即时状态更新,并且您必须在每几次视图后重新生成 HTML 页面并将其再次保存在磁盘上,那么这种方法就没有什么价值。
希望这可以帮助。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)