1、背景
2、常规计数器
2.1 如何使用 Redis 进行常规计数
Redis实现常规计数器有两种数据类型适合:String 和 Hash。
2.1.1 使用string 计数
127.0.0.1:6379> SET counter 100OK127.0.0.1:6379> INCR counter(integer) 101127.0.0.1:6379> DECR counter(integer) 100
除Incr与Decr命令外,RedisString 类型还提供Incrby 与 Decrby 命令,语法格式为:
incrby:INCRBY key count
将 key 增加 count,count 可正可负,返回key 的结果:
127.0.0.1:6379> INCRBY counter 10(integer) 10127.0.0.1:6379> INCRBY counter -20(integer) -10
decrby:DECRBY key count
将 key 减少 count,count 可正可负,返回key 的结果:
127.0.0.1:6379> DECRBY counter 10(integer) -10127.0.0.1:6379> DECRBY counter -20(integer) 10
2.1.2 使用Hash计数
hincrby:HINCRBY key filedcount
将 Hash key 的 filed 增加 count,count 可正可负,返回对应 field 的结果:
127.0.0.1:6379> HGET userid field(nil)127.0.0.1:6379> HINCRBY userid field 1(integer) 1127.0.0.1:6379> HINCRBY userid field -1(integer) 0127.0.0.1:6379> HGET userid field"0"
2.2 常规计数器使用场景
3、基数统计:HyperLogLog 的原理及使用
3.1 HyperLogLog原理介绍
从伯努利试验到基数计数


分桶平均减小误差


3.2 Redis中的HyperLogLog
Redis将HyperLogLog实现成一种数据类型,对于每个元素,Redis将其Hash成64位的二进制串,用低14位用来表示桶的下标(所以桶的个数为1<<14=16384),剩余的位用来模拟伯努利分布,每个桶需要6个bit;最多能够对2的64次方个元素进行统计,内存占用约12 k;其标准误差为 0.81%。
pfadd:将所有元素参数添加到 HyperLogLog 数据结构中
127.0.0.1:6379> pfadd key1 ele1 ele2(integer) 1127.0.0.1:6379> pfadd key1(integer) 0127.0.0.1:6379> pfadd key2(integer) 0
pfcount:返回给定的HyperLogLog的基数估计值
语法:PFCOUNT key1 [key2 … ]
返回对应 HyperLogLog 的基数值,多个key时,返回多个key的合并后的基数值。
127.0.0.1:6379> pfcount key1(integer) 0127.0.0.1:6379> pfadd key1 ele1 ele2(integer) 1127.0.0.1:6379> pfadd key2 ele1 ele3(integer) 1127.0.0.1:6379> pfcount key1(integer) 2127.0.0.1:6379> pfcount key1 key2(integer) 3
pfmerge:将多个 HyperLogLog 合并为一个
语法:PFMERGE destkey sourcekey1 [sourcekey2 …]
将 sourcekey 与 destkey 合并,当 destkey 不存在时,会创建 destkey
返回OK
127.0.0.1:6379> pfadd key1 ele1 ele2(integer) 1127.0.0.1:6379> pfadd key2 ele1 ele3(integer) 1127.0.0.1:6379> pfcount key3(integer) 0127.0.0.1:6379> pfmerge key3 key1 key2OK127.0.0.1:6379> pfcount key3(integer) 3
3.3 HyperLogLog的适用场景
统计网站的UV(uniquevisitor)
pfadd key_prefix_2021010101 "127.0.0.1"
当需要统计这一天0-1点这一个小时一共有多少IP访问了这个网页时:
pfcount key_prefix_2021010101
需要统计上午8到12点的网页访问情况:
pfcount key_prefix_2021010109 …… key_prefix_2021010112
一天结束了,需要统计并保存这一天访问情况:
pfmerge key_prefix_2021010101 ...... key_prefix_2021010124
对于一个热门的网页,这样一个计数的方式显然能够极大的节约存储空间。
用户画像

对于每个标签,创建hyperloglog key值保存数据,如:man, woman, basketball…等,对于每个需要记录的值,都需要创建一个key进行记录。
每多一个用户时,向所有记录的key里使用pfadd 添加元素。
进行数据分析时,使用 pfcount 将需要分析的数据进行统计。
4 高斯Redis在计数上的优势
4.1 开源 Redis 的问题
生产环境中,为避免单点故障,增强数据库可用性,Redis 通常将数据复制多个副本,保存在不同的服务器上;在大量并发请求过来时,为了尽可能利用主从节点的服务器资源,可以采用主写从读的方式。由于Redis 的主从同步是异步的,当主节点写入数据后,从节点不保证立刻更新数据,如果此时读取数据,读到的就是过期的旧数据,产生数据不一致问题。
当主节点故障宕机后,数据不一致的问题会更严重。主节点故障后,哨兵节点会将从节点提升为主,原主节点上堆积的数据 buffer 就彻底丢失了。在电商秒杀业务中,如果发生主节点复制buffer堆积,导致从节点与主节点的counter 偏大很多,一旦此时主节点宕机,发生主备倒换后,容易导致流量压力超出阈值,大量数据可能会将 MySQL 压垮,导致系统不可用。

4.2 高斯 Redis 如何解决


5 结语
6 附录
本文作者:华为云高斯Redis团队
杭州西安深圳简历投递:yuwenlong4@huawei.com






