使用Redis和MongoDB统计唯一(HyperLogLog)

时间:2016-11-17 15:21:48

标签: node.js mongodb redis hyperloglog

我在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'}}}
]

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

[{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约束,并且可以接受任何实现)

1 个答案:

答案 0 :(得分:0)

免责声明:我只使用过来自C ++和Linux的redis。 Python,所以这可能没有帮助,但是......

PFADD支持多个参数;在我使用redis HLL计算唯一条目的系统中,我发现对它们进行批处理并一次发送一个包含许多(大约100个)项目的PFADD会导致显着的加速 - 可能是因为避免了redis客户端往返。