Redis的三种新类型
三种新类型不是只都是redis6新增加的类型,而是区别于常见常用的类型
为什么会有这些类型1
在很多场景中,mysql或redis的基本类型可以解决,但是会浪费很多无用资源
在这样一个场景中你会如何来解决?
mysql实现
如果没有使用过或不常使用redis第一个想到的应该就是mysql了吧,当然我也不例外😄。
每次我们签到都要存入如下的数据结构
以上就是一个用户签到一天所要存储的数据(当然可能还会有更多字段),是不是觉得有点过于冗余
第一,我们只是想知道某一天是否签到过 用 0,1来表示就可以了
第二,我们只需要知道总共有多少个1,或者有多少个连续的1就可以了
常用redis实现
- 我们可以使用string 的append来实现
- 我们可以使用list 来实现
当然 set, hash,zset也是可以实现的,这里我就不一一举例了
那么问题又来了,这是最好的解决办法吗?0 和 1 来表达数据难道没有让你想到什么吗?
bit 是最小的单位 可以存的数据就是 0 或者 1 ,我们存储的字符串‘1’对应的ASCII码为49 二进制位 0011 0001 。
由此可以发现本来可以存储8个数据却仅仅存储的一个数据,由此导致了内存浪费,所以可以用redis提供的bitmap来解决问题
为什么会有这些类型2 - 亿级系统常见的四种统计
- 聚合统计 -
交差并等集合统计 - set - 排序统计 -
抖音视频最新评论留言的场景 - list,zset list会有问题 - 二值统计 -
签到 - bitmap - 基数统计 -
不重复元素个数 - hyperloglog
list排序统计,如展示最新几条的数据时,请求量多的话,可能会在分页时出现重复数据,所以zset会更好
bitmap - 位图
用String类型作为底层数据结构实现的一种统计二值状态的数据类型
位图本质是数组,它是基于String数据类型的按位的操作。该数组由多个二进制位组成,每个二进制位都对应一个偏移量(我们可以称之为一个索引或者位格)。Bitmap支持的最大位数是2^32位,它可以极大的节约存储空间,使用512M内存就可以存储多大42.9亿的字节信息(2^32 = 4294967296)
常用命令
SETBIT key offset value 设置offset索引的值 (只能为0或1)
GETBIT key offset 获取offset索引的值
BITCOUNT key [start end] 获取范围内总共有多少个1
BITOP 两个key 与或非运算 AND, OR, XOR, NOT
BITPOS 查找第一个 0 或者 1 的索引
此时我们来验证bitmap底层是string,并且为8位一组
我们存储的bm1 只存储了第一位 我们看看get bm1试一下
此时的结果是 "\x80" ,get 命令是string的哦
打开我们的redis可视化客户端(第二篇有安装)
可以发现我们存了8位也就是1byte的数据
应用场景
- 签到场景
- 日活统计
- 连续打卡签到
- ....
Hyperloglog
在网站或其他产品上,经常会有UV(单日独立访问),PV(浏览量),DAU(日活跃),MAU(月活跃)等数据,在这种情况下就可以使用Hyperloglog
只是进行不重复的基数统计,不是集合也不保存数据,只记录数量而不是具体内容。
Hyperloglog 以空间换取精确度,最大只占用12kb。(后面会详细介绍)
常用命令
PFADD key element .... 将所有元素添加到key中
PFCOUNT key 统计key的估算值(不准确)
PGMERGE new_key key1 key2 ... 合并多个key到新key
应用场景
产品的UV(单日独立访问),PV(浏览量),DAU(日活跃)等统计
GEO
地理位置的处理
底层应用zset
关于GeoHash
常用命令
GEOADD 多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中
GEOPOS 从键里面返回所有给定位置元素的位置(经度和纬度)
GEODIST 返回两个给定位置之间的距离。
GEORADIUS 以给定的经纬度为中心, 返回与中心的距离不超过给定最大距离的所有位置元素。
GEORADIUSBYMEMBER 跟GEORADIUS类似
GEOHASH 返回一个或多个位置元素的 Geohash 表示
应用场景
- 打车软件
- 附近共享单车
- 美团附近商家
- ......
总结
好了这就是三种拓展类型了,其中还有很多关于底层的没有讲解,后续会在源码中详细解释的。