Redis 基础数据类型

版权归原作者所有。 本文最后更新于:2023年12月5日 凌晨

String类型

不同类型的数据结构的差异都在于value
value类似java ArrayList

可以动态扩容

在实际分配的空间小于1MB时,扩容是加倍现有空间,如果超过1MB之后,扩容只会多扩容1MB,需要注意的是字符串长度最大为512MB

命令

set k1 v1
get k1
exists k1  # 是否存在k1缓存
del k1
mset k1 v1 k2 v2
mget k1 k2 k3
expire k1 5   # 5s后过期

setex  k1 5 v1  # 5s后过期,等价与  set+expire
setnx k1 v1 # k1如果存在则创建不成功

计数器

set age 10
incr age  # 这个时候 age变为11
incr age by 5 # 这个时候age变为 16
incr age by -5 # 这个时候age变为 11

字符串时间底层采用bitmap

list(列表)

相当于Java的链表(双向链表)

常用来作为异步队列使用
右边进左边出:队列

命令

rpush k1 v2 v3 v4
llen  k1   # 3
lpop k1  # v2
lpop  k1 # v3
右边进右边出:栈 (使用场景并不多)
rpush k1 v1 v2 v3
rpop k1 # v3

lindex 按照下表找到元素,因为是链表,所以要遍历链表,随着index变大而变差

ltrim 类似 java的字符串去除两边空格,但是这里去除的不是两边空格,而是按照 给出一个开始index和结尾index 得到子串,例如 k1=abcde ltrim k1 1 -2 得出来的是 bcd 这个方式,也是o(n), 需要慎用

快速列表

redis底层存储的并不是一个简单的linkedlist
而是为一个快速链表的,
首先用一块连续的内存存储,这个结构为 ziplist, 压缩链表
然后当数据量比较多的时候才会改为quicklist,快速链表
普通链表需要附加指针空间太大,会浪费空间,加重内存的碎片化
quicklist就是把多个ziplist 通过双指针连起来,这样满足插入性能,又不会出现太大的空间

hash(字典)

相当于Java HashMap

数组+链表的二维结构
hash碰撞后会使通过链表进行连接
redis hash值只能为string,rehash的方式不一样
渐进式rehash,就是每次会保存 old hash 和 new hash,当通过定时任务或者下一次hash时进行old hash迁移到new hash之后,搬迁完成之后 new hash才会替代old hash

命令

hset k1 f1 v1
hgetall k1
hlen k1
hget k1 f1
hmset k1 f1 v1 k2 f2 v2
hincrby k1 f1 1  # 给单个key中的字段数值 +1

set(集合)

Java HashSet

内部键值对是无序的、唯一的,内部相当于一个特殊的字典,key为值,value为NULL
set由于有去重的逻辑,所以存储例如中奖用户id,这样会保证同一个用户不会中奖多次

sadd k1 v1
sadd k1 v2 v3
smembers k1 # 返回的顺序和插入顺序不一致,因为无序
sismembers k1 v2 # 查询某个值是否存在
scard k1 # 获取长度
spop k1 # 弹出一个, 弹出代表:随机弹出一个,拿出来,这个时候查看长度也就减一了

zset(有序集合)

类似Java的SortedSet和HashMap的结合体

一方面是set 保证唯一性,另一方面 给每一个value 赋予一个score,用于排序的权重
内部实现了一个跳表数据结构

应用场景

可以用来存储分析关注列表,用户id为value 关注时间为 score
存储学生成绩 用户id 为value 学生成绩为 score

命令

zadd k1 1.0  v1
zadd k1 2.0  v2
zadd k1 3.0  v3
zrange k1 0 -1   # 按照score 排名输出,参数区间为排名范围  -1代表 从第0个开始到最后都输出  
输出  v1 v2 v3
zrange k1 0 1 # 从第0个到 第1个,这个0 1 是下表,并且取值为 左闭右闭区间 [0, 1] 输出位  v1 v2
zrevrange k1 0 1  # 逆序输出, 输出 v3 v2
zcard k1  # 看k1的长度
zcore k1 v1 # 这里输出精度会有问题,存储结构为double

image.png
zrank k1 v2 # 输出当前v2的排名 从0开始
zrangebyscore k1 0 2 # 按照分数范围去除,例如把分数作为筛选条件 左闭右闭区间
zrem k1 v1 # 删除一个元素

跳跃列表

zset要时间随机插入和删除,不适合用数组来实现
拓展知识:
对于任意位置按照顺序插入通常采用二分查找方式来找到位置插入,二分查找的对象必须是数组,只有数组才可以支持快速位置定位,

通过跳跃列表可以实现,实现类似生活中的层级制
跳跃表原理:
TODO

上面类型中有通用规则

容器型数据结构的通用规则

1、如果不存在则创建(create if not exists):如果容器不存在,就创建一个,然后rpush一个新元素
2、如果没有元素了则删除容器(drop if no elements): 如果容器内没有元素了则立即删除容器,释放内存

过期时间

所有的数据类型都可以设置过期事件,过期时间是以对象为单位设置的,例如hashmap的field不支持单独设置过期时间,如果设置过期时间,然后重新set 之后,过期时间会失效
exprire


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明蚁点博客出处!