【问题标题】:Incrementing hundreds of counters at once, redis or mongodb?一次递增数百个计数器,redis 还是 mongodb?
【发布时间】:2012-07-11 13:56:42
【问题描述】:

背景/意图:

因此,我将从头开始创建一个事件跟踪器,并对如何执行此操作有一些想法,但我不确定处理数据库方面的最佳方法。我感兴趣的一件事是允许这些事件完全动态,但同时允许报告关系事件计数器。

例如,按操作系统划分的所有国家/地区。期望的效果是:

  1. 美国事件数
    • iOS - 美国发生的事件数
    • Android - 美国发生的事件数
  2. CA # 事件
    • iOS - 在 CA 中发生的事件数
    • Android - 在 CA 中发生的事件数

我的意图是能够像这样接受这些事件名称:

/?country=US&os=iOS&device=iPhone&color=blue&carrier=Sprint&city=orlando&state=FL&randomParam=123&randomParam2=456&randomParam3=789

这意味着为了对上述情况执行关系计数器,我可能会为每个请求增加 100 多个计数器。

假设每天会有 10+ 百万个上述请求。

我希望在跟踪事件名称方面保持完全动态,并且我还希望以这样一种方式进行,即对数据的查找保持超快。因此,我一直在考虑为此使用 redis 或 mongodb。

问题:

  1. 在保持字段动态的同时,还有比计数器更好的方法吗?

  2. 如果所有这些都在一个文档中(结构像一棵树),那么使用 mongodb 中的 $inc 运算符在一个操作中同时增加 100 多个计数器是否可行且不慢?这样做的好处是我可以在一个查询中快速检索一个“活动”的所有统计信息。

  3. 这是否更适合 redis 并为事件的所有适用计数器执行 zincrby?

谢谢

【问题讨论】:

  • 你需要它有多“动态”?即什么延迟?另一种方法是为每个事件存储一个文档,然后定期使用 map-reduce 来汇总数据。这种方法还允许您在事后更改您报告的内容(例如,为“奥兰多”添加自定义报告)。
  • 由于这更多地用于营销信息,因此尽快提供它是理想的。我认为计数器可能很适合的另一个原因。

标签: mongodb redis schema


【解决方案1】:

根据您的关键结构的布局方式,我建议使用流水线方式处理 zincr 命令。你有一个简单的“提交”触发器——请求。如果你要迭代你的参数和 zincr 每个键,那么在请求结束时传递执行命令它将非常快。我已经实现了一个像你描述为 cgi 和 Django 应用程序的系统。我按照以下思路设置了一个关键结构:

YYYY-MM-DD:HH:MM -> 排序集

并且能够使用单个进程在 redis 端每秒处理 150000-200000 增量,这对于您描述的场景来说应该足够了。这个关键结构允许我根据时间窗口获取数据。我还为密钥添加了过期时间以避免编写数据库清理过程。然后,我有一个 cronjob,它会使用上述关键模式的变体来执行设置操作,以将统计数据“汇总”到每小时、每天和每周。我提出这些想法是因为它们是您可以利用 Redis 的内置功能使报告方面更简单的方法。还有其他方法可以做到这一点,但这种模式似乎运作良好。

正如 eyossi 所指出的,对于进行并发写入和读取的系统来说,全局锁可能是一个真正的问题。如果您将其编写为实时系统,则并发性很可能是一个问题。如果它是一个“end if day”日志解析系统,那么它不太可能触发争用,除非您在输入时运行解析器的多个实例或报告。关于在 Redis 中保持快速读取,我会考虑设置一个只读的 redis 实例,从主实例中脱离出来。如果将它放在运行报告的服务器上并将报告进程指向它,那么生成报告应该非常快。

根据您的可用内存、数据集大小以及是否在 redis 实例中存储任何其他类型的数据,您可能会考虑运行 32 位 redis 服务器以降低内存使用率。一个 32b 的实例应该能够将大量此类数据保存在一小块内存中,但如果运行普通的 64 位 Redis 不会占用太多内存,请随意使用它。一如既往地测试你自己的使用模式来验证

【讨论】:

  • 感谢您的观点和建议。我实际上正在考虑以类似的方式进行操作。目的是拥有这个实时并拥有多个用户和活动,因此将数据向上和从 redis 中滚动出来可能会很棘手,因为参数可能会产生很多未知的变化。我将不得不进一步考虑这一点,但这应该是一个很好的起点!
【解决方案2】:

在 redis 中,您可以使用 multi 同时增加多个键。

【讨论】:

  • 谢谢,在玩了多一点之后,我想我最终可能会走这条路。
【解决方案3】:

我对 MongoDB 有过一些不好的体验,我发现当你对它进行大量写入时,它可能真的很棘手......

您可以查看this link 了解更多信息,并且不要忘记阅读“MongoDB 使用 1 BFGL(大他妈的全局锁)”部分(可能在 2.x 版中已经改进) - 我没有检查它)

另一方面,我对Redis 有很好的体验,我将它用于大量的读/写,而且效果很好。 您可以在此处找到有关我如何使用Redis 的更多信息(以了解并发读取/写入的数量):http://engineering.picscout.com/2011/11/redis-as-messaging-framework.html

【讨论】:

  • 欣赏链接。我已经使用了很多 redis 并且非常喜欢它,所以我可能会直接使用它。吸引我到 mongodb 的是在一个文档中包含“活动”的所有内容的潜在前景,但 BFGL 在这方面令人沮丧。虽然我不清楚这是否只影响跨集合的写入,或者它是否也会影响集合中的内容。我会进一步调查!
【解决方案4】:

如果您不需要原子功能,我宁愿使用pipeline而不是multi..

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-07
    • 2021-07-21
    • 2014-02-24
    相关资源
    最近更新 更多