平常接需求的时候, PM提出来一个须要统计页面UV/PV的需求你怎么作?html
下面有三个选择:mysql
首先, 选1的时候看公司架构怎么说, 若是人家给你排期到半个月后了你这需求还作不作了?redis
其次, 选2是咱们的大多数状况, 并且是最直白的一种统计方式.
这种方式的好处就是统计准确, 且能保留住数据, 在特定的业务里面还能复用(好比作个ip黑名单, 反做弊啥的).
固然缺点也很明显, 若是你的服务请求量特别大, 那么你存储数据的体积增加特别快. 算法
好比放到redis的集合里面(曾经我就这么干过), 把全部请求的ip存到redis中, 最后统计集合中元素的个数, 后来运维开始在群里嚷嚷:我们缓存服务的内存要不够用啦!
运维把大key一列, 嗯? xx, 你这缓存能优化一下不? 这几百mb的冷数据扔缓存里面太浪费资源了balabalasql
总之就是你得优化一下了, 那么怎么优化呢? 缓存
bitmap也是一种不错的方式, 把十进制映射到bit字节上, 好比 10000000 个基数, 那么转换后就变成了 100000000/8/1024/1024 ≈ 12M, 这也是个不错的选择, 不过key不少的状况下占用空间也很多架构
通过我一番谷歌+翻文档, 发现了这么个神奇的东西: HyperLogLog, 基于几率这种玄学的算法运维
Redis 在 2.8.9 版本添加了 HyperLogLog 结构, 它的优点就是每一个key仅需12kb的内存, 就能存储 2^64 个不一样元素的基数, 存储空间小且固定, 缺点就是元数据没法直接提取了post
这种是基于几率的算法, 既然是几率就包含着不肯定性, 存在统计偏差, 不过大部分场景是能hold住的, 若是须要绝对精确的状况, 不要用这个大数据
使用的命令以下:
127.0.0.1:6379> PFADD test_uv id1 id2 id3 id4 id1 (integer) 1 127.0.0.1:6379> PFCOUNT test_uv (integer) 4 127.0.0.1:6379> PFADD test_uv2 id1 id2 id5 (integer) 1 127.0.0.1:6379> PFMERGE test_uv3 test_uv test_uv2 OK 127.0.0.1:6379> PFCOUNT test_uv3 (integer) 5
PFADD 添加基数
PFCOUNT 统计个数
PFMERGE 两个key合并
就是这么简单, 粗暴
这个我也是看的别人的, 因此就把这两篇文章列出来本身复习一下: