【Redis的那些事 · 续集】Redis的位图、HyperLogLog数据结构演示以及布隆过滤器

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 位图的最小单位是bit,每个bit的值只能是0和1,位图的应用场景一般用于一些签到记录,例如打卡等。场景举例: 例如某APP要存储用户的打卡记录,如果按照正常的思路来做,可能是用户每天是否打卡的记录都单独设置一个key-value键值对来存储,这样的话,每个用户每天都需要耗费一个键值对空间。而如果是位图,就可以很方便地通过位图来进行记录


一、Redis位图


1、位图的最小单位是bit,每个bit的值只能是0和1,位图的应用场景一般用于一些签到记录,例如打卡等。


场景举例: 例如某APP要存储用户的打卡记录,如果按照正常的思路来做,可能是用户每天是否打卡的记录都单独设置一个key-value键值对来存储,这样的话,每个用户每天都需要耗费一个键值对空间。而如果是位图,就可以很方便地通过位图来进行记录,例如如下图:

1995789-20220101165802903-1364088580.png

 

位图不算基础数据结构或者特殊数据结构,其本质上还是字符串。由于每个bit代表一个数据,所以还可以当作是bit数组来看待。

 

2、可以通过命令:


setbit key 偏移量(索引位)  value(0/1,默认是0)

进行设置对应位置的位图数据。

通过命令:

getbit key 偏移量

可以获取到对应的位图索引数据。

也可以通过:

get key

来获取位图对应的字符串信息。


 1995789-20220101165843761-922817543.png

 

3、例如hello字符串的ascii码对应的二进制,分别是:


h: 01101000

e: 01100101

l: 01101100

l: 01101100

o: 01101111


以下设置字符串hello的位图操作,如图所示,字符串对应二进制数拼接起来的二进制,值为1所在的bit索引位(offset),使用:

setbit key offset 1

进行设置1即可。

 1995789-20220101165933861-932554592.png

 

setbit/gitbit 和 set/get 实际上是可以互相转换的,只是一种是操作bit位,一种是操作直接的值。同时可以互相交叉操作使用,例如setbit存储,get读取;set 存储,getbit读取等等。

 

4、可以通过命令: bitcount key 起始字符索引 结束字符索引


对指定key里面的数据,指定的字符索引区间内,获取到对应的位图数据是1的个数。如果不指定,则会获取到全部字符串对应位图的1的个数。如下图所示,结合以上二进制数据可知,h字符有3个1,o字符有6个1。

1995789-20220101170000477-985219408.png


以上指令操作可以适用于在类似打卡天数统计上使用,可以快速统计出区间内为1的数据个数。

 

5、通过命令:bitops  key  bit值(0/1)  起始字符索引 结束字符索引


可以获取到指定的区间内,第一次出现指定的bit值(0或1)所在的位图索引。如果不指定区间,默认代表字符串全部区间。如下图所示,hello里面,第一次出现1是在位图的第一个索引位置;第一次出现0是在第0个位图索引位;字符索引位为1代表第二个字符,第一次出现的值为1的位图索引位置为9。


注意: 字符串的索引,0到N,0代表第一个字符,例如’h’。位图的索引,也是0到N,0代表位图上面第一个bit位,值为0或者1,例如h的位图索引位置是0的值是0  (01101000)

1995789-20220101170306106-57173840.png

 

6、可以通过命令:


bitfield  key get 类型 位图索引

来获取指定类型数据的ascii码。

例如,以下截图中,命令:

bitfield hello get u8 0

其中,u8代表类型,u开头代表无符号数据,8代表获取8个bit位。如果是有符号的数据,是以i开头的。最后面的0,代表要获取的起始位图下标索引,此处是第0个索引。

hello五个字符,对应的ascii码分别为:104,101,108,108,111

如果以上命令的类型 u8 换成 u4 ,则获取到的值是0110,对应的值是6;以此类推。

也可以并列get获取,例如:

bitfield  key  get  type1 offset1  type2 offset2 ……

其他玩法,大佬们可以自己尝试。我这边有关操作可以参考如下截图所示内容。

1995789-20220101170329886-239475763.png

 

7、通过命令:


bitfield key set type 位图索引 ascii码

可以把对应的ascii码根据类型写入到指定的索引中,并且会返回原来索引被替换的ascii码值。


例如下图所示操作,位图索引从0开始,代表第一个字符h所在位置。97代表a的ascii码,执行以后,返回104(h的ascii码),并且通过get命令可以查看到字符串已经被替换了。

1995789-20220101170337350-2118249790.png

 

8、可以使用命令:


bitfield  key  incrby  type  索引  自增值

对指定类型和索引区间的值进行累加 ,如下图所示。h通过 u8 类型自增1,即h+1=i


注意:对于累加的数据不能超出指定类型的最大值,例如 u4 最大值是15,累加到15以后会自动折返为0。


1995789-20220101170344496-938807077.png

 

9、针对以上会出现折返的情况,可以使用溢出报错或者保持最大或最小值的方式来避免折返的情况。


使用命令:

Bitfield  key  overflow  fail  incrby  type  offset  value

可以实现溢出的时候,会返回nil;


使用命令:

Bitfield  key  overflow  sat  incrby  type  offset  value

可以实现当要溢出的时候,还是会返回当前的最大值或最小值。如下图所示。

1995789-20220101170352100-1450921889.png

 

二、HyperLogLog


10、HyperLogLog是一种可以快速去重的数据结构。但是有一定的误差率,大概在0.81%左右。应用场景一般是在需要针对一些大数据量的情况下进行去重计算大概的统计值使用,例如网站的PV量等等。


使用命令:

pfadd   key  value1  value2 ……

可以添加对应的多个数据集到指定的key里面去。

如果添加已经存在的数据,会被自动去重。

使用命令:pfcount key

可以统计数据集的个数。

使用命令:pfmerge 目标key  源key1   源key2  ……

可以对多个不同的key进行数据合并,并且数据集重复的会自动排重。


使用HyperLogLog的用途,是在针对大数据量的情况下,在允许一定的容错率的情况下,用它可以节约资源并且快速地进行排重。例如使用set来设置数据,资源损耗肯定是巨大的;但是使用hyperloglog来处理,资源损耗是固定的12kb,可以处理的数据量大约是2^64个数据。

1995789-20220101170403325-729245509.png


冷门科普:命令是pf开头,是为了纪念HyperLogLog的作者——Philippe Flajolet


三、布隆过滤器


11、布隆过滤器,最常见的场景是商品推荐业务。例如购物时候浏览的信息被记录以后,可以进行推荐其他同类型的其他商品。推荐的其他商品不会和浏览过的商品重复(去重),但是也存在一定的误差。


布隆过滤器源地址链接:

https://github.com/RedisBloom/RedisBloom

 

先进行下载,下载方式可以按照自己喜欢的方式下载。例如此处我下载到d目录下的wesky/bloom文件夹下。

 1995789-20220101170626508-492916146.png

 

然后进入到文件夹内,使用make命令进行编译。编译成功的话,会产生一个 redisbloom.so的文件。如下,我也很尴尬,没成功,就暂且到这里吧。

1995789-20220101170637800-1665123082.png

 

假如上面配置成功的话,启动redis服务的时候,可以把.so文件配置到redis.conf配置文件下,例如我上面所在的位置,新增的样式如下:

loadmodule D:/Wesky/Bloom/RedisBloom/redisbloom.so

或者使用命令启动的时候,使用命令进行指定:

redis-server --loadmodule D:/Wesky/Bloom/RedisBloom/redisbloom.so

 

由于当前我本机无法编译布隆过滤器源码,所以就暂且到这吧,请见谅。

布隆过滤器下,会有一些命令,供参考,大家可以根据自己情况,进行自己尝试,当作是留个悬念了。

命令:

bf.add  key  xxx

bf.madd  key  数据1   数据2 ……

bf.exists key 数据

bf.mexists key 数据1 数据2 ……


相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
25天前
|
存储 消息中间件 NoSQL
Redis数据结构:List类型全面解析
Redis数据结构——List类型全面解析:存储多个有序的字符串,列表中每个字符串成为元素 Eelement,最多可以存储 2^32-1 个元素。可对列表两端插入(push)和弹出(pop)、获取指定范围的元素列表等,常见命令。 底层数据结构:3.2版本之前,底层采用**压缩链表ZipList**和**双向链表LinkedList**;3.2版本之后,底层数据结构为**快速链表QuickList** 列表是一种比较灵活的数据结构,可以充当栈、队列、阻塞队列,在实际开发中有很多应用场景。
|
30天前
|
存储 消息中间件 NoSQL
Redis 数据结构与对象
【10月更文挑战第15天】在实际应用中,需要根据具体的业务需求和数据特点来选择合适的数据结构,并合理地设计数据模型,以充分发挥 Redis 的优势。
55 8
|
29天前
|
存储 NoSQL Java
介绍下Redis 的基础数据结构
本文介绍了Redis的基础数据结构,包括动态字符串(SDS)、链表和字典。SDS是Redis自实现的动态字符串,避免了C语言字符串的不足;链表实现了双向链表,提供了高效的操作;字典则类似于Java的HashMap,采用数组加链表的方式存储数据,并支持渐进式rehash,确保高并发下的性能。
介绍下Redis 的基础数据结构
|
25天前
|
存储 NoSQL 关系型数据库
Redis的ZSet底层数据结构,ZSet类型全面解析
Redis的ZSet底层数据结构,ZSet类型全面解析;应用场景、底层结构、常用命令;压缩列表ZipList、跳表SkipList;B+树与跳表对比,MySQL为什么使用B+树;ZSet为什么用跳表,而不是B+树、红黑树、二叉树
|
25天前
|
存储 NoSQL Redis
Redis常见面试题:ZSet底层数据结构,SDS、压缩列表ZipList、跳表SkipList
String类型底层数据结构,List类型全面解析,ZSet底层数据结构;简单动态字符串SDS、压缩列表ZipList、哈希表、跳表SkipList、整数数组IntSet
|
Web App开发 缓存 NoSQL
【Redis】布隆过滤器原理与应用
【Redis】布隆过滤器原理与应用
|
缓存 NoSQL Redis
详细解析Redis中的布隆过滤器及其应用
之前的布隆过滤器可以使用Redis中的位图操作实现,直到Redis4.0版本提供了插件功能,Redis官方提供的布隆过滤器才正式登场。布隆过滤器作为一个插件加载到Redis Server中,就会给Redis提供了强大的布隆去重功能。
540 0
详细解析Redis中的布隆过滤器及其应用
|
1月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
77 6
|
13天前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
14天前
|
存储 缓存 NoSQL
【赵渝强老师】基于Redis的旁路缓存架构
本文介绍了引入缓存后的系统架构,通过缓存可以提升访问性能、降低网络拥堵、减轻服务负载和增强可扩展性。文中提供了相关图片和视频讲解,并讨论了数据库读写分离、分库分表等方法来减轻数据库压力。同时,文章也指出了缓存可能带来的复杂度增加、成本提高和数据一致性问题。
【赵渝强老师】基于Redis的旁路缓存架构
下一篇
无影云桌面