41

我正在构建一个跟踪和验证广告展示次数和点击次数的系统。这意味着有很多插入命令(平均大约 90 次/秒,峰值为 250 次)和一些读取操作,但重点是性能并使其超快。

该系统目前在 MongoDB 上,但从那时起我就被介绍给 Cassandra 和 Redis。选择这两种解决方案中的一种而不是留在 MongoDB 上会是个好主意吗?为什么或者为什么不?

谢谢

4

9 回答 9

31

对于这样的收获解决方案,我建议采用多阶段方法。Redis 擅长实时通信。Redis 被设计为内存中的键/值存储,并继承了作为内存数据库的一些非常好的优点:O(1) 列表操作。只要服务器上有 RAM 可用,Redis 就不会减慢推送到列表末尾的速度,这在您需要以如此高的速率插入项目时很好。不幸的是,Redis 无法处理大于您拥有的 RAM 量的数据集(它只写入磁盘,读取用于重新启动服务器或系统崩溃)并且必须由您的应用程序进行扩展. (一种常见的方法是在多个服务器上传播密钥,这是由一些 Redis 驱动程序实现的,尤其是那些用于 Ruby on Rails 的驱动程序。)Redis 还支持简单的发布/订阅消息传递,这有时也很有用。

在这种情况下,Redis 处于“第一阶段”。对于每种特定类型的事件,您在 Redis 中创建一个具有唯一名称的列表;例如我们有“页面查看”和“链接点击”。为简单起见,我们要确保每个列表中的数据具有相同的结构;点击的链接可能有用户令牌、链接名称和 URL,而查看的页面可能只有用户令牌和 URL。您首先关心的只是了解它发生的事实,以及推送您需要的任何绝对必要的数据。

接下来,我们有一些简单的处理工作人员,通过要求它从列表末尾取出一个项目并将其移交给 Redis,这些工作人员将这些疯狂插入的信息从 Redis 手中夺走。工作人员可以进行正确归档数据所需的任何调整/重复数据删除/ID 查找,并将其移交给更永久的存储站点。尽可能多地启动这些工作人员,以保持 Redis 的内存负载可承受。你可以用任何你想要的方式(Node.js、C#、Java 等)编写 worker,只要它有一个 Redis 驱动程序(现在大多数 Web 语言都有)和一个用于你想要的存储(SQL、Mongo 等)。 )

MongoDB擅长文档存储。与 Redis 不同,它能够处理大于 RAM 的数据库,并且它自己支持分片/复制。与基于 SQL 的选项相比,MongoDB 的一个优势是您不必拥有预先确定的模式,您可以随时随意更改数据的存储方式。

但是,我建议将 Redis 或 Mongo 用于保存数据以进行处理的“第一步”阶段,并使用传统的 SQL 设置(也许是 Postgres 或 MSSQL)来存储处理后的数据。跟踪客户行为对我来说听起来像是关系数据,因为您可能想要“向我展示查看此页面的每个人”或“此人在这一天查看了多少页面”或“哪一天的浏览者总数最多? ”。出于分析目的,您可能会想出更复杂的联接或查询,成熟的 SQL 解决方案可以为您完成大量此类过滤;NoSQL(特别是 Mongo 或 Redis)无法跨不同的数据集进行连接或复杂查询。

于 2012-01-16T23:20:50.733 回答
22

我目前为一个非常大的广告网络工作,我们写入平面文件:)

我个人是 Mongo 的粉丝,但坦率地说,Redis 和 Cassandra 的表现不太可能更好或更差。我的意思是,您所做的只是将内容放入内存,然后在后台刷新到磁盘(Mongo 和 Redis 都这样做)。

如果您正在寻找极快的速度,另一种选择是在本地内存中保留几个印象,然后每分钟左右刷新一次磁盘。当然,这基本上是 Mongo 和 Redis 为你做的。不是真正令人信服的搬家理由。

于 2010-06-10T06:10:34.193 回答
12

所有三种解决方案(如果您计算平面文件,则四种)将为您提供极快的写入速度。非关系 (nosql) 解决方案将为您提供可调的容错能力,以及用于灾难恢复的目的。

在规模方面,我们的测试环境,只有三个 MongoDB 节点,每秒可以处理 2-3k 个混合事务。在 8 个节点上,我们每秒可以处理 12k-15k 混合事务。Cassandra 可以扩展得更高。250 次读取是(或应该)没有问题。

更重要的问题是,你想用这些数据做什么?运营报告?时间序列分析?即席模式分析?实时报告?

如果您希望能够基于集合中的多个属性进行临时分析,那么 MongoDB 是一个不错的选择。您最多可以在一个集合上放置 40 个索引,尽管索引将存储在内存中,因此请注意大小。但结果是一个灵活的分析解决方案。

Cassandra 是一个键值对存储。您可以预先定义一个静态列或一组列作为您的主索引。针对 Cassandra 运行的所有查询都应调整为此索引。您可以在其上放置辅助设备,但仅此而已。当然,您可以使用 MapReduce 扫描存储以查找非键属性,但这只是:对存储进行串行扫描。Cassandra 在服务器节点上也没有“like”或正则表达式操作的概念。如果要查找名字以“Alex”开头的所有客户,则必须扫描整个集合,为每个条目提取名字并通过客户端正则表达式运行它。

我对 Redis 不够熟悉,无法明智地谈论它。对不起。

如果您正在评估非关系平台,您可能还需要考虑 CouchDB 和 Riak。

希望这可以帮助。

于 2011-03-26T08:56:54.590 回答
9

刚刚发现:http ://blog.axant.it/archives/236

引用最有趣的部分:

第二张图是关于 Redis RPUSH vs Mongo $PUSH vs Mongo insert,我觉得这张图非常有趣。即使与 Redis RPUSH 相比,最多 5000 个条目 mongodb $push 也更快,然后它变得非常慢,可能 mongodb 数组类型具有线性插入时间,因此它变得越来越慢。mongodb 可能会通过暴露恒定时间插入列表类型获得一些性能,但即使使用线性时间数组类型(可以保证恒定时间查找),它也适用于小型数据集。

我想一切都至少取决于数据类型和数量。最好的建议可能是对您的典型数据集进行基准测试并了解自己。

于 2010-09-12T21:34:45.143 回答
7

根据 Benchmarking Top NoSQL Databases(在此处下载),我推荐 Cassandra。 在此处输入图像描述

于 2014-12-04T06:44:28.550 回答
3

我可以在一个简单的 350 美元戴尔上使用 MongoDB 获得大约 30k 插入/秒。如果您只需要大约 2k 次插入/秒,我会坚持使用 MongoDB 并将其分片以实现可扩展性。也许还考虑使用 Node.js 或类似的东西来使事情变得更加异步。

于 2011-09-08T23:43:59.457 回答
3

如果你有选择(并且需要远离扁平化),我会选择 Redis。它速度极快,可以轻松处理您所说的负载,但更重要的是,您不必管理刷新/IO 代码。我理解它非常简单,但管理的代码越少越好。

您还将获得使用 Redis 的水平缩放选项,而基于文件的缓存可能无法获得这些选项。

于 2010-06-10T06:31:37.080 回答
2

插入数据库的问题是它们通常需要为每次插入写入磁盘上的随机块。您想要的是每 10 次左右插入才写入磁盘的东西,理想情况下是写入顺序块。

平面文件很好。可以使用合并排序映射缩减类型算法以可扩展的方式从平面文件中获得汇总统计信息(例如每页的总点击数)。自己动手并不难。

SQLite 现在支持 Write Ahead Logging,它也可以提供足够的性能。

于 2011-02-28T23:49:52.563 回答
-8

我有 mongodb、couchdb 和 cassandra 的实践经验。我将很多文件转换为base64字符串并将这些字符串插入nosql。
mongodb 是最快的。cassandra 最慢。couchdb 也很慢。

我认为 mysql 会比所有这些都快得多,但我还没有为我的测试用例尝试 mysql。

于 2011-07-06T12:22:05.367 回答