当前位置: 首页 > news >正文

Redis 概率型数据结构实战指南

1. 为什么要用「近似」?

随着业务量爆发式增长,精确统计 的内存或 CPU 成本可能难以接受。例如:

  • 统计一天内 唯一 IP 数 —— 用 SET 精确去重,百万 IP→占用数百 MB。
  • 统计海量商品销量、实时计算 P99 延迟、获取 TOP-N 热门页面……

概率型(Probabilistic)数据结构 通过牺牲可控的精度,换取极低内存与高吞吐,成为解决此类问题的利器。Redis-Bloom 模块为 Redis 提供了一整套成熟实现,go-redis v9 已封装全部指令,开箱即用。

2. 近似集合操作

需求数据结构误差特点是否可删除
是否出现过Bloom Filter假阳性(可调)
Cuckoo Filter假阳性(略低)
集合基数HyperLogLog标准误差 ≈ 0.81%

2.1 Bloom Filter —— 最小内存的存在性判断

// 批量写入
okList, _ := rdb.BFMAdd(ctx,"recorded_users","andy", "cameron", "david", "michelle",
).Result()                      // [true true true true]// 判断存在
exists, _ := rdb.BFExists(ctx, "recorded_users", "cameron")  // true
absent, _ := rdb.BFExists(ctx, "recorded_users", "kaitlyn")  // false

应用场景

  • 去重写日志、判重爬虫 URL、垃圾邮件过滤。
  • 典型误判率 1%~0.01%,可通过 BF.RESERVE 自定义。

2.2 Cuckoo Filter —— 支持删除

rdb.CFAdd(ctx, "other_users", "paolo")           // true
rdb.CFDel(ctx, "other_users", "paolo")           // true
rdb.CFExists(ctx, "other_users", "paolo")        // false

选型要点

对比项BloomCuckoo
写入速度更快略慢
内存更省稍高
DEL不支持支持
查询性能略慢更快

结论:需要删除就选 Cuckoo;极端节省内存或写密集则用 Bloom。

2.3 HyperLogLog —— 基数统计王者

// group:1 共 3 个不同成员
rdb.PFAdd(ctx, "group:1", "andy", "cameron", "david")
// group:2 共 4 个不同成员
rdb.PFAdd(ctx, "group:2", "kaitlyn", "michelle", "paolo", "rachel")cnt1, _ := rdb.PFCount(ctx, "group:1")           // 3
cnt2, _ := rdb.PFCount(ctx, "group:2")           // 4// 合并后去重
rdb.PFMerge(ctx, "both_groups", "group:1", "group:2")
total, _ := rdb.PFCount(ctx, "both_groups")      // 7
  • 固定 12 KB 即可统计 2⁶⁴ 去重计数。
  • 误差 ≈ 0.81%。
  • 典型场景:UV、去重后计数、唯一用户量。

3. 近似统计运算

需求数据结构误差可调典型场景
频率估计Count-min Sketch商品销量、PV 计数
分位数/百分位t-digest延迟 P99、身高分布
TOP-K 排名Top-K最热商品/页面

3.1 Count-min Sketch —— 近似频率查询

// 误差≤0.1%,错误概率≤0.05%
rdb.CMSInitByProb(ctx, "items_sold", 0.01, 0.005)rdb.CMSIncrBy(ctx, "items_sold","bread", 300, "tea", 200, "coffee", 200, "beer", 100)rdb.CMSIncrBy(ctx, "items_sold", "bread", 100, "coffee", 150)freq, _ := rdb.CMSQuery(ctx, "items_sold", "bread", "coffee") // [400 350]
  • 内存固定(取决于误差参数),无需随 item 增长。
  • 「流式」场景比 ZINCRBYZRANGE 省内存高效。

3.2 t-digest —— 分位数利器

rdb.TDigestCreate(ctx, "male_heights")
rdb.TDigestAdd(ctx, "male_heights", 175.5, 181, 160.8, 152, 177, 196, 164)p75, _ := rdb.TDigestQuantile(ctx, "male_heights", 0.75) // [181]
cdf, _ := rdb.TDigestCDF(ctx, "male_heights", 181)       // ≈0.7857
min, _ := rdb.TDigestMin(ctx, "male_heights")            // 152
max, _ := rdb.TDigestMax(ctx, "male_heights")            // 196
  • 采样点多时仍保持 O(1) 内存。
  • 适合 P95、P99 时延监控、A/B 实验指标。

3.3 Top-K —— 热门榜单实时统计

// 创建「Top3」榜单
rdb.TopKReserve(ctx, "top_3_songs", 3)// 批量增加播放量
rdb.TopKIncrBy(ctx, "top_3_songs","Starfish Trooper", 3000,"Only one more time", 1850,"Rock me, Handel", 1325,"How will anyone know?", 3890,"Average lover", 4098,"Road to everywhere", 770)// 列出前 3
top3, _ := rdb.TopKList(ctx, "top_3_songs")
// [Average lover, How will anyone know?, Starfish Trooper]// 查询某歌曲是否在榜
hit, _ := rdb.TopKQuery(ctx, "top_3_songs", "Starfish Trooper") // [true]
  • 内部基于 Count-min + 堆,内存固定。
  • 适合实时 TOP-N 榜单,如热搜、热卖、热文章。

4. 选型与实践指南

场景建议数据结构备注
唯一访问 IP / UVHyperLogLog固定 12 KB / 0.81% 误差
日志去重、注册判重Bloom / Cuckoo需删除 → Cuckoo;否则 Bloom
商品销量、页面 PVCount-min Sketch更关注趋势而非精确值
延迟分布监控t-digest秒级更新 P95/P99
最热商品/话题榜单Top-K高并发流式排名
拼写/命名黑名单Bloom Filter快速 filtration

提示

  1. 所有模块均属于 RedisBloom,需加载模块或使用 Redis Stack。

  2. go-redis v9 命令位于 github.com/redis/go-redis/v9,大写前缀如 BFMAddCMSInitByProb

  3. 针对误差/容量调优:

    • Bloom:BF.RESERVE key errorRate capacity
    • CMS:CMS.INITBYPROB key error prob
    • t-digest:可选压缩率 TDIGEST.CREATE key compression

5. 踩坑 & 性能建议

问题解决方案
误差过大调大容量 / 调小 errorRate;但会增内存
Top-K 大量并发 INCRBY 压力采用 Pipeline 批量上报
同一 Key 频繁删除(Cuckoo 满)提前预估容量,使用 CF.RESERVE
CMS 超过容量后误差逐渐增大按天/小时拆分 Key 或定期快照重建
t-digest 估算极端分位不准 (P99.9)增大 compression、增加样本数
HyperLogLog 需要合并太多 Key两层:先分片,再定期 PFMERGE

6. 生产 Checklist

  1. 模块加载redis-stack-server--loadmodule redisbloom.so
  2. 版本:Redis ≥ 6.2,RedisBloom ≥ 2.6。
  3. 监控:结合 INFO modules 观察 BF/CMS 内部 stats;或自定义 Metrics。
  4. 备份:RDB/AOF 包含概率结构,但恢复后误差不变;无须额外处理。
  5. 容量预估:使用统计学公式或压测,宁可稍大,不可过小。
  6. 代码封装:为每种结构写 DAO,隐藏底层命令,方便替换与调参。

7. 总结

概率型数据结构 = 低成本 + 可接受误差
高 QPS / 大数据量 / 对精度容忍度高 的场景,它们能显著减少内存与 IO,提升系统整体吞吐。合理选型、正确调参,再配合 go-redis 的高效封装,你就能轻松构建 高性能、低成本 的统计与去重服务。

推荐阅读

  • RedisBloom 官方案例
  • ACM 论文《Less Hashing, Same Performance: Building a Better Bloom Filter》
  • Dunning & Ertl《A Comprehensive Evaluation of Approximate Cardinality Estimation Algorithms》

Happy Coding,愿你的 Redis 永不爆表!

http://www.lryc.cn/news/594110.html

相关文章:

  • 借助AI学习开源代码git0.7之四update-cache
  • 响应式编程入门教程第九节:UniRx 高级特性与自定义
  • 分治算法---归并
  • 7. 命令模式
  • 一维数组练题习~
  • 算法题(176):three states
  • windows11环境配置torch-points-kernels库编译安装详细教程
  • 如何优雅解决缓存与数据库的数据一致性问题?
  • 循环黑洞:用Python生成银河系特效图
  • tidyverse-数据可视化 - 图形的分层语法
  • Web开发 04
  • Work SSD基础知识
  • jxORM--编程指南
  • 试用SAP BTP 02:试用SAP HANA Cloud
  • MySQL笔记3
  • Oracle触发器:数据世界的“隐形守护者“
  • Uniapp 纯前端台球计分器开发指南:能否上架微信小程序 打包成APP?
  • Github 贪吃蛇 主页设置
  • 将EXCEL或者CSV转换为键值对形式的Markdown文件
  • 【Python数据采集】Python爬取小红书搜索关键词下面的所有笔记的内容、点赞数量、评论数量等数据,绘制词云图、词频分析、数据分析
  • (LeetCode 面试经典 150 题 ) 1. 两数之和 (哈希表)
  • ps2025下载与安装教程(附安装包) 2025最新版photoshop安装教程
  • 在NLP深层语义分析中,深度学习和机器学习的区别与联系
  • MacBook的ARM架构(M芯片)操作虚拟机的docker拉取镜像问题
  • XSS内容总结
  • 【图文详解】Transformer架构详细解析:多头自注意力机制、qkv计算过程、encoder架构、decoder架构以及mask的意义
  • Logback简单使用
  • WiFiMouseServer手机等作为远程输入
  • 进阶向:基于Python的局域网文件传输工具
  • LeetCode|Day20|9. 回文数|Python刷题笔记