我应该选择什么: MongoDB/Cassandra/Redis/CouchDB?

我们正在开发一个非常大的项目,我想知道是否有人可以给我一些建议,关于什么数据库后端我们应该选择。

我们的系统由1100个电子设备组成,这些设备向中央服务器发送信号,然后服务器存储信号信息(信号长约35字节)。不管怎样,这些设备每分钟都会发送3个信号,所以如果我们计算数字,那么数据库中每天会有4.752.000条新记录,每个月总共会有142.560.000条新记录。

我们需要一个数据库后端,照明快速和可靠。当然,我们需要对那个数据库进行一些复杂的数据挖掘。我们正在对 MongoDB/Cassandra/Redis/CouchDB 做一些研究,但是文档网站仍然处于早期阶段。

有什么帮助吗,有什么想法吗?

非常感谢!

34683 次浏览

我使用了 咒语中的 MongoDB,并且很喜欢它。虽然我不能说速度与这样大的数据集,Clojure (其中 Incanter 是基于)是非常可靠的事务管理方面。Incanter 还提供了一些很棒的分析工具,所以如果您打算分析所有这些数据,MongoDB + Incanter 可能是一个强大的组合。

所以你把数据存储在一个中央数据库中用于数据挖掘? 没有在线事务处理?

我不认为 MongoDB 在耐久性方面做得很好。参见 http://nosql.mypopescu.com/post/392868405/mongodb-durability-a-tradeoff-to-be-aware-of

也许你可以使用分析数据库信息布赖特,它有一个社区版: http://www.infobright.org/

如果你喜欢 Cassandra 的外观,因为它从一开始就设计了横向扩展、根据可用性调整一致性等功能,那么你可能也想看看 Riak,它有一个类似的功能集,但是采用了不同的方法。

~ 3000个信号/分钟 = 50次写入/秒,这些系统中的任何一个都可以轻松处理。

不过,当您的数据集大于内存时,Cassandra 可能工作得最好,而 Hadoop 集成将有助于您的数据挖掘。

您正在寻找一个能够“闪电般快速”写入(数据保存在磁盘上)的数据存储,并且数据挖掘将在稍后阶段(这是 READ 周期)进行。另外,考虑到您所陈述的数字,结果是您每天将收集159MB 的所有信息,或者大约每月收集5GB 的信息。

在这种情况下,为什么不看看 Redis。

您总是可以存档每日 Redis 数据文件,并在以后引用它(如果您担心加载5GB 或更大的 RAM 空间,那么这种存档可能是一种解决方案)

根据该网站公布的数据,Redis 相当快。 希望这个能帮上忙。 Kiran

CouchDB 非常可靠,提供了极好的耐久性,并且您将体验到非常低的 CPU 负载。它还非常擅长在多个节点之间进行复制,无论是按需复制还是连续复制。

由于它的复制能力和 RESTful API (它使用 HTTP 作为 API) ,使用成熟的工具可以非常容易地横向扩展。(Nginx 或 Apache 用于反向代理、 HTTP 负载均衡等)

用 JavaScript 编写 map/reduce 函数来预先计算查询。结果是逐步建立在磁盘上的,这意味着每个信号只需要计算一次。换句话说,查询可以非常快,因为它只需要对自上次运行查询以来记录的信号数据进行计算。

CouchDB 以磁盘空间换取性能,因此您可以期望使用大量的磁盘空间。您的查询可以快如闪电,并且如果正确地实现它们,还可以节省磁盘空间。

试试 CouchDB。

看看 为什么大型强子对撞机科学家使用 CouchDB在英国广播公司 CouchDB 作为一个容错,可扩展,多数据中心的关键值存储

不要让空间尺度(1000 + 设备)在计算和/或存储尺度方面误导您。每秒几十个35字节的插入对于任何主流 DBMS 来说都是微不足道的工作负载,甚至可以在低端硬件上运行。同样,每月1.42亿条记录只有每月1 ~ 10GB 的存储量,没有任何压缩,包括索引。

在你的问题评论中,你说:

“这一切都与可靠性、可扩展性和速度有关。解决方案的可扩展性非常重要(MongoDB 自动分片?)只要投入更多的节点,速度也是非常重要的

可靠性?任何主流数据库管理系统都可以保证这一点(假设您的意思是它不会破坏您的数据,也不会崩溃——请参阅我在这个答案底部对 CAP 定理的讨论)。速度?即使使用单台机器,这个工作负载的10 ~ 100倍应该也不是问题。可伸缩性?按照目前的速度,一整年的数据(未压缩的,甚至是完全索引的)很容易就能容纳100GB 的磁盘空间(同样,我们已经确定插入速度不是问题)。

因此,我认为没有任何明确的需要像 NoSQL 这样的奇特解决方案,甚至也没有任何分布式数据库——一个普通的、老式的关系数据库,比如 MySQL 就可以了。如果您担心故障转移,只需以主从配置设置备份服务器。如果我们讨论的是当前比例的100或1000倍,那么只需根据数据收集设备的 ID (也就是说。{分区索引} = {设备 ID }模块{分区数})水平分区几个实例。

要记住,离开安全舒适的关系数据库,就意味着放弃 代表性模型丰富的工具。这将使您的“复杂数据挖掘”更加困难——您不仅需要将数据放入数据库,还需要将它取出。

尽管如此,MongoDB 和 CouchDB 的部署和使用异常简单。它们也非常有趣,并且会让你对任何人(不仅仅是程序员——还有高管)更有吸引力.

在你提出的三种 NoSQL 解决方案中,Cassandra 是最适合高插入容量的(当然,相对而言,我不认为你 是高插入容量的——这是为 脸书设计的) ;。因此,除非你有一些奇怪的需求,你没有提到,我会建议反对它,为您的用例。

如果您正在进行 NoSQL 部署,那么可能需要考虑 CAP 定理。这将帮助您在 MongoDB 和 CouchDB 之间做出选择。这里有一个很好的链接: http://blog.nahurst.com/visual-guide-to-nosql-systems。这一切都归结为你所说的“可靠性”: MongoDB 以可用性换取一致性,而 CouchDB 以一致性换取可用性。(Cassandra 允许您通过指定一个写/读操作必须写/读多少个服务器才能成功,从而对每个查询进行权衡; 更新: 现在,使用 “大沙发”的 CouchDB 也可以做到这一点!非常令人兴奋...)

祝你项目顺利。

答案很大程度上取决于收集完成后你想用它做什么。存储大量数据很容易: 只需将其转储到日志文件中,不需要数据库。另一方面,如果您想对它执行复杂的分析和数据挖掘,那么数据库是有帮助的。

下一个问题是你要做什么样的分析。它是否会在具有特定属性的数据子集上执行(仅限于最后一小时/天/周/月) ,数据是否可以聚合或以某种方式预先计算?换句话说: 您是否需要以收集的形式访问整个数据集?当数据过于陈旧而不再有趣时,你能将其存档吗?您能够聚合数据并对聚合执行分析吗?

根据我从事广告分析工作的经验(收集关于广告曝光的数十亿个数据点) ,聚合是关键。您收集原始数据,对其进行消毒,然后将其放入 MongoDB、 Cassandra 甚至 MySQL 等数据库中,这些数据库允许您进行更新和查询。然后定期聚合数据并将其从数据库中删除(但是对原始数据进行存档,以后可能需要它)。

聚合实际上会询问您想要询问的关于数据的所有问题,并将其保存为一种形式,以便于检索特定问题的答案。假设你想知道一周中哪一天 X 最多。这种方法的简单实现是将所有已记录的信号保存在一个巨大的表中,并执行一个查询,对包含 X 的所有行进行求和。随着收集的信号数量的增长,这个查询将花费越来越长的时间。再多的索引、分片或优化也无济于事。取而代之的是每天/每小时/每分钟(取决于确切的用例和如何更新你的报告需要)你查看你记录的新信号,对于每个 X,你增加计数器来记录星期一有多少个 X,如果是星期一,星期二如果是星期二等等。这样,您可以稍后检索一周中每一天的计数,并对它们进行比较。对所有希望能够回答的问题执行此操作,然后从数据库中删除信号(同样,保留原始数据)。

记录聚合的数据库类型可以与存储传入信号的数据库类型相同,但不需要非常花哨。它将存储表示特定答案的键和通常只是数字的值。

在旧式的数据仓库中,存储传入信号的数据库称为 OLTP (用于在线事务处理) ,存储聚集数据的数据库称为 OLAP (用于在线分析处理)。OLTP 针对插入进行了优化,OLAP 针对查询进行了优化。这些术语已经过时了,当人们听到这些术语时,他们往往会马上想到 SQL 和 starschema 等等。也许我不该用它们,但它们是方便的术语。

无论如何,对于 OLTP,您需要能够快速插入数据的东西,还需要能够支持数据索引和搜索的东西。数据库对聚合有很大的帮助,它只完成一半的求和和查找最大值和最小值的工作。我非常喜欢 MongoDB,因为它非常容易设置和使用。我处理的数据往往是混乱的,并非所有的项目都具有相同的属性集,因此 Mongo 的宽容的无模式性是一种恩惠。另一方面,您的数据听起来更加统一,因此 Mongo 可能不会给您带来那么多好处。但是,不要忽视那些好的旧的关系数据库。如果你要做很多求和之类的工作,那么 SQL 是很棒的,这就是它的用途。

对于 OLAP,工作原理要简单得多,只需要一个键值存储。我使用 Redis 是因为它也非常容易使用和设置。它还允许您存储比标量值更多的值,这很方便。有时,在大多数键值存储中,您的值实际上是一个列表或散列,您必须对这些值进行编码,但 Redis 本地处理它。Redis 的缺点是不能执行查询(“比如给我所有具有 Y 值的行”) ,必须自己保留数据的索引。另一方面,由于所有问题的答案都是预先计算好的,所以你不需要太多的索引,你所需要做的就是通过一个由问题定义的键来查找答案。对于上面的问题,一周中哪一天的 X 最多,你可以查找 X 周一、周二等的工作量,也许你把它们存储为 X: 周一、 X: 周二等。

总之: MongoDB 和 Redis 对我很有用。我不认为 MongoDB 对您的用例非常有用,相反,我认为您实际上可能会从传统的 SQL 数据库中获益更多(但这取决于,如果您的数据非常简单,您可能会一直使用 Redis)。最重要的是不要错误地认为您需要将数据保存在一个数据库中并永远保存它。聚合和丢弃旧数据是关键。