哈希日志篇

Redis超级日志(HyperLogLog)是一种概率数据结构,用于在内存大小不变的情况下计算唯一值。你可以高效地添加和统计大量唯一项,并将两个或多个HyperLogLog数据结构合并为一个。

hyper-loglog

场景

由于HyperLogLog是一种概率数据结构所以通常都是用来做估算统计类的场景。

基数统计

最典型的场景就是统计数据集合中的基数(不重复元素的数量)。例如,统计网站的独立访客数量、唯一 IP 地址数量、唯一用户数量等。HyperLogLog可以在占用极少内存的情况下,快速且准确地估算基数。

$ip = $_SERVER['REMOTE_ADDR'];
$redis->pfAdd('visit:ips', [$ip]); // (int) 1

// 独立IP数量
$count = $redis->pfCount('visit:ips');

大数据集合处理

当需要处理大型数据集合时,使用传统的准确计数方法可能会占用大量内存。而使用 HyperLogLog 可以以极少的内存占用来进行近似的基数统计,从而在节省内存的同时完成统计任务。

网站分析和监控

在网站分析和监控系统中,经常需要统计用户访问行为、用户活跃度、页面浏览量等指标的唯一值数量,HyperLogLog 可以用于快速而准确地进行这些统计。

广告点击分析

对广告点击进行统计时,经常需要统计不同用户的唯一点击次数,HyperLogLog 可以帮助快速估算唯一点击用户数量,从而评估广告的效果。

// 同一个用户点击多次算一次
$redis->pfAdd('ad:1', ['user:1', 'user:2', 'user:1']);  // (int) 1

// 获取点击的唯一用户数量
$count = $redis->pfCount('ad:1');  // (int) 2


大规模数据集合处理

对于大规模的数据集合,例如社交网络中的用户关注列表、好友列表等,使用 HyperLogLog 可以快速估算集合中的唯一元素数量,提供实时的统计结果。

数据清洗和去重

在数据清洗和去重过程中,可以使用 HyperLogLog 来快速估算数据集合中的唯一元素数量,从而筛选出重复数据或者不合法数据。


$redis->pfAdd('user:device:android', ['a', 'b', 'c']); // (int) 1

$redis->pfAdd('user:device:apple', ['d', 'e', 'a']); // (int) 1

// 合并用户两个设备的记录集合并且去重
$redis->pfMerge('user:device:history', ['user:device:apple', 'user:device:android']); // true


$redis->pfCount('user:device:history'); // (int) 5

实时监控和警报

在实时监控和警报系统中,可以使用 HyperLogLog 来快速统计某些指标的唯一值数量,并根据预设的阈值进行实时监控和警报。


$count = $redis->pfCount('bs:stat'); // (int) 5
if ($count > 10) {
    // todo alert
}

搜索引擎优化

在搜索引擎优化领域,可以使用 HyperLogLog 来统计网站的独立访客数量、唯一搜索关键词数量等指标,从而评估网站的流量和用户行为。

消息推送过滤

在一些需要根据历史记录进行消息推送时候,可以使用HyperLogLog快速判断用户历史记录有没有这条消息。


$count = $redis->pfAdd('user:history', [11, 12, 14]); // (int) 1

// 待推送的ID
$pushId = 11;
// 小于 1 说明用户看过此消息
if ($redis->pfAdd('user:history', [$pushId]) < 1) {
    return false; // 不需要推送
}

缓存穿透

当太多的请求无法在缓存中找到,而直达数据库时,数据库可能直接抗不住导致服务崩溃。通过HyperLogLog预先写入条件值,判断是否存在条件值。


// 预选写入条件值.
$values = ['u:1', 'u:2', 'u:3'];

$redis->pfAdd('filters', $values);

$conditionValue = $_GET['condition'];

if ($redis->pfAdd('filters', $conditionValue) === 1) { // 不在里面.
    // todo 
}


协作

如果你有更多的场景使用用例,可以通过github提交pr请求。有问题可以开issue编辑此页面