【问题标题】:Count Unique using Redis and MongoDB (HyperLogLog)使用 Redis 和 MongoDB (HyperLogLog) 计算唯一性
【发布时间】:2016-11-17 15:21:48
【问题描述】:

我在 MongoDB 中有一个带有示例文档的集合,如下所示 -

{
    "_id" : ObjectId("58114e5e43d6420b7db4e15c"),
    "browser" : "Chrome",
    "name": "hyades",
    "country" : "in",
    "day" : "16-10-21",
    "ip" : "0.0.0.0",
    "class" : "A123"
}

问题陈述

我应该能够在获取不同数量的 IP 时对任何字段进行分组。

聚合查询 -

[
    {$group: {_id: '$class', ip_arr: {$addToSet: '$ip'}}},
    {$project: {class: '$_id.class', ip: {$size: '$ip_arr'}}}
]

给出了预期的结果,但速度很慢。同样,使用另一个 $group 计数 ip 很慢。输出是 -

[{class: "A123",ip: 42},{class: "B123", ip: 56}..] 

我尝试了什么

我考虑过为此使用 Hyperloglog。我尝试使用 Redis 实现。我尝试将整个数据流式传输,仅将我分组的内容投影,并将 PFADD 投影到 redis 中相应的 hyperloglog 结构中。

逻辑看起来像 -

var stream = Model.find({}, {ip: 1, class: 1}).stream();
stream.on('data', function (doc) {
    var hash = "HLL/" + doc.class;
    client.pfadd(hash, doc.ip);
});

我试图针对一百万多个数据点运行此程序。要流式传输的数据大小约为 1GB,Mongo 和 Node 服务器之间的连接速度为 1 Gbps。我曾预计这段代码会运行得足够快。但是,它非常慢(比在 MongoDB 中计数要慢)。

我想过但没有实现的另一件事是为每个类预先创建存储桶,并随着数据的流入实时增加它们。但是支持任意分组所需的内存是巨大的,所以不得不放弃这个想法.

请提出我可能做错的地方,或者我可以在这里改进的地方,以便我能够充分利用 hyperloglog(我不受 Redis 的限制,并且可以接受任何实现)

【问题讨论】:

  • 你对这个集合的索引是什么?
  • 你的问题是必须要理解的,而且标题有误导性。
  • @dyouberg 索引在日期、姓名、班级(如果重要)上。
  • 如果要使用 Hyperloglog 进行计数,每次向 MongoDB 中插入项目时都应该调用PFADD。当前的解决方案不会更快,因为您仍然需要从 MongoDB 读取数据。
  • @for_stack 如果我理解正确,我会预先计算每个可能值的计数,包括所有可能的分组对象。这里的内存成本非常高。

标签: node.js mongodb redis hyperloglog


【解决方案1】:

免责声明:我只使用过来自 C++ 和 Python 的 redis,所以这可能无济于事,但是...

PFADD 支持多个参数;在我使用 redis HLL 来计算唯一条目的系统中,我发现将它们批处理并一次发送一个带有许多(大约 100 个)项目的 PFADD 会导致显着的加速 - 大概是由于避免了 redis 客户端往返。

【讨论】:

  • 是的,这肯定是一种优化。但是,我在同一个盒子上使用 Redis,所以不会浪费往返时间。想知道将所有数据流式传输到 Redis 是否是个好主意?
  • 我也在同一个机器上使用了 redis(TCP localhost,没有尝试 unix 套接字),我上面提到的 PFADD 的加速就是在那个设置上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-03
  • 2011-08-24
  • 1970-01-01
  • 1970-01-01
  • 2018-07-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多