文章目录
前言
Redis,作为一款高性能的键值对数据库,凭借其出色的性能和丰富的数据类型,在缓存、消息队列、计数器等多种场景中发挥着重要作用。它支持多种数据类型,包括字符串(string)、哈希(hash)、列表(list)、集合(set)以及有序集合(zset),每种数据类型都有其独特的使用场景和优势。
在这篇博客中,我们将深入探讨Redis中的这五种核心数据类型,详细解析每种数据类型的特性、使用场景以及操作方法。同时,我们也将介绍对Redis键(key)的各种操作方法及样例,以更好地理解和应用Redis。
redis官网:https://redis.io/
Redis 数据类型 | 菜鸟教程:https://www.runoob.com/redis/redis-data-types.html
redis数据类型
string
1. 设置单个字符串数据
set 设置的数据没有额外操作时,是不会过期的。
语法:set key value
例如:设置键为name
值为xiaoming
的数据,如果name存在,则表示修改name的值,如果name不存在,则表示添加一个key为name,value为"xiaoming"。
set name xiaoming
2.设置多个字符串类型的数据
语法:
mset key1 value1 key2 value2 ...
例如:设置键为a1
值为python
、键为a2
值为java
、键为a3
值为c
mset a1 python a2 java a3 c
3.字符串拼接值
append的key如果不存在,则相当于set添加了一个字符串数据。
语法:append key value
例如:向键为a1
中拼接值haha
append title "我的" append title "redis" append title "学习之路"
4.根据键获取字符串的值
根据键获取值,如果不存在此键则返回
nil
,相当于python的None
语法:get key
例如:获取键name
的值
get name
5.根据多个键获取多个值
语法:
mget key1 key2 ...
例如:获取键a1、a2、a3
的值
mget a1 a2 a3
6.自增自减
set num 1 incr num # 相当于num+=1 get num # 2 incr num # 相当于num+=1 get num # 3 set goods:10 100 decr goods:10 # 相当于 goods:10-=1 get goods:10 # 99 decr goods:10 # 相当于goods:10-=-1 get goods:10 # 98
7.获取字符串的长度
set name xiaoming strlen name # 8
8.比特流操作
使用场景:签到记录、布隆过滤器(防止缓存击穿的一种防范手段)、打卡记录、心跳检测。
命令 | 描述 |
---|---|
BITCOUNT | 统计字符串的值被设置为1的bit数. |
BITPOS | 返回字符串里面第一个被设置为1或者0的bit位。 |
SETBIT | 设置一个bit数据的值 |
GETBIT | 获取一个bit数据的值 |
# 假设做一个签到功能,记录用户一年内的所有签到次数。 # 签到,id为1的用户2022年第7天签到 setbit user:1:checkin:2022 7 1 # 00000001 # 查询,用户1在2022年第7天是否上班 getbit user:1:checkin:2022 7 # 1 # 查询,用户1在2022年第3天是否上班 getbit user:1:checkin:2022 3 # 0 # 补签,用户1在2022年第4天补签 setbit user:1:checkin:2022 4 1 # 00001001 # 签到,用户1在2022年第15天签到 setbit user:1:checkin:2022 15 1 # 0000100100000001 # 统计,用户1在2022年一共签到了多少天 bitcount user:1:checkin:2022 # 3 # 查询,首次签到是什么时候 bitpos user:1:checkin:2022 1 # 4
key操作
redis中所有的数据都是通过key(键)来进行操作,这里是一些关于任何数据类型都通用的命令。
a.查找键
参数支持简单的正则表达式:
keys pattern
查看所有键:keys *
例如:
# 查看名称中包含`e`的键 keys *e* # 查看以n开头的键 keys n* # 查看以数字结尾的键 keys *[1-9] # 查看2022年所有用户的签到记录的key列表 keys user:*:checkin:2022
b.设置键值的过期时间
redis中可以对一切的数据进行设置有效期,不仅是string,还包括其他的四种数据类型。
语法:setex key seconds value
例如:设置键为name
值为xiaoming
过期时间为20秒的数据
setex name 20 xiaoming
c.查看键的有效期
语法:
ttl key
- 结果是秒作为单位的整数
- -1 表示永不过期
- -2 表示当前数据已经过期,查看一个不存在的数据的有效期就是-2
d.设置key的有效期
给已有的数据重新设置有效期,redis中所有的数据都可以通过expire来设置它的有效期。
语法:expire key seconds
例如:设置一个hash数据的有效期为30秒
hset person:1 name xiaoming age 17 expire person:1 30 ttl person:1 # 30
e.判断键是否存在
- 在redis中如果key没有被设置或者过期了,则key不存在。
- 可以使用
exists key
来判断,如果存在返回1
,不存在返回0
例如:判断键title
是否存在
exists title
f.查看键的数据类型
语法:
type key
- none 空,当前数据不存在
- string 字符串
- hash 哈希类型
- list 列表类型
- set 无序集合
- zset 有序集合
g.查看键的值数据类型
set name xiaoming type name # string sadd member_list xiaoming xiaohong xiaobai # (integer) 3 type member_list # set hset user_1 name xiaobai age 17 sex 1 # (integer) 3 type user_1 # hash lpush brothers zhangfei guangyu liubei xiaohei # (integer) 4 type brothers # list zadd achievements 61 xiaoming 62 xiaohong 83 xiaobai 78 xiaohei 87 xiaohui 99 xiaolong # (integer) 6 type achievements # zset
h.key重命名
改变key的名称,但是不会修改值。
语法:rename 旧的key 新的key
例如:把name重命名为username
set name xioaming rename name username get username
i.删除键以及键对应的值
删除key表示可以删除任意类型的数据。
语法:del key
# 删除一个key del name # 删除多个key del title num
j.清空所有key
慎用,一旦执行,则redis所有数据库0~15的全部key都会被清除
语法:flushall
k.select切换数据库
redis的配置文件中,默认有0~15之间的16个数据库,默认操作的就是0号数据库
语法:select <数据库ID>
# 默认处于0号库 127.0.0.1:6379> select 1 OK # 这是在1号库 127.0.0.1:6379[1]> set name xiaoming OK 127.0.0.1:6379[1]> select 2 OK # 这是在2号库 127.0.0.1:6379[2]> set name xiaohei OK
hash
1.设置指定键的单个属性
语法:
hset key field value
例如:设置键 user:1
的属性name
为xiaoming
127.0.0.1:6379> hset user:1 name xiaoming # user:1 没有的key会自动创建,并因为使用hset,所以是一个hash数据类型 (integer) 1 127.0.0.1:6379> hset user:1 name xiaohong # user:1中重复的属性name会被修改,返回值为0,是因为没有新增属性。 (integer) 0 127.0.0.1:6379> hset user:1 age 16 # user:1中没有的属性会被新增 (integer) 1 127.0.0.1:6379> hset user:1 sex 1 classmate 301 # hset可以一次性增加多个成员。 # 注意:在redis旧版本中,设置多成员可以使用hmset,新版本没有hmset (integer) 2
2.获取指定键的域/属性的值
获取hash的所有成员
语法:hgetall key
例如:获取user:3的所有成员
127.0.0.1:6379> hgetall user:3 1) "name" 2) "xiaohong" 3) "age" 4) "17" 5) "sex" 6) "1"
例如:获取指定键所有的域/属性
hkeys key
例如:获取键user的所有域/属性
127.0.0.1:6379> hkeys user:1 1) "name" 2) "age" 3) "sex" 4) "classmate" 127.0.0.1:6379> hkeys user:3 1) "name" 2) "age" 3) "sex"
3.删除指定键的域/属性
语法:
hdel key field1 field2 ...
例如:删除键user:1
的属性classmate/age
,当键中的hash数据没有任何属性,则当前键会被redis删除
127.0.0.1:6379> hdel user:1 classmate age (integer) 2
4.判断指定属性/域是否存在于当前hash中
语法:
hexists key field
例如:判断user:3中是否存在age属性或classmate属性
127.0.0.1:6379> hexists user:3 age (integer) 1 127.0.0.1:6379> hexists user:3 classmate (integer) 0
5.属性值自增自减
语法:
hincrby key field number
例如:给user:3的age属性在age现有值的基础上-2
# 按指定数值自增 127.0.0.1:6379> hincrby user:3 age 2 (integer) 19 127.0.0.1:6379> hincrby user:3 age 2 (integer) 21 # 按指定数值自减 127.0.0.1:6379> hincrby user:3 age -2 (integer) 19 127.0.0.1:6379> hincrby user:3 age -2 (integer) 17
6.获取hash的成员数量
语法:
hlen key
例如:获取hash的成员数量
127.0.0.1:6379> hlen user:3 (integer) 3
list
列表,有顺序的数据结构,其子成员类型为string,可以是重复的成员。
1.添加子成员
- 在左侧(上方,前面)添加一条或多条数据
lpush key value1 value2 ...
- 在右侧(上方,后面)添加一条或多条数据
rpush key value1 value2 ...
- 指定元素的左边(前免,上方)/右边(后面,下方)插入一个或多个数据
linsert key before 指定元素 value1 value2 ....
linsert key after 指定元素 value1 value2 ....
例如:从键为team:1
的列表左侧添加一个或多个数据xiaoming、xiaohong、xiaohei、xiaobai
# brother这个key如果不存在,则表示新建列表 lpush team:1 xiaoming (integer) 1 # 如果brother这个key存在了,则表示给已有列表左侧添加成员 127.0.0.1:6379> lpush team:1 xiaohong (integer) 2 # lpush还支持一次性左侧添加多个成员 127.0.0.1:6379> lpush team:1 xiaohei xiaobai (integer) 4
2.设置指定索引位置成员的值
- redis的列表也有索引,从左往右,从0开始,逐一递增,第1个元素下标为0,索引可以是负数,表示尾部开始计数,如
-1
表示最后1个元素。lset key index value
例如:修改键为team:1
的列表中下标为5
的元素值为xiaocao2
lset team:1 5 xiaocao2
3.删除指定成员
语法:
lrem key count value
- count表示删除的数量,value表示要删除的成员。该命令默认表示将列表从左侧前count个value的元素移除
- count==0,表示删除列表所有值为value的成员
- count >0,表示删除列表左侧开始的前count个value成员
- count <0,表示删除列表右侧开始的前count个value成员
127.0.0.1:6379> rpush team:3 xiaoA xiaoB xiaoA xiaoC xiaoA xiaoB (integer) 6 127.0.0.1:6379> lrem team:3 2 xiaoA (integer) 2 # 从左侧开始删除2个xiaoA 127.0.0.1:6379> lrange team:3 0 -1 1) "xiaoB" 2) "xiaoC" 3) "xiaoA" 4) "xiaoB" 127.0.0.1:6379> del team:3 (integer) 1 127.0.0.1:6379> rpush team:3 xiaoA xiaoB xiaoA xiaoC xiaoA xiaoB (integer) 6 # 从右侧开始删除2个xiaoA 127.0.0.1:6379> lrem team:3 -2 xiaoA (integer) 2 127.0.0.1:6379> lrange team:3 0 -1 1) "xiaoA" 2) "xiaoB" 3) "xiaoC" 4) "xiaoB" # 删除所有xiaoA 127.0.0.1:6379> del team:3 (integer) 1 127.0.0.1:6379> rpush team:3 xiaoA xiaoB xiaoA xiaoC xiaoA xiaoB (integer) 6 127.0.0.1:6379> lrem team:3 0 xiaoA (integer) 3 127.0.0.1:6379> lrange team:3 0 -1 1) "xiaoB" 2) "xiaoC" 3) "xiaoB"
4.获取列表成员
根据指定的索引获取成员的值
语法:lindex key index
例如:获取team:1
下标为2以及-2的成员
127.0.0.1:6379> lindex team:1 2 "xiaocao" 127.0.0.1:6379> lindex team:1 -2 "xiaohong"
5.获取列表的切片
闭区间 (start, stop)
语法:lrange key start stop
# 获取列表的前三个成员 127.0.0.1:6379> lrange team:1 0 2 1) "xiaobai" 2) "xiaoshu" 3) "xiaocao" # 获取下标为2-4之间的成员 127.0.0.1:6379> lrange team:1 2 4 1) "xiaocao" 2) "xiaohua" 3) "xiaohei" # 获取列表尾部的三个成员 127.0.0.1:6379> lrange team:1 -3 -1 1) "xiaolan" 2) "xiaohong" 3) "xiaoming" # 注意,redis的列表切片取值方向是从左往右的。 127.0.0.1:6379> lrange team:1 -1 -3 (empty array) # 获取列表的全部成员 127.0.0.1:6379> lrange team:1 0 -1 1) "xiaobai" 2) "xiaoshu" 3) "xiaocao" 4) "xiaohua" 5) "xiaohei" 6) "xiaocao2" 7) "xiaohua" 8) "xiaolan" 9) "xiaohong" 10) "xiaoming"
6.获取列表的长度
语法:
llen key
例如:获取brother列表的成员个数
127.0.0.1:6379> llen team:1 (integer) 10
set
无序集合,特点就是去重和无序。成员也只能是string。
1.添加元素
语法:
sadd key member1 member2 ...
例如:向键authors
的集合中添加元素zhangsan
、lisi
、wangwu
sadd authors zhangsan sili wangwu
2.获取集合的所有成员
语法:
smembers key
例如:获取键authors
的集合中所有元素
smembers authors
3.获取集合的长度
语法:
scard keys
例如:获取authors集合的长度
127.0.0.1:6379> scard authors (integer) 3
4.随机获取一个或多个成员
当集成的所有成员都被删除或提取出来,则key会自动被redis回收。
spop key [count=1]
- count为可选参数,不填则默认1个。被提取成员会从集合中被删除掉
例如:随机获取authors集合的1个或多个成员
127.0.0.1:6379> sadd authors zhangsan sili wangwu (integer) 3 127.0.0.1:6379> spop authors "sili" 127.0.0.1:6379> spop authors "wangwu" 127.0.0.1:6379> spop authors "zhangsan" 127.0.0.1:6379> sadd authors zhangsan sili wangwu (integer) 3 127.0.0.1:6379> spop authors 2 1) "sili" 2) "zhangsan" 127.0.0.1:6379> spop authors 2 1) "wangwu" 127.0.0.1:6379> spop authors 2 (empty array)
5.删除指定元素
语法:
srem key value
例如:删除键authors
的集合中元素wangwu
srem authors wangwu
6.交集、差集和并集
- 交集,比较多个集合中共同存在的成员
sinter key1 key2 key3 ....
- 差集,比较多个集合中不同的成员,我有你(们)没有的
sdiff key1 key2 key3 ....
- 并集,合并所有集合的成员,并去重
sunion key1 key2 key3 ....
例如:商城的购物推荐,根据用户的购买的商品的相似度来进行推荐
# 基本数据 # user:1 = {1,2,3,4} sadd user:1 1 2 3 4 # user:2 = {1,3,4,5} sadd user:2 1 3 4 5 # user:3 = {1,3,5,6} sadd user:3 1 3 5 6 # user:4 = {2,3,4} sadd user:4 2 3 4 # 交集 127.0.0.1:6379> sinter user:1 user:2 1) "1" 2) "3" 3) "4" 127.0.0.1:6379> sinter user:1 user:3 1) "1" 2) "3" 127.0.0.1:6379> sinter user:1 user:4 1) "2" 2) "3" 3) "4" 127.0.0.1:6379> sinter user:2 user:4 1) "3" 2) "4" # 并集 127.0.0.1:6379> sunion user:1 user:2 user:4 1) "1" 2) "2" 3) "3" 4) "4" 5) "5" # 差集 127.0.0.1:6379> sdiff user:2 user:3 1) "4" # 此时可以给user:3推荐4 127.0.0.1:6379> sdiff user:3 user:2 1) "6" # 此时可以给user:2推荐6 127.0.0.1:6379> sdiff user:1 user:3 1) "2" 2) "4"
zset
有序集合(sortedSet),去重并且根据score权重值(分数)对值进行排序。score从小到大或从大到小排列。有序集成的成员都是由分数+值组成的。
1.添加成员
语法:
zadd key score1 member1
zadd key score1 member1 score2 member2 score3 member3 ....
例如:设置榜单achievements,设置成绩和用户名作为achievements的成员
127.0.0.1:6379> zadd achievements 61 xiaoming 62 xiaohong 83 xiaobai 78 xiaohei 87 xiaohui 99 xiaolan (integer) 6 127.0.0.1:6379> zadd achievements 85 xiaohuang (integer) 1 127.0.0.1:6379> zadd achievements 54 xiaoqing
2.给指定成员增加权重值(分数)
语法:
zincrby key score member
例如:给achievements中xiaobai增加10分
127.0.0.1:6379> ZINCRBY achievements 10 xiaobai "93
3.获取集合长度
ps:也就是成员的个数
语法:
zcard key
例如:获取achievements的长度
zcard achievements
4.获取指定成员的权重值
语法:
zscore key member
例如:获取指定成员的权重值
127.0.0.1:6379> zscore achievements xiaobai "93" 127.0.0.1:6379> zscore achievements xiaohong "62" 127.0.0.1:6379> zscore achievements xiaoming "61"
5.获取指定成员在集合中的排名
ps:排名从0开始计算
语法:
srank key member # score从小到大的排名
zrevrank key member # score从大到小的排名
例如:获取achievements中xiaohei的分数排名
# 从大到小 127.0.0.1:6379> zrevrank achievements xiaohei (integer) 4 # 从小到大 127.0.0.1:6379> zrank achievements xiaohei (integer) 3
6.获取在指定score区间的所有成员数量
语法:
zcount key min max
例如:获取achievements从0~60分之间的人数[闭区间]
127.0.0.1:6379> zadd achievements 60 xiaolv (integer) 1 127.0.0.1:6379> zadd achievements 0 xiaocao (integer) 1 # 获取分数在 (0,60) 这个区间的成员 127.0.0.1:6379> zcount achievements 0 60 (integer) 3 127.0.0.1:6379> zcount achievements 61 100 (integer) 7
7.获取在指定score/index区间的所有成员
语法:
zrangebyscore key min max
# 按score进行从低往高排序获取指定score区间`zrevrangebyscore key min max
# 按score进行从高往低排序获取指定score区间`zrange key start stop
# 按scoer进行从低往高排序获取指定索引区间`zrevrange key start stop
# 按scoer进行从高往低排序获取指定索引区间`
例如:获取achievements中在(60,70)这个区间的数据
127.0.0.1:6379> zrangebyscore achievements 0 60 1) "xiaocao" 2) "xiaoqing" 3) "xiaolv" 127.0.0.1:6379> zrangebyscore achievements 90 100 1) "xiaobai" 2) "xiaolan"
8.删除成员
语法:
zrem key member1
zrem key member1 member2 member3 ....
例如:从achievements中删除xiaoming的数据
zrem achievements xiaoming
9.删除指定数量的成员
语法:
zpopmin key [count]
# 删除指定数量的成员,从最低score开始删除zpopmax key [count]
# 删除指定数量的成员,从最高score开始删除
# 如果不指定count,则删除一个成员,zpopmin表示从score分数最低开始删除,而zpopmax则表示从score分数最高开始删除 127.0.0.1:6379> zpopmin achievements 1) "xiaocao" 2) "0" 127.0.0.1:6379> zpopmax achievements 1) "xiaolan" 2) "99" # 从achievements中提取并删除成绩最低的2个数据 127.0.0.1:6379> zpopmin achievements 2 1) "xiaoqing" 2) "54" 3) "xiaolv" 4) "60" # 从achievements中提取并删除成绩最高的2个数据 127.0.0.1:6379> zpopmax achievements 2 1) "xiaobai" 2) "93" 3) "xiaohui" 4) "87"
各种数据类型在开发中的常用业务场景
针对各种数据类型它们的特性,使用场景如下:
- 字符串string: 用于保存一些项目中的普通数据,只要键值对的都可以保存,例如,保存 session/jwt,定时记录状态,倒计时、验证码、防灌水答案
- 哈希hash:用于保存项目中的一些对象结构/字典数据,但是不能保存多维的字典,例如,商城的购物车,文章信息,json结构数据
- 列表list:用于保存项目中的列表数据,但是也不能保存多维的列表,例如,消息队列,秒杀系统,排队,浏览历史
- 无序集合set: 用于保存项目中的一些不能重复的数据,可以用于过滤,例如,候选人名单, 作者名单
- 有序集合zset:用于保存项目中一些不能重复,但是需要进行排序的数据, 例如:分数排行榜, 海选人排行榜,热搜排行