redis数据类型介绍
一、String
存储数据类型
可以用来存储INT、float、String。
常用操作命令
# 获取指定范围的字符
getrange test001 0 1
# 获取字符串长度
strlen test001
# 追加字符串
append test001 000
# 设置多个值 (原子操作)
mset test002 002 test003 003
# 获取多个值
mget test002 test003
# 设置值,如果key不存在则成功,key存在则不成功;基于此可实现分布式锁,用del key释放锁。
set test002 0002
# 设置值,如果key不存在则成功,key存在则不成功;并同时设置时效时间EX单位是秒,PX单位是毫秒
# * EX seconds − 设置指定的到期时间(以秒为单位)。
# * PX milliseconds - 设置指定的到期时间(以毫秒为单位)。
# * NX - 仅在键不存在时设置键。
# * XX - 只有在键已存在时才设置。
set key value [expiration EX secords|PX millisecord][NX|XX]
set test004 0004 EX 10 NX
# 整数值递增(值不存在则递增1)
incr test001
incrby test001 100
# 整数递减
decr test001
decr test001 100
# 浮点数增加
incrbyfloat 7.9
应用场景
缓存
String类型,缓存热点数据,可以显著的提升访问速度。
分布式数据共享
redis是分布式独立部署的服务,可以在多个服务之间共享
例如:分布式session
分布式锁
使用setnx方法,来实现分布式锁,只有不存在时才能添加成功,返回true。
全局ID
INT类型,通过incrby方法实现,利用redis的原子性
计数器
INT类型,通过incrby方法实现
例如:微博阅读量,点赞量等;允许一定的延迟,先写到redis在同步到数据库。
限流
INT类型,通过incrby方法实现。可以使用IP和一些信息作为key,访问一次就增加1。
二、Hash
存储数据类型
Hash用来存储多个无序的键值对。最大存储量2^32 - 1 (40亿左右)。
注意:Hash的value只能是字符串,不能嵌套其他类型,比如hash或者list。
Hash的字符串和String有啥区别?
- 把所有的value汇聚到一个key上面,节省内存空间。
- 只有一个key,减少冲突。
- 当要获取值的时候,只需要一个命令,减少内存/IO/CPU的消耗
Hash不适合的场景
- field需要单独设置过期时间。
- 需要考虑数据量分布的问题(field特别多的时候,无法分布到多个节点上)
常用操作命令
# 设置值
hset hash001 f1 v1
# 设置多个值
hmset hash001 f2 v2 f3 v3
# 获取单个值
hget hash001 f1
# 获取多个值
hmget hash001 f1 f2 f3
# 获取所有的值
hgetall hash001
# 查看所有的field
hkeys hash001
# 查看多有的value值
# 删除单个field
hdel hash001 f1
# 删除整个hash的数据
hdel hash001
应用场景
String可以做的事情,Hash都可以做。
存储对象类型的数据
例如:存储商品信息
可以设置很多个商品的属性,
可以通过hincr field 来增加来维护销量
也可以通过hdecr field 来维护库存
hgetall 查询商品详情
三、List
存储数据类型
存储有序字符串(从左到右),元素可以重复。最大存储数量2^32-1(大约40亿)。
这里可以理解成队列。
常用操作命令
# 增加元素
lpush mylist 0
rpush mylist 1 2 3
# 取出并删除
lpop mylist
rpop mylist
# 只取值
lindex mylist 0
lrange mylist 0 -1
# 阻塞弹出
blpop queue 1 100 # 1取出元素个数,100阻塞时间
brpop mylist
应用场景
有序列表,缓存公告列表,活动列表,通知列表等,按照时间排序的类表
可以缓存所有字段,使用lrange 方法来分页。
队列/栈
可以当做分布式环境下的队列/栈使用。
通过blpop 和brpop 命令实现阻塞队列功能。
队列:先进先出,rpush/blpop
栈:先进后出,rpush/brpop
四、set集合
储存数据类型
存储String类型的无序集合(去重),最大存储量2^32 - 1 (40亿左右)。
常用操作命令
# 添加一个或多个元素
sadd myset a b c d
# 获取所有的元素
smembers myset
# 统计元素个数
scard myset
# 随机获取一个元素
srandmember myset
# 随机弹出一个元素
spop myset
# 删除一个或多个元素
srem myset 0 2 3
# 查看元素是否存在
sismember myset a
# 两个集合取差集
sdiff set1 set2
# 两个集合取交集(intersection)
sinter set1 set2
# 两个集合取补集
sunion set1 set2
应用场景
抽奖
可以使用spop 命令随机弹出一个幸运儿。
点赞,签到,打卡
例如微博的点赞 ,假设微博 id = w1001,用户id = u1001
点赞:sadd like:w1001 u1001
取消点赞:srem like:w1001 u1001
点赞数量:scard like:w1001
所有点赞的人:smembers like:w1001
是否点赞:sismember like:w1001
商品标签
假设商品id=100
sadd tags:100 美观大方
sadd tags:100 安装服务好
用户关注模型
# 两个集合取差集
sdiff set1 set2
# 两个集合取交集(intersection)
sinter set1 set2
# 两个集合取补集
sunion set1 set2
可以使用以上集合交并补命令实现
我的关注集合 sadd like:001 user1 user2
你关注的集合 sadd like:002 user2 user3
- 相互关注只要判断,我的集合是否有你,你的集合是否有我,使用sismember命令
- 我关注的人也关注了她 我的集合和你的集合取交集,共同关注。
- 可能认识的人 我关注人,他们的集合取交集,存在的人,就可以是我认识的。
五、zset有序集合
存储数据类型
sorted set 存储有序的元素。每个元素都一个score,按照score从小到大排名。
score相同时,按照key的ASCII码排序。
List、set、zset数据结构对比
数据结构 | 是否存在重复元素 | 是否有序 | 有序的实现方式 |
---|---|---|---|
List | 是 | 是 | 索引下标 |
set | 否 | 否 | 无 |
zset | 否 | 是 | 分值score |
常用操作命令
# 添加元素,先添加分值
zadd myzset 10 java 20 ruby 30 python
# 查看所有元素(带分数)
zrange myzset 0 -1 withscores
zrevrange myzset 0 -1 withscores
#根据分数区间取元素
zrangebyscore myzset 20 30
# 移除元素,也可以根据分值区间移除
zrem myzset java
# 统计元素个数
zcard myzset
# 分值递增
zincrby myzset 5 python
# 根据分值区间统计个数
zcount myzset 0 100
# 获取排名,从0开始
zrank myzset python
# 获取分数
zscore myzset java
应用场景
顺序会变化的排名列表
例如:热搜
id为1001的新闻,点击量+1 zincrby hotNewSet:20210613 1 new1001
获取今天点击量最多的10条新闻: zrevrange hotNewSet:20210613 0 15
六、数据结构总结
对象 | 对象type属性值 | type命令输出 | 底层可能的储存结构 | object encoding |
---|---|---|---|---|
字符串对象 | OBJ_STRING | “string” | OBJ_ENCODING_INT OBJ_ENCODING_EMBSTR OBJ_ENCODING_RAW | int embstr raw |
哈希对象 | OBJ_HASH | “hash” | OBJ_ENCODING_ZIPLIST OBJ_ENCODING_HT | ziplist hashtable |
列表对象 | OBJ_LIST | “list” | OBJ_ENCODING_QUICKLIST | quicklist |
集合对象 | OBJ_SET | “set” | OBJ_ENCODING_INTSET OBJ_ENCODING_HT | intset hashtable |
有序集合对象 | OBJ_ZSET | “zset” | OBJ_ENCODING_ZIPLIST OBJ_ENCODING_SKIPLIST | ziplist skiplist+hashtable |
七、编码转换总结
对象 | 原始编码 | 升级编码 | |
---|---|---|---|
字符串对象 | INT 整数并且小于long 2^63-1 | embstr 超过44字节,被修改 | raw |
哈希对象 | ziplist 键和值的长度小于64byte,键值对个数不超过512个,同时满足 | hashtable | |
列表对象 | quicklist | ||
集合对象 | intset 元素都是整数类型,元素个数小于512个,同时满足 | hashtable | |
有序结合对象 | ziplist 元素数量不超过128个,任何一个member的长度小于64字节,同时满足 | skiplist |