1

我正在使用大约 400 万个文档和大约 5-6GB 数据库大小的 MongoDB。该机器有 10GB 的 RAM,并且免费报告仅使用了大约 3.7GB。该数据库用于视频游戏相关的阶梯(排名)网站,按地区分隔。

这是一个相当繁重的写入操作,但仍然可以获得大量读取。我们使用一个更新程序,它每隔一两个小时查询一次外部源。然后,此更新程序处理记录并更新数据库上的文档。更新程序一次只处理一个区域(见上一段),因此大约 33% 的数据库被更新。

当更新程序运行时,在其运行期间,平均刷新时间会飙升至大约 35-40 秒,并且我们会遇到其他查询的普遍减速。更新程序是在单独的机器上运行的,并且仅在最后从第三方检索和处理所有数据时才查询 MongoDB。

有人建议放慢更新次数,或者只更新发生变化的玩家,但问题归结为排名。由于我们支持玩家之间的关系,我们需要预先计算排名 - 所以如果只有少数用户实际改变了排名,我们仍然需要相应地更新其余用户的排名。至少,MySQL 就是这种情况——我不确定 MongoDB 是否有一个很好的解决方案,可以在支持关系的同时对约 800K->120 万个文档进行排名。

我的问题是:我们如何才能改善我们正在经历的冲洗和减速?为什么它的峰值如此之高?禁用日志(以减轻 i/o 的负载)会有所帮助吗,因为数据丢失不是我担心的事情,因为数据库经常更新,无论如何?

服务器状态: http: //pastebin.com/w1ETfPWs

4

2 回答 2

5

您为这项工作使用了错误的工具。MongoDB 不是为实时排列大型梯子而设计的,至少不是很快。

使用 Redis 之类的东西,Redis 有一个专门为这项工作设计的称为“排序列表”的东西,有了它,你可以拥有 1 亿个条目,并且仍然以亚毫秒的速度获取第 5000000 到第 5001000。

从官方网站(Redis - 排序集):

排序集

使用排序集,您可以以非常快速的方式添加、删除或更新元素(时间与元素数量的对数成正比)。由于元素是按顺序排列的,而不是事后排序的,因此您还可以通过分数或排名(位置)以非常快速的方式获取范围。访问有序集合的中间也非常快,因此您可以将有序集合用作非重复元素的智能列表,您可以在其中快速访问您需要的所有内容:按顺序排列的元素、快速存在测试、快速访问中间元素!

简而言之,使用排序集,您可以执行许多性能出色的任务,而这些任务在其他类型的数据库中很难建模。

使用排序集,您可以

在大型在线游戏中占据排行榜,每次提交新分数时,您都使用 ZADD 对其进行更新。您可以使用 ZRANGE 轻松获取排名靠前的用户,还可以在给定用户名的情况下使用 ZRANK 返回其在列表中的排名。将 ZRANK 和 ZRANGE 一起使用,您可以向用户显示与给定用户相似的分数。一切都很快。

排序集通常用于索引存储在 Redis 中的数据。例如,如果您有许多代表用户的哈希值,您可以使用一个排序集,其中包含用户的年龄作为分数,用户的 ID 作为值的元素。因此,使用 ZRANGEBYSCORE 检索具有给定年龄间隔的所有用户将是简单而快速的。

Sorted Sets 可能是最高级的 Redis 数据类型,因此请花一些时间查看 Sorted Set 命令的完整列表,以了解您可以使用 Redis 做什么!

于 2013-08-10T06:04:30.863 回答
1

在没有看到任何磁盘统计信息的情况下,我认为您的磁盘已饱和。

这可以用iostat -xmt 2, 和检查%util列来检查。

请不要禁用日记功能 - 当您的机器崩溃时,您只会在以后导致更多问题。

分离集合将没有效果。分离数据库可能,但如果您受 IO 限制,这对您没有任何帮助。

选项

如果我是正确的,并且您的磁盘已饱和,那么在 RAID 10 配置中添加更多磁盘将极大地提高性能和耐用性 - 如果您将日志分离到 SSD 则更是如此。

假设这台机器是单台服务器,您可以设置一个副本集并在那里发送您的读取查询。这应该对您有所帮助,但不如磁盘那么多。

于 2013-07-11T13:03:28.113 回答