redis中有哪些数据类型?这个问题我被面试官问过好多次了,下面总结下这5种数据类型的特点,命令,还有应用场景
redis客户端的一些通用命令:
ping # 测试redis是否链接 如果已链接返回 PONG
echo message # 测试redis是否链接 如果已链接返回给定的message字符串
keys * # 返回所有的 key 可以加*通配
exists key # 判断key是否存在 如果存在返回1,否则返回0
expire key time(s) # 设置一个 key 的过期时间 单位秒。时间到达后会删除 key 及 value
ttl key # 查询已设置过期时间的 key 的剩余时间 如果返回-2 表示该键值对已经被删除
persist key # 移除给定 key 的过期时间
select dbindex # 选择数据库(0-15)
move key dbIndex # 将当前数据库中的 key 转移到其他数据库中; 如果当前数据库(源数据库)和给定数据库(目标数据库)有相同名字的给定 key ,或者 key 不存在于当前数据库,那么 MOVE 没有任何效果。
dbsize # 返回当前数据库中的 key 的数目info 获取服务器的信息和统计
flushdb # 删除当前选择的数据库中的 key
flushall # 删除所有数据库中的所有 key
quit/exit # 退出连接
一、String类型
1、特点:
https://blog.csdn.net/pugongying_95/article/details/99718749
https://blog.csdn.net/dazhu233/article/details/80072471
-
Redis中,默认以SDS(simple dynamic string)作为自己的字符串表示。只有在一些字符串不可能出现变化的地方使用C字符串。
-
string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。
-
string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
-
string 类型的值最大能存储 512MB。
2、常用命令:
① SET key value [EX seconds] [PX milliseconds] [NX|XX] 将键key
设定为指定的“字符串”值。
127.0.0.1:6379> set name Tom
OK
127.0.0.1:6379> get name
"Tom"
如果 key 已经保存了一个值,那么这个操作会直接覆盖原来的值,并且忽略原始类型。
127.0.0.1:6379> set name Bob
OK
127.0.0.1:6379> get name
"Bob"
选项参数:从2.6.12版本开始,redis为SET
命令增加了一系列选项:
-
EX
seconds – Set the specified expire time, in seconds. 设置指定的过期时间,单位为秒127.0.0.1:6379> set token 123456 EX 5 OK 127.0.0.1:6379> get token "123456" 127.0.0.1:6379> get token "123456" 127.0.0.1:6379> get token "123456" 127.0.0.1:6379> get token (nil) # SET key value EX seconds等同于SETEX key seconds value 127.0.0.1:6379> setex token 5 123456 OK 127.0.0.1:6379> get token "123456" 127.0.0.1:6379> get token (nil)
-
PX
milliseconds – Set the specified expire time, in milliseconds. 给key
设置指定的过期时间,单位为毫秒127.0.0.1:6379> set token 123456 PX 5000 OK 127.0.0.1:6379> get token "123456" 127.0.0.1:6379> get token "123456" 127.0.0.1:6379> get token (nil) # SET key value PX milliseconds等同于PSETEX key milliseconds value 127.0.0.1:6379> psetex token 5000 123456 OK 127.0.0.1:6379> get token "123456" 127.0.0.1:6379> get token "123456" 127.0.0.1:6379> get token (nil)
-
NX
– Only set the key if it does not already exist. 当key
不存在的时候才设置127.0.0.1:6379> set name Lucy OK 127.0.0.1:6379> get name "Lucy" 127.0.0.1:6379> set name Lucy2 NX # name已经存在,设置失败 (nil) 127.0.0.1:6379> get name "Lucy" 127.0.0.1:6379> set name2 Lucy2 NX # name2不存在,设置成功 OK 127.0.0.1:6379> get name "Lucy" 127.0.0.1:6379> get name2 "Lucy2" # SET key value NX等同于SETNX key value 127.0.0.1:6379> set age 10 OK 127.0.0.1:6379> get age "10" 127.0.0.1:6379> setnx age 20 (integer) 0 127.0.0.1:6379> get age "10" 127.0.0.1:6379> setnx age1 20 (integer) 1 127.0.0.1:6379> get age1 "20"
-
XX
– Only set the key if it already exist. 当key
存在时才设置127.0.0.1:6379> get name "Jack" 127.0.0.1:6379> get name3 (nil) 127.0.0.1:6379> set name3 Jack3 XX # name3不存在,设置失败 (nil) 127.0.0.1:6379> get name3 (nil) 127.0.0.1:6379> set name Jack3 XX # name存在,设置成功 OK 127.0.0.1:6379> get name "Jack3"
② GET key 返回key
的value
。
如果key不存在,返回特殊值nil
。
如果key
的value
不是string,就返回错误,因为GET
只处理string类型的values
。
127.0.0.1:6379> set key1 value1
OK
127.0.0.1:6379> get key1 # key1存在,获取成功
"value1"
127.0.0.1:6379> get key2 # key2不存在,返回nil
(nil)
127.0.0.1:6379> hset key field value
(integer) 1
127.0.0.1:6379> get key # key对应的value不是string,报错
(error) WRONGTYPE Operation against a key holding the wrong kind of value
③ INCR key 对存储在指定key
的数值执行原子的加1操作。
127.0.0.1:6379> set count 10
OK
127.0.0.1:6379> incr count # 给count对应的值加1
(integer) 11 # 返回执行递增操作后key对应的value值
如果指定的key不存在,那么在执行incr操作之前,会先将它的值设定为0
。
127.0.0.1:6379> incr num # num不存在,则先执行set num 0,然后再incr
(integer) 1
如果指定的key中存储的值不是字符串类型或者存储的字符串类型不能表示为一个整数,那么执行这个命令时服务器会返回一个错误(eq:(error) ERR value is not an integer or out of range)。
127.0.0.1:6379> set count cat
OK
127.0.0.1:6379> get count
"cat"
127.0.0.1:6379> incr count # count对应的值不能表示整数,报错
(error) ERR value is not an integer or out of range
127.0.0.1:6379> hset hashKey f1 v1
(integer) 1
127.0.0.1:6379> hget hashKey f1
"v1"
127.0.0.1:6379> incr hashKey # hashKey的value值不是string,报错
(error) WRONGTYPE Operation against a key holding the wrong kind of value
这个操作仅限于64位的有符号整型数据。
注意: 由于redis并没有一个明确的类型来表示整型数据,所以这个操作是一个字符串操作。
执行这个操作的时候,key对应存储的字符串被解析为10进制的64位有符号整型数据。
事实上,Redis 内部采用整数形式(Integer representation)来存储对应的整数值,所以对该类字符串值实际上是用整数保存,也就不存在存储整数的字符串表示(String representation)所带来的额外消耗。
④ INCRBY key increment 将key对应的数字加increment。
127.0.0.1:6379> set count 10
OK
127.0.0.1:6379> get count
"10"
127.0.0.1:6379> incrby count 10 # 给count对应的值加10
(integer) 20
127.0.0.1:6379> get count
"20"
和incr一样,如果key不存在,操作之前,key就会被置为0。
127.0.0.1:6379> get num
(nil)
127.0.0.1:6379> incrby num 10
(integer) 10
127.0.0.1:6379> get num
"10"
和incr一样,如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。这个操作最多支持64位有符号的正型数字。
127.0.0.1:6379> set name Tom
OK
127.0.0.1:6379> incrby name 10
(error) ERR value is not an integer or out of range
⑤ DECR key 对key对应的数字做减1操作。
127.0.0.1:6379> get count
"20"
127.0.0.1:6379> decr count
(integer) 19
127.0.0.1:6379> get count
"19"
如果key不存在,那么在操作之前,这个key对应的值会被置为0。
127.0.0.1:6379> decr count2
(integer) -1
如果key有一个错误类型的value或者是一个不能表示成数字的字符串,就返回错误。这个操作最大支持在64位有符号的整型数字。
127.0.0.1:6379> set myKey 234293482390480948029348230948
OK
127.0.0.1:6379> decr myKey
(error) ERR value is not an integer or out of range
⑥ DECRBY key decrement 将key对应的数字减decrement。
127.0.0.1:6379> get count
"19"
127.0.0.1:6379> decrby count 9 # 对count对应的值减9
(integer) 10
127.0.0.1:6379> get count
"10"
如果key不存在,那么在操作之前,这个key对应的值会被置为0。
127.0.0.1:6379> get count3
(nil)
127.0.0.1:6379> decrby count3 10 # count3不存在,先将count3对应的值置为0,再减10
(integer) -10
127.0.0.1:6379> get count3
"-10"
如果key的value类型错误或者是个不能表示成数字的字符串,就返回错误。这个操作最多支持64位有符号的正型数字。
127.0.0.1:6379> set name zhang3
OK
127.0.0.1:6379> decrby name 10
(error) ERR value is not an integer or out of range
⑦ INCRBYFLOAT key increment 通过指定浮点数来增长key
对应的浮点数(存放于string中)的值。
127.0.0.1:6379> set float 10.5
OK
127.0.0.1:6379> incrbyfloat float 0.5
"11"
127.0.0.1:6379> get float
"11"
当键不存在时,先将其值设为0再操作
127.0.0.1:6379> get money
(nil)
127.0.0.1:6379> incrbyfloat money 0.5
"0.5"
当前的key或者相加后的值不能解析为一个双精度的浮点值.(超出精度范围了),报错
127.0.0.1:6379> set key1 2.0e18
OK
127.0.0.1:6379> get key1
"2.0e18"
127.0.0.1:6379> incrbyfloat key1 2.0e18
"4000000000000000000"
127.0.0.1:6379> incrbyfloat key1 2.0e10000 # 相加后超出精度范围,报错
(error) ERR value is not a valid float
⑧ append 追加
如果 key
已经存在,并且值为字符串,那么这个命令会把 value
追加到原来值(value)的结尾。
127.0.0.1:6379> set name Hello
OK
127.0.0.1:6379> get name
"Hello"
127.0.0.1:6379> append name " World" # 给name对应的值追加 “ World”
(integer) 11 # 返回追加后字符串的长度
127.0.0.1:6379> get name
"Hello World"
如果 key
不存在,那么它将首先创建一个空字符串的key
,再执行追加操作,这种情况 APPEND将类似于SET操作。
127.0.0.1:6379> get name2
(nil)
127.0.0.1:6379> append name2 li4 # 键name2不存在,此时append类似于set操作
(integer) 3
127.0.0.1:6379> get name2
"li4"
⑨ mget/mset 作用与 get/set 相似,不过 mget/mset 可以同时获得/设置多个键的键值
127.0.0.1:6379> mset name1 zhang3 name2 li4
OK
127.0.0.1:6379> mget name1 name2
1) "zhang3"
2) "li4"
⑩ DEL key [key …] 删除指定的key,可以指定多个key
127.0.0.1:6379> mget name1 name2 name3
1) "zhang3"
2) "li4"
3) "dd"
127.0.0.1:6379> del name1
(integer) 1
127.0.0.1:6379> del name2 name3
(integer) 2
127.0.0.1:6379> mget name1 name2 name3
1) (nil)
2) (nil)
3) (nil)
⑪ strlen key 返回key对应值的长度
127.0.0.1:6379> set name Bob
OK
127.0.0.1:6379> strlen name
(integer) 3
⑫ getset key value 设置并返回原值
127.0.0.1:6379> get name
"Bob"
127.0.0.1:6379> getset name Tom
"Bob"
127.0.0.1:6379> get name
"Tom"
⑬ setrange key offeset value 设置指定位置的字符,如果设置了多个字符,从指定位置往后顺移替换
127.0.0.1:6379> set name redis
OK
127.0.0.1:6379> get name
"redis"
127.0.0.1:6379> setrange name 2 1
(integer) 5
127.0.0.1:6379> get name
"re1is"
127.0.0.1:6379> setrange name 2 xx
(integer) 5
127.0.0.1:6379> get name
"rexxs"
127.0.0.1:6379> setrange name 2 xxx
(integer) 5
127.0.0.1:6379> get name
"rexxx"
127.0.0.1:6379> setrange name 2 xxxx
(integer) 6
127.0.0.1:6379> get name
"rexxxx"
⑭ getrange key start end 获取指定范围子串
警告:这个命令是被改成GETRANGE的,在小于2.0的Redis版本中叫SUBSTR。 返回key对应的字符串value的子串,这个子串是由start和end位移决定的(两者都在string内)。
可以用负的位移来表示从string尾部开始数的下标。所以-1就是最后一个字符,-2就是倒数第二个,以此类推。
这个函数处理超出范围的请求时,都把结果限制在string内。
127.0.0.1:6379> get name
"rexxxx"
127.0.0.1:6379> getrange name 0 1
"re"
127.0.0.1:6379> getrange name 0 2
"rex"
127.0.0.1:6379> getrange name 2 5
"xxxx"
127.0.0.1:6379> getrange name 2 6 # 6超出字符串
"xxxx"
127.0.0.1:6379> set name 0123456
OK
127.0.0.1:6379> get name
"0123456"
127.0.0.1:6379> getrange name 0 -1 # 下标位于0到字符串最后一个字符之间
"0123456"
127.0.0.1:6379> getrange name 0 -2 # 下标位于0到字符串倒数第二个字符之间
"012345"
127.0.0.1:6379> getrange name 0 -3
"01234"
127.0.0.1:6379> getrange name -1 7 # 字符串最后一个字符到第下标7
"6"
127.0.0.1:6379> getrange name -1 6 # 最后一个元素
"6"
127.0.0.1:6379> getrange name -1 5 # -1表示最后一个元素,相当于下标为6,[6,5]区间有问题,返回空串
""
3、应用场景:
-
缓存:由于redis具有支撑高并发特性,所以使用redis作为关系型数据库的缓存层,可以降低关系型数据库的压力,提高系统的读取效率
-
计数:incr就可以很方便的用来计数,并且可以快速的返回,比如点赞,视频播放量,文章阅读数等
-
接口防刷(限速):处于安全考虑,每次进行登录时让用户输入手机验证码,为了短信接口不被频繁访问, 可以限制用户每分钟获取验证码的频率。
-
session共享:由于负载均衡机制的存在,在很短时间间隔内的两个请求可能进入到不同的服务器,如果两个服务器都是单独管理session的,那第二次请求就得重新登录,如果把session统一存到一个公共的地方管理起来,那不管怎么均衡,session仅此一份,由于redis非常快,所以redis非常适合用来管理session。还有一种情况是一个系统中的众多的微服务,统一管理会话也可以用redis。
-
存储流程日志:将一个流程的每个步骤的日志都存在redis中,在执行流程时轮训查询日志展示。
二、Hash类型
1、特点:
-
Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。
-
Redis 中每个 hash 可以存储 2^32 - 1 键值对(40多亿)。
2、常用命令:
① HSET key field value 设置 key 指定的哈希集中指定字段的值。
127.0.0.1:6379> hset person name Tom age 20 salary 3000.0 # 可以给键person设置多个键值对
(integer) 3 # 新加field不存在则返回1,多个累加,field存在,返回0
127.0.0.1:6379> hget person name
"Tom"
127.0.0.1:6379> hget person age
"20"
127.0.0.1:6379> hset person name Bob # field name已存在,返回0
(integer) 0
127.0.0.1:6379> hset person address bj # field address 不存在,返回1
(integer) 1
② HGET key field 返回 key 指定的哈希集中该字段所关联的值
127.0.0.1:6379> hget person age
"20"
127.0.0.1:6379> hget person xx
(nil)
127.0.0.1:6379> hget xx
(error) ERR wrong number of arguments for 'hget' command
③ HMSET key field value [field value …] 给键key设置多个键值对
127.0.0.1:6379> hmset user username admin password 123456
OK
127.0.0.1:6379> hget user username
"admin"
④ HMGET key field [field …] 获取多个键值对的值
127.0.0.1:6379> hmget user username password
1) "admin"
2) "123456"
⑤ HEXISTS key field 判断指定key下的field是否存在
127.0.0.1:6379> hexists person name # 存在,返回1
(integer) 1
127.0.0.1:6379> hexists person name1 # 不存在,返回0
(integer) 0
⑥ HDEL key field [field …] 删除哈希表中指定键值对,可以指定多个
127.0.0.1:6379> hmget person name age salary
1) "Bob"
2) "20"
3) "3000.0"
127.0.0.1:6379> hdel person name age
(integer) 2 # 返回删除的field数量
127.0.0.1:6379> hmget person name age salary
1) (nil)
2) (nil)
3) "3000.0"
⑦ HGETALL key 获取指定key下的所有键值对
127.0.0.1:6379> hgetall person
1) "salary"
2) "3000.0"
3) "address"
4) "bj"
127.0.0.1:6379> hgetall user
1) "username"
2) "admin"
3) "password"
4) "123456"
⑧ HVALS key 返回 key 指定的哈希集中所有字段的值。
127.0.0.1:6379> hvals person # 只返回值
1) "3000.0"
2) "bj"
⑨ HKEYS key 返回 key 指定的哈希集中所有字段的名字。
127.0.0.1:6379> hkeys person # 只返回field属性名称
1) "salary"
2) "address"
⑩ HLEN key 返回指定key的哈希集合的元素个数(键值对个数)
127.0.0.1:6379> hlen person
(integer) 2
127.0.0.1:6379> hlen user
(integer) 2
3、应用场景:
- 管理对象信息:哈希结构相对于字符串序列化缓存信息更加直观,并且在更新操作上更加便捷(只需修改指定字段 hset key field)。
三、List类型
1、特点:
-
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
-
一个列表最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
2、常用命令:
① LPUSH key value [value …] 将所有指定的值插入到存于 key 的列表的头部
元素是从最左端的到最右端的、一个接一个被插入到 list 的头部。 所以对于这个命令例子 LPUSH mylist a b c
,返回的列表是 c 为第一个元素, b 为第二个元素, a 为第三个元素。
127.0.0.1:6379> lpush list redis mysql mongdb
(integer) 3
127.0.0.1:6379> lpush person # person不是list类型
(error) ERR wrong number of arguments for 'lpush' command
127.0.0.1:6379> lrange list 0 2
1) "mongdb"
2) "mysql"
3) "redis"
② LRANGE key start end 返回存储在 key 的列表里指定范围内的元素。
start 和 end 偏移量都是基于0的下标,即list的第一个元素下标是0(list的表头),第二个元素下标是1,以此类推。
127.0.0.1:6379> lrange list 0 2
1) "mongdb"
2) "mysql"
3) "redis"
偏移量也可以是负数,表示偏移量是从list尾部开始计数。 例如, -1 表示列表的最后一个元素,-2 是倒数第二个,以此类推。
127.0.0.1:6379> lrange list -2 -1
1) "mysql"
2) "redis"
127.0.0.1:6379> lrange list -3 -1
1) "mongdb"
2) "mysql"
3) "redis"
当下标超过list范围的时候不会产生error。
如果start比list的尾部下标大的时候,会返回一个空列表。
如果end比list的实际尾部大的时候,Redis会当它是最后一个元素的下标。
127.0.0.1:6379> lrange list -3 -1
1) "mongdb"
2) "mysql"
3) "redis"
127.0.0.1:6379> lrange list 3 2
(empty array)
127.0.0.1:6379> lrange list 0 3
1) "mongdb"
2) "mysql"
3) "redis"
③ LPOP key 移除并且返回 key 对应的 list 的第一个元素。
127.0.0.1:6379> lrange list 0 3
1) "mongdb"
2) "mysql"
3) "redis"
127.0.0.1:6379> lpop list
"mongdb"
127.0.0.1:6379> lpop list
"mysql"
127.0.0.1:6379> lrange list 0 3
1) "redis"
127.0.0.1:6379> lpop xxx # key不存在时,返回nil
(nil)
④ RPUSH key value [value …] 向存于 key 的列表的尾部插入所有指定的值。
127.0.0.1:6379> rpush list2 a b c
(integer) 3
127.0.0.1:6379> lrange list2 0 2
1) "a"
2) "b"
3) "c"
⑤ RPOP key 移除并返回存于 key 的 list 的最后一个元素。
127.0.0.1:6379> lrange list2 0 2
1) "a"
2) "b"
3) "c"
127.0.0.1:6379> rpop list2
"c"
127.0.0.1:6379> rpop list2
"b"
127.0.0.1:6379> lrange list2 0 2
1) "a"
⑥ LLEN key 返回存储在 key 里的list的长度
如果 key 不存在,那么就被看作是空list,并且返回长度为 0。 当存储在 key 里的值不是一个list的话,会返回error。
127.0.0.1:6379> llen list2
(integer) 1
127.0.0.1:6379> lpush list2 b
(integer) 2
127.0.0.1:6379> llen list2
(integer) 2
⑦ LINDEX key index 返回列表中指定索引的元素
127.0.0.1:6379> lrange list2 0 2
1) "b"
2) "a"
127.0.0.1:6379> lindex list2 0
"b"
127.0.0.1:6379> lindex list2 1
"a"
负数索引用于指定从列表尾部开始索引的元素。在这种方法下,-1 表示最后一个元素,-2 表示倒数第二个元素,并以此往前推。
127.0.0.1:6379> lindex list2 -1
"a"
127.0.0.1:6379> lindex list2 -2
"b"
⑧ LSET key index value 设置 index 位置的list元素的值为 value。
127.0.0.1:6379> lset list3 0 a1 # key不存在时,报错
(error) ERR no such key
127.0.0.1:6379> lrange list2 0 1
1) "b"
2) "a"
127.0.0.1:6379> lset list2 2 c # 超出列表长度时,报错
(error) ERR index out of range
127.0.0.1:6379> lset list2 0 c # 只能修改设置列表范围内某一下标的元素
OK
127.0.0.1:6379> lrange list2 0 1
1) "c"
2) "a"
⑨ BLPOP key [key …] timeout 阻塞式弹出指定列表左边第一个元素,可以指定多个列表
当list中没有数据时,blpop会阻塞等待,直到list中加入数据或者超过等待时间。下图中等待10秒阻塞结束
下图中,blpop在等待期间,另一个客户端向list中添加数据了,blpop弹出list列表中左边的第一个元素
多个列表时,从左往右检索,直到找到不为空的列表的左边第一个元素
127.0.0.1:6379> lrange list 0 2 # list列表为空
(empty array)
127.0.0.1:6379> lrange list1 0 2 # list1列表3个元素
1) "c1"
2) "b1"
3) "a1"
127.0.0.1:6379> lrange list2 0 2 # list2列表3个元素
1) "c2"
2) "b2"
3) "a2"
127.0.0.1:6379> blpop list list1 list2 10 # 从左往右找,弹出list1的左边第一个元素
1) "list1"
2) "c1"
⑩ BRPOP key [key …] timeout 阻塞式弹出指定列表右边的第一个元素,可以指定多个列表
127.0.0.1:6379> brpop list list1 list2 10 # 从左往右找,弹出list1的尾部元素
1) "list1"
2) "a1"
3、应用场景:
- 消息队列:redis的lpush+brpop命令组合即可实现阻塞队列,生产者客户端是用lupsh从列表左侧插入元素, 多个消费者客户端使用brpop命令阻塞时的“抢”列表尾部的元素,多个客户端保证了消费的负载均衡 和高可用性
四、Set类型
1、特点:
-
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
-
Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
-
集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)。
2、常用命令:
① SADD key member [member …] 添加一个或多个指定的member元素到集合的 key中
127.0.0.1:6379> sadd person Tom
(integer) 1 # 返回新成功添加到集合里元素的数量,不包括已经存在于集合中的元素。
127.0.0.1:6379> sadd person Tom # member Tom 已经存在,返回0
(integer) 0
127.0.0.1:6379> sadd person Bob
(integer) 1
127.0.0.1:6379> sadd person Jack Lucy # 添加多个member到person集合中
(integer) 2
127.0.0.1:6379> smembers person # 返回person集合中所有成员,结果无序
1) "Lucy"
2) "Jack"
3) "Bob"
4) "Tom"
② SMEMBERS key 返回key集合所有的元素,结果无序
127.0.0.1:6379> smembers person # 返回person集合中所有成员,结果无序
1) "Lucy"
2) "Jack"
3) "Bob"
4) "Tom"
③ SCARD key 返回集合key中的元素个数
127.0.0.1:6379> scard person
(integer) 4
④ SISMEMBER key member 判断成员 member 是否是存储在集合 key中的成员
127.0.0.1:6379> sismember person zhang3 # 不存在返回0
(integer) 0
127.0.0.1:6379> sismember person Tom # 存在返回1
(integer) 1
⑤ SREM key member [member …] 删除集合key中的指定成员,可以指定多个成员
127.0.0.1:6379> srem person Tom # 返回删除成功的成员个数
(integer) 1
127.0.0.1:6379> smembers person
1) "Lucy"
2) "Jack"
3) "Bob"
127.0.0.1:6379> srem person Bob Jack
(integer) 2
127.0.0.1:6379> smembers person
1) "Lucy"
127.0.0.1:6379> srem person xx
(integer) 0
⑥ SRANDMEMBER key [count] 随机返回指定数量的成员
127.0.0.1:6379> sadd tag tag1 tag2 tag3
(integer) 3
127.0.0.1:6379> SRANDMEMBER tag
"tag2"
127.0.0.1:6379> SRANDMEMBER tag 1
1) "tag2"
127.0.0.1:6379> SRANDMEMBER tag 2
1) "tag2"
2) "tag3"
127.0.0.1:6379> SRANDMEMBER tag 3
1) "tag2"
2) "tag3"
3) "tag1"
⑦ SPOP key [count] 从集合中移除并返回一个或多个随机元素。
127.0.0.1:6379> sadd tag tag1 tag2 tag3 tag4
(integer) 4
127.0.0.1:6379> smembers tag
1) "tag3"
2) "tag2"
3) "tag1"
4) "tag4"
127.0.0.1:6379> spop tag
"tag1"
127.0.0.1:6379> spop tag 2
1) "tag3"
2) "tag4"
127.0.0.1:6379> spop tag
"tag2"
127.0.0.1:6379> spop tag
(nil)
⑧ SINTER key [key …] 求多个集合的交集
127.0.0.1:6379> sadd user:1:tag tag1 tag2 tag3 tag4
(integer) 4
127.0.0.1:6379> sadd user:2:tag tag3 tag2 tag5
(integer) 3
127.0.0.1:6379> sinter user:1:tag user:2:tag
1) "tag2"
2) "tag3"
⑨ SUNION key [key …] 返回给定的多个集合的并集中的所有成员
127.0.0.1:6379> sunion user:1:tag user:2:tag
1) "tag4"
2) "tag5"
3) "tag1"
4) "tag3"
5) "tag2"
⑩ SDIFF key [key …] 返回一个集合与给定集合的差集的元素
127.0.0.1:6379> sdiff user:1:tag user:2:tag
1) "tag1"
2) "tag4"
127.0.0.1:6379> sdiff user:2:tag user:1:tag
1) "tag5"
⑪ SINTERSTORE/SUNIONSTORE/SDIFFSTORE destination key [key …] 将交集、并集、差集保存到指定集合中
127.0.0.1:6379> sinterstore inter user:1:tag user:2:tag
(integer) 2
127.0.0.1:6379> smembers inter
1) "tag3"
2) "tag2"
127.0.0.1:6379> sunionstore union user:1:tag user:2:tag
(integer) 5
127.0.0.1:6379> smembers union
1) "tag4"
2) "tag5"
3) "tag1"
4) "tag3"
5) "tag2"
127.0.0.1:6379> sdiffstore user1_user2:diff user:1:tag user:2:tag
(integer) 2
127.0.0.1:6379> smembers user1_user2:diff
1) "tag1"
2) "tag4"
3、应用场景:
- 标签:sadd可以给用户添加标签
- 抽奖:spop/srandmember 随机抽奖
- 社交需求:sadd + sinter,可以找出有相同爱好或者相同地理位置的人
五、SortedSet类型
1、特点:
-
Redis 有序集合SortedSet和集合Set一样也是 string 类型元素的集合,且不允许重复的成员,不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。
-
有序集合的成员是唯一的,但分数(score)却可以重复。
-
集合是通过哈希表实现的,所以添加,删除,查找效率都很高。 集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)。
2、常用命令:
① ZADD key [NX|XX] [CH] [INCR] score member [score member …] 将所有指定成员添加到键为key
的有序集合(sorted set)里面
127.0.0.1:6379> zadd stu 10 Tom 20 Bob 30 Jack # 添加时可以指定多个分数/成员(score/member)对
(integer) 3
127.0.0.1:6379> zrange stu 0 -1
1) "Tom"
2) "Bob"
3) "Jack"
127.0.0.1:6379> zrange stu 0 -1 withscores
1) "Tom"
2) "10"
3) "Bob"
4) "20"
5) "Jack"
6) "30"
如果指定添加的成员已经是有序集合里面的成员,则会更新改成员的分数(scrore)并更新到正确的排序位置。
127.0.0.1:6379> zadd stu 10 Tom 20 Bob 30 Jack
(integer) 3
127.0.0.1:6379> zadd stu 40 Tom
(integer) 0
127.0.0.1:6379> zrange stu 0 -1
1) "Bob"
2) "Jack"
3) "Tom"
如果两个成员的分数相同,将按照字典顺序进行排序
127.0.0.1:6379> zadd stu 100 zhang3 100 li4
(integer) 2
127.0.0.1:6379> zrange stu 0 -1
1) "Bob"
2) "Jack"
3) "Tom"
4) "li4"
5) "zhang3"
选项:
-
XX: 仅仅更新存在的成员,不添加新成员。
127.0.0.1:6379> zadd stu 10 Tom 20 Bob 100 zhang3 100 li4 120 Jack # 添加5个元素 (integer) 5 127.0.0.1:6379> zrange stu 0 -1 withscores # 查看一下所有成员及其分数 1) "Tom" 2) "10" 3) "Bob" 4) "20" 5) "li4" 6) "100" 7) "zhang3" 8) "100" 9) "Jack" 10) "120" 127.0.0.1:6379> zadd stu XX 500 li4 520 Jack # 修改li4的分数为500,修改Jack的分数为520 (integer) 0 127.0.0.1:6379> zrange stu 0 -1 withscores 1) "Tom" 2) "10" 3) "Bob" 4) "20" 5) "zhang3" 6) "100" 7) "li4" 8) "500" 9) "Jack" 10) "520" 127.0.0.1:6379> zadd stu XX 15 Bluce # 修改Bluce的分数,Bluce不存在,所以既不会修改,也不会添加 (integer) 0 127.0.0.1:6379> zrange stu 0 -1 withscores 1) "Tom" 2) "10" 3) "Bob" 4) "20" 5) "zhang3" 6) "100" 7) "li4" 8) "500" 9) "Jack" 10) "520"
-
NX: 不更新存在的成员。只添加新成员。
127.0.0.1:6379> zadd stu NX 35 li4 (integer) 0 127.0.0.1:6379> zrange stu 0 -1 withscores 1) "Tom" 2) "10" 3) "Bob" 4) "20" 5) "zhang3" 6) "100" 7) "li4" 8) "500" 9) "Jack" 10) "520" 127.0.0.1:6379> zadd stu NX 15 Bluce (integer) 1 127.0.0.1:6379> zrange stu 0 -1 withscores 1) "Tom" 2) "10" 3) "Bluce" 4) "15" 5) "Bob" 6) "20" 7) "zhang3" 8) "100" 9) "li4" 10) "500" 11) "Jack" 12) "520"
-
INCR: 对成员的分数进行递增操作。
127.0.0.1:6379> zadd stu 10 Tom 20 Bob (integer) 2 127.0.0.1:6379> zrange stu 0 -1 withscores 1) "Tom" 2) "10" 3) "Bob" 4) "20" 127.0.0.1:6379> zadd stu incr 10 Tom # 给Tom的分数加10 "20" 127.0.0.1:6379> zrange stu 0 -1 withscores 1) "Bob" 2) "20" 3) "Tom" 4) "20" # 等同于 ZINCRBY key increment member
② ZRANGE key start stop [WITHSCORES] 返回存储在有序集合key
中的指定范围的元素。
返回的元素可以认为是按得分从最低到最高排列。 如果得分相同,将按字典排序。
参数start
和stop
都是基于零的索引,即0
是第一个元素,1
是第二个元素,以此类推。 它们也可以是负数,表示从有序集合的末尾的偏移量,其中-1
是有序集合的最后一个元素,-2
是倒数第二个元素,等等。
start
和stop
都是全包含的区间,因此例如ZRANGE myzset 0 1
将会返回有序集合的第一个和第二个元素。
可以传递WITHSCORES
选项,以便将元素的分数与元素一起返回
127.0.0.1:6379> zrange stu 0 -1 withscores
1) "Bob"
2) "20"
3) "Tom"
4) "20"
127.0.0.1:6379> zrange stu 0 -1
1) "Bob"
2) "Tom"
③ ZCARD key 返回有序集合的元素个数
127.0.0.1:6379> zcard stu
(integer) 2
④ ZSCORE key member 返回指定成员的分数
127.0.0.1:6379> zscore stu Tom # 成员存在,返回分数
"20"
127.0.0.1:6379> zscore stu Jack # 成员不存在,返回nil
(nil)
⑤ 计算成员的排名,zrank key member 从低到高,zrevrank key member 从高到低
127.0.0.1:6379> zrank stu Tom
(integer) 1
127.0.0.1:6379> zrevrank stu Tom
(integer) 0
⑥ zrem key member 删除成员
127.0.0.1:6379> zrem stu Tom Bob
(integer) 2
127.0.0.1:6379> zrange stu 0 -1
(empty array)
3、应用场景:
- 排行榜:可以是点赞数排行榜,评论数排行榜,热卖排行榜,分数排行榜等等
六、总结
redis中常用的数据类型有5种,String,Hash,List,Set, SortedSet
String 类型最常用,就是存字符串的,但它是二进制安全的,所以可以存二进制数据如图片,最多能存512MB,可以用来做关系型数据库的缓存,session共享,接口防刷;
Hash类型用的相对少一些,主要用来存对象信息;
List类型主要可以用来模拟栈和队列;
Set类型是String类型的集合,成员不重复,主要用来存各种标签,抽奖,社交软件推荐共同兴趣的人;
SortedSet跟Set类似,不同的是可以根据分数排序,所以主要用来做各种排行榜展示给用户。
七、参考
https://blog.csdn.net/zh15732621679/article/details/80614091