社交应用程序的数据库设计和优化注意事项

Posted

技术标签:

【中文标题】社交应用程序的数据库设计和优化注意事项【英文标题】:DB design and optimization considerations for a social application 【发布时间】:2011-07-23 10:55:31 【问题描述】:

通常情况。我有一个简单的应用程序,可以让人们上传照片并关注其他人。结果,每个用户都会有类似“墙”或“活动源”的东西,他或她可以在其中看到从他/她的朋友(他或她关注的人)上传的最新照片。

大部分功能都很容易实现。但是,当涉及到这个历史活动提要时,由于纯粹的性能原因,事情很容易变得一团糟。

我在这里遇到了以下困境: 我可以轻松地将活动提要设计为数据库的规范化部分,这将节省我的写作周期,但在为每个用户选择这些结果时会大大增加复杂性(对于在特定时间段内上传的每张照片,选择一定数量,我关注的上传者/对于我关注的每个人,选择他的照片)

一个优化选项可以是引入一系列阈值约束,例如,允许我根据他们上次上传的日期对我关注的人进行排序,甚至排除一些人,以节省周期,以及每个用户,仅选择 5(例如)最后上传的照片。

第二种方法是为活动提要引入一个完全非规范化的架构,其中每一行都代表我的一个关注者的通知。这意味着每次我上传照片时,数据库都会在这个“drop bucket”中放入 n 行,n 表示我关注的人数,即大量的写作周期。不过,如果我有这样的表,我可以轻松应用一些优化技术,例如智能索引,以及修剪超过特定时间段的条目(队列)。

然而,我想到的第三种方法甚至是一种非规范化程度较低的模式,其中服务器端应用程序将从数据库中移除部分复杂性。我看到一些社交应用程序,例如friendfeed,严重依赖于数据库中JSON 对象等序列化对象的存储。

我肯定还在掌握可扩展数据库设计的技能,所以我确信我错过了很多东西,或者仍然需要学习。如果有人能给我指出正确的方向,我将不胜感激。

【问题讨论】:

我不太擅长数据库优化,但您可能需要一个非 SQL 数据库(看看 Cassandra 和 MongoDB)。实际上,在那种情况下,它们似乎真的更快。 (想想 facebook,使用 cassandra 作为主要 dbms :D) 有没有关于设计可扩展数据库(用于社交应用和 MMO)主题的好书? 只是想知道,除了可扩展的数据库和数据检索之外,您在设计此类应用程序时是否遇到任何其他问题..您选择哪种框架、语言来开发此类应用程序。 ..实际上我问过类似的问题:- ***.com/questions/4842276/… 【参考方案1】:

如果您的申请成功,那么您的读取次数肯定会多于写入次数 - 我只上传一次照片(写入),但我的每个朋友都会在刷新他们的提要时阅读它。因此,您应该针对指向非规范化模式方向的快速读取而不是快速写入进行优化。

这里的问题是,如果您拥有大量用户,您创建的数据量可能会很快失控。数据库上很难查询非常大的表,因此再次存在潜在的性能问题。 (还有足够存储空间的问题,但这更容易解决)。

如果按照您的建议,您可以在一定时间后删除行,那么这可能是一个很好的解决方案。随着您的成长和遇到性能问题,您可以减少该时间量(最多)。

关于存储序列化对象,如果这些对象是不可变的(写入后不会更改它们)并且不需要对它们进行索引或查询,这是一个不错的选择。请注意,如果您对数据进行非规范化,则可能意味着您有一个用于活动源的表。在那种情况下,我发现存储 blob 几乎没有什么好处。 如果您采用序列化对象的方式,请考虑使用一些 NoSQL 解决方案,例如 CouchDB - 它们针对处理此类数据进行了更好的优化,因此原则上您应该在相同的硬件设置下获得更好的性能。 请注意,我并不是建议您将所有数据移至 NoSQL - 仅用于它是更好解决方案的那部分。

最后,根据经验说一句警告:构建可扩展的应用程序很困难,而且需要花时间更好地花在其他地方。您应该花时间担心如何让数百万用户使用您的应用程序,然后再担心如何为数百万用户提供服务——首先是更困难的问题。当您取得巨大成功时,您可以重新架构和重建您的应用程序。

【讨论】:

+1 获得数百万用户然后担心扩展,而不是构建一个很少人使用的可扩展应用程序。【参考方案2】:

你可以有很多选择

添加更多硬件、内存、CPU -- Enter cloud hosting Hows 24GB of memory sound? 大多数重要访问的数据库信息都可以放在内存中。 选择具有可扩展SSD的主机。 在您的应用程序中使用基于事件的系统来编写所有用户的“历史”。所以它会像这样:id, user_id, event_name, date, event_parameters' -- 一个例子是:1, 8, CHANGED_PROFILE_PICTURE, 26-03-2011 12:34, <id of picture> 并且最重要的是,这个表将在内存中。不再需要担心写入性能。在记录过去(即 3 天)之后,如果用户选择返回那么远,它们可以被清除到另一个表(在非内存中)并包含在查询结果中。通过将所有这些都放在一个表中,您无需执行多个查询和 SELECT 来构建这些信息。 Consider using INNODB 用于历史记录/提要表。

值得阅读的好资源

Exploring the software behind Facebook, the world’s largest site Digg: 4000% Performance Increase by Sorting in php Rather than mysql Caching & Performance: Lessons from Facebook

【讨论】:

【参考方案3】:

我可能会从使用规范化模式开始,以便您可以快速而紧凑地编写。然后使用非事务性(无锁定)读取将信息拉回,确保使用游标,以便您可以在结果返回时处理结果,而不是等待整个结果集。由于这些信息听起来没有任何特别重要的含义,因此您实际上不必担心锁定通常会使您远离事务性读取的问题。

【讨论】:

【参考方案4】:

这些问题是目前使用 NOSql 解决方案的原因。我在之前的项目中所做的非常简单。我不保留用户->墙用户->历史,它在内存存储中包含纯粹的提要'id(我最喜欢的是redis)。所以在每次插入时,我都会对数据库进行 1 次插入操作,并在内存存储中进行(n*read 优化)插入操作。我设计内存存储来优化我的读取。如果我想过滤视频的用户历史记录(或墙),我将推送 feedid 放到类似 user::userid::wall::videos 的列表中。

当然,您也可以纯粹在内存存储中构建系统,但有 2 个系统做他们最擅长的事情,这很好。

编辑: 查看这些应用程序以获得一个想法:

http://retwis.antirez.com/

http://twissandra.com/

【讨论】:

【参考方案5】:

我正在阅读越来越多的关于 NoSQL 解决方案和建议的人,但是没有人提到这种选择的缺点。 对我来说最明显的是缺乏交易 - 想象一下,如果您不时丢失一些记录(有案例报告这种情况经常发生)。

但是,令我惊讶的是,没有人提到 MySQL 被用作 NoSQL - here's a link for some reading。

最后,无论您选择哪种解决方案(关系数据库或 NoSQL 存储),它们都以类似的方式扩展 - 通过跨网络分片数据(当然,有更多选择,但这是最明显的一种)。由于 NoSQL 的工作量较少(没有 SQL 层,因此 CPU 周期不会浪费在解释 SQL 上),因此速度更快,但也可以达到顶峰。

正如Elad 已经指出的那样 - 构建一个从一开始就可扩展的应用程序是一个痛苦的过程。最好花时间专注于让它流行起来,然后再扩大规模。

【讨论】:

以上是关于社交应用程序的数据库设计和优化注意事项的主要内容,如果未能解决你的问题,请参考以下文章

社交网络应用程序数据库设计:如何改进此架构?

计算机毕业设计之java+ssm大学生社交平台

旅游社交网络数据库设计

大数据量数据库优化

社交网站的数据库设计

大数据量高并发的数据库优化