摘要:高斯 Redis,计数的最佳抉择!
本文分享自华为云社区《华为云 PB 级数据库 GaussDB(for Redis)揭秘第八期:用高斯 Redis 进行计数》,原文作者:神思胖。
一、背景
当咱们关上手机刷微博时,就要开始和各种各样的计数器打交道了。咱们注册一个帐号后,微博就会给咱们记录一组数据:关注数、粉丝数、动静数…;咱们刷帖时,关注每天的热搜状况,微博须要为每个热搜记录一组搜寻量。在这一串数据前面,是一个个计数器在工作。
计数器能够分为惯例计数器和基数计数器,对于惯例计数器,只须要对计数器进行简略的增减即可;对于基数计数器,须要对元素进行去重,比方统计搜寻量时,须要保障每个用户的屡次搜寻只统计一次。对于这两种需要,Redis 都有对应的数据类型进行统计。然而开源 Redis 是一个弱一致性的数据库,在特定的场景下,弱统一的计数不能满足业务需要,为此,咱们须要一个强统一的数据库进行计数。
GaussDB(for Redis)(下文简称 高斯 Redis),是华为自研的强统一、长久化 NoSQL 数据库,兼容 Redis5.0 协定。本文将介绍惯例计数器与基数计数器的利用场景及应用高斯 Redis 实现计数。
二、惯例计数器
2.1 如何应用 Redis 进行惯例计数
Redis 实现惯例计数器有两种数据类型适宜:String 和 Hash。
2.1.1 应用 string 计数
当咱们须要保护的计数器数目较少,比方统计网站的注册用户数时,适宜应用 String 类型的计数器。Redis 提供的 Incr 和 Decr 命令别离对 String 类型的 key 值进行增一与减一操作:
127.0.0.1:6379> SET counter 100
OK
127.0.0.1:6379> INCR counter
(integer) 101
127.0.0.1:6379> DECR counter
(integer) 100
除 Incr 与 Decr 命令外,Redis String 类型还提供 Incrby 与 Decrby 命令,语法格局为:
- incrby:INCRBY key count
将 key 减少 count,count 可正可负,返回 key 的后果:
127.0.0.1:6379> INCRBY counter 10
(integer) 10
127.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) -10
127.0.0.1:6379> DECRBY counter -20
(integer) 10
2.1.2 应用 Hash 计数
须要保护多个亲密关联的计数器时,能够应用 Hash 构造进行计数。比方,当咱们注册一个微博账号时,微博会给每个用户记录一些用户数据,比方粉丝数、关注数等,这些数据都绑定到对应用户上,因而能够将这组计数器记录在同一个 Hash key 中,应用 hincrby 命令,语法格局为:
- hincrby:HINCRBY key filed count
将 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) 1
127.0.0.1:6379> HINCRBY userid field -1
(integer) 0
127.0.0.1:6379> HGET userid field
"0"
2.2 惯例计数器应用场景
惯例计数器的应用场景很宽泛,对于社交产品,用户的粉丝数、关注数,帖子的点赞数、珍藏数…;对于视频网站,须要统计视频的播放次数(PV 统计,Page View);对于电商秒杀,须要统计商品数量并进行流量管制。在并发量高的状况下,Redis 的性能劣势显著,非常适合以上场景。
以电商秒杀业务为例,为了解决高并发读写,通常在 MySQL 下层部署 Redis 作为缓存。为了抗住大流量,应用计数器作限流。比方,当咱们想管制每秒 1 万次申请时,能够初始化一个 counter=10000,随后每次申请过去,都对 counter 减一,当 counter 归零后,阻塞后续的申请。每隔一段时间,重置 counter=10000,以此保障大流量不会冲击底层的 MySQL。
三、基数统计:HyperLogLog 的原理及应用
基数计数(cardinality counting)是指在一个数据汇合中,统计不反复元素的个数,是理论利用中一种常见的场景。比方统计一段时间内拜访某个网站的用户数,网络游戏的日活用户数量等。
在数据量较小状况下,咱们能够把所有数据保留下来进行去重统计。Redis 中,能够应用 Set 与 Zset 将数据保留下来,而后统计汇合中的元素数量。而当数据量较大时,该办法会耗费较大的存储空间,须要思考其它的算法。
思考一种状况,当咱们登录微博时,微博会记录咱们的登录状况,并统计每天有多少沉闷用户。很显然,咱们不须要也不应该记录沉闷用户的 ID,并且,大量误差对沉闷用户数量的统计应用影响不大,这种场景下,咱们能够应用 HyperLogLog 进行计数。HyperLogLog 是一种应用极少内存实现巨量统计的计数算法,非常适合大数据场景的基数预计,在 Redis 中被实现为一种数据类型。
3.1HyperLogLog 原理介绍
3.1.1 从伯努利试验到基数计数
HyperLogLog 是一种基数预计算法,其思维来自于伯努利过程。
简略来说,伯努利过程就是一个抛硬币的过程。抛一次硬币,后果为侧面或者背面的概率都是 1 /2。记侧面为 1,背面为 0,如果抛硬币屡次,直到呈现第一次侧面时进行,记为一次投掷试验,并且失去一个投掷后果的序列,比方“001”,咱们能够晓得,这个序列呈现的概率是。
反过来,如果咱们继续进行投掷试验,当呈现第一次“001”序列时,咱们能够简略估算出,咱们投掷试验次数为 8(事实上,这是一个极大似然预计)。
HyperLogLog 的原理就是将每个元素视为一次投掷试验,通过记录试验的最大投掷次数对元素的数量进行预计。当咱们向汇合中每插入一个元素,视为做了一次投掷试验,雷同的元素对应一个投掷后果的序列。为了将每一个元素转化成一个“01”序列,咱们能够应用一个哈希函数进行转换:
这里,咱们有了一个简略的预计算法。咱们只须要记录哈希后果中第一个“1”呈现的地位的最大值即可,但很显著,当数据量较小时,这样一个估计值误差会很大,而且单个元素的对估计值的影响不平滑。
3.1.2 分桶均匀减小误差
为了减小繁多估计量的影响,HyperLogLog 应用分桶屡次试验的办法减小误差。办法是将哈希后的 bitmap 中前若干位当成桶的编号,残余位当成试验后果。
对于每个桶中的后果,计算其和谐平均值获取基数估计值(相比算术平均,和谐平均数可能无效改善基数较小状况下极值影响过大的问题):
3.2Redis 中的 HyperLogLog
Redis 将 HyperLogLog 实现成一种数据类型,对于每个元素,Redis 将其 Hash 成 64 位的二进制串,用低 14 位用来示意 bucket 的下标(所以桶的个数为 1 <<14=16384),残余的位用来模仿伯努利散布,每个桶须要 6 个 bit;最多可能对 个元素进行统计,内存占用约 12 k;其标准误差为 0.81%。
Redis 反对的 HyperLogLog 命令只有 3 个,pfadd,pfcoun,pfmerge, 其语法如下:
- pfadd:将所有元素参数增加到 HyperLogLog 数据结构中
语法:PFADD key element1 [element2…]
如果至多有一个元素被增加返回 1,否则返回 0
如果没有指定 element,则创立 hyperloglog key
127.0.0.1:6379> pfadd key1 ele1 ele2
(integer) 1
127.0.0.1:6379> pfadd key1
(integer) 0
127.0.0.1:6379> pfadd key2
(integer) 0
- pfcount:返回给定的 HyperLogLog 的基数估计值
语法:PFCOUNT key1 [key2 …]
返回对应 HyperLogLog 的基数值,多个 key 时,返回多个 key 的合并后的基数值。
127.0.0.1:6379> pfcount key1
(integer) 0
127.0.0.1:6379> pfadd key1 ele1 ele2
(integer) 1
127.0.0.1:6379> pfadd key2 ele1 ele3
(integer) 1
127.0.0.1:6379> pfcount key1
(integer) 2
127.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) 1
127.0.0.1:6379> pfadd key2 ele1 ele3
(integer) 1
127.0.0.1:6379> pfcount key3
(integer) 0
127.0.0.1:6379> pfmerge key3 key1 key2
OK
127.0.0.1:6379> pfcount key3
(integer) 3
3.3HyperLogLog 的实用场景
HyperLogLog 作为一种计算大数据量的基数统计算法,在统计注册用户数,每日拜访 IP 数,实时统计在线用户数等场景能够大显神威。
- 统计网站的 UV(unique visitor)
对于一个网页,咱们想要晓得这个网页的受关注水平,能够统计一下有多少用户(IP)点击了这个网页。为此,咱们给每个时间段设置一条记录,比方,127.0.0.1 这个 IP 在 2021 年 1 月 1 日 1 点的时候拜访了网页:
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 进行数据的保留与剖析。
- 对于每个标签,创立 hyperloglog key 值保留数据,如:man, woman,basketball…等,对于每个须要记录的值,都须要创立一个 key 进行记录。
- 每多一个用户时,向所有记录的 key 里应用 pfadd 增加元素。
- 进行数据分析时,应用 pfcount 将须要剖析的数据进行统计。
四、高斯 Redis 在计数上的劣势
4.1 开源 Redis 的问题
生产环境中,为防止单点故障,加强数据库可用性,Redis 通常将数据复制多个正本,保留在不同的服务器上;在大量并发申请过去时,为了尽可能利用主从节点的服务器资源,能够采纳主写从读的形式。因为 Redis 的主从同步是异步的,当主节点写入数据后,从节点不保障立即更新数据,如果此时读取数据,读到的就是过期的旧数据,产生数据不统一问题。
当主节点故障宕机后,数据不统一的问题会更重大。主节点故障后,哨兵节点会将从节点晋升为主,原主节点上沉积的数据 buffer 就彻底失落了。在电商秒杀业务中,如果产生主节点复制 buffer 沉积,导致从节点与主节点的 counter 偏大很多,一旦此时主节点宕机,产生主备倒换后,容易导致流量压力超出阈值,大量数据可能会将 MySQL 压垮,导致系统不可用。
4.2 高斯 Redis 如何解决
高斯 Redis 借助高斯品牌的“存算拆散”架构,将全量数据下沉到强统一存储层(DFV Pool),彻底摒弃了开源 Redis 的异步复制机制;计算层将海量数据进行分片,在故障场景下,主动进行接管,实现了服务的高可用。
存储层 DFV Pool 是华为外部自研的公司级 Data Lake,是分布式、强统一、高性能的先进架构。底层实现 3 正本强统一的存储,保障了在任何工夫点的数据强统一,故障状况下数据不失落,对于秒杀等业务满足计数的相对准确。此外,借助存算拆散架构,高斯 Redis 还领有低成本、大容量、秒扩容等劣势:
五、结语
高斯 Redis 在社区版 Redis 的根底上,联合华为自研强统一存储 DFV Pool,具备强统一、秒扩容、超可用、低成本等劣势,保障了计数的准确性、可靠性。
本文作者:华为云高斯 Redis 团队。
杭州西安深圳简历投递:yuwenlong4@huawei.com
更多技术文章,关注高斯 Redis 官网博客:https://bbs.huaweicloud.com/c…
六、参考资料
1.《Redis 利用场景 - 计数器》
https://blog.csdn.net/nklinsi…
2.《HyperLogLog 算法的原理解说以及 Redis 是如何利用它的》
https://juejin.cn/post/684490…
3.《五种罕用基数预计算法成果试验及实际倡议》
http://blog.codinglabs.org/ar…
4.《【云驻共创】从相识到相惜:Redis 与计算存储拆散四部曲》
https://bbs.huaweicloud.com/b…
5.《华为云 PB 级数据库 GaussDB(for Redis)揭秘第七期:高斯 Redis 与强统一》
https://bbs.huaweicloud.com/b…
点击关注,第一工夫理解华为云陈腐技术~