Redis学习笔记:
https://blog.csdn.net/2301_80220607/category_13051025.html?spm=1001.2014.3001.5482
前言:
上一篇已经讲解了Redis中String字符串类型的许多指令的使用,Redis中这些数据类型的相关指令都是十分相似的,今天我们将除了String以外的剩下的几个Redis常用数据类型及其相关知识点讲解一下
目录
[1. 命令](#1. 命令)
[1.1 HSET](#1.1 HSET)
[1.2 HGET](#1.2 HGET)
[1.3 HEXISTS](#1.3 HEXISTS)
[1.4 HDEL](#1.4 HDEL)
[1.5 HKEYS](#1.5 HKEYS)
[1.6 HVALS](#1.6 HVALS)
[1.7 HGETALL](#1.7 HGETALL)
[1.8 HMGET](#1.8 HMGET)
[1.9 HLEN](#1.9 HLEN)
[1.10 HSETNX](#1.10 HSETNX)
[1.11 HINCRBY](#1.11 HINCRBY)
[1.12 HINCRBYFLOAT](#1.12 HINCRBYFLOAT)
[2. 命令小结](#2. 命令小结)
[1. 命令](#1. 命令)
[1.1 LPUSH](#1.1 LPUSH)
[1.2 LPUSHX](#1.2 LPUSHX)
[1.3 RPUSH](#1.3 RPUSH)
[1.4 RPUSHX](#1.4 RPUSHX)
[1.5 LRANGE](#1.5 LRANGE)
[1.6 LPOP](#1.6 LPOP)
[1.7 RPOP](#1.7 RPOP)
[1.8 LINDEX](#1.8 LINDEX)
[1.9 LINSERT](#1.9 LINSERT)
[1.10 LLEN](#1.10 LLEN)
[2. 阻塞版本命令](#2. 阻塞版本命令)
[2.1 BLPOP](#2.1 BLPOP)
[2.2 BRPOP](#2.2 BRPOP)
[3. 内部编码](#3. 内部编码)
[1. 普通命令](#1. 普通命令)
[1.1 SADD](#1.1 SADD)
[1.2 SMEMBERS](#1.2 SMEMBERS)
[1.3 SISMEMBER](#1.3 SISMEMBER)
[1.4 SCARD](#1.4 SCARD)
[1.5 SPOP](#1.5 SPOP)
[1.6 SMOVE](#1.6 SMOVE)
[1.7 SREM](#1.7 SREM)
[2. 集合间操作](#2. 集合间操作)
[2.1 SINTER](#2.1 SINTER)
[2.2 SINTERSTORE](#2.2 SINTERSTORE)
[2.3 SUNION](#2.3 SUNION)
[2.4 SUNIONSTORE](#2.4 SUNIONSTORE)
[2.5 SDIFF](#2.5 SDIFF)
[2.6 SDIFFSTORE](#2.6 SDIFFSTORE)
[1. 普通命令](#1. 普通命令)
[1.1 ZADD](#1.1 ZADD)
[1.2 ZCARD](#1.2 ZCARD)
[1.3 ZCOUNT](#1.3 ZCOUNT)
[1.4 ZRANGE](#1.4 ZRANGE)
[1.5 ZREVRANGE](#1.5 ZREVRANGE)
[1.6 ZRANGEBYSCORE](#1.6 ZRANGEBYSCORE)
[1.7 ZPOPMAX](#1.7 ZPOPMAX)
[1.8 ZPOPMIN](#1.8 ZPOPMIN)
[1.9 BZPOPMIN](#1.9 BZPOPMIN)
[1.10 ZRANK](#1.10 ZRANK)
[1.11 ZSCORE](#1.11 ZSCORE)
[1.12 ZREM](#1.12 ZREM)
[1.13 ZREMRANGEBYRANK](#1.13 ZREMRANGEBYRANK)
[1.14 ZREMRANGEBYSCORE](#1.14 ZREMRANGEBYSCORE)
[1.15 ZINCRBY](#1.15 ZINCRBY)
[2. 集合间操作](#2. 集合间操作)
[2.1 ZINTERSTORE](#2.1 ZINTERSTORE)
[2.2 ZUNIONSTORE](#2.2 ZUNIONSTORE)
[3. 内部编码](#3. 内部编码)
一、Hash(哈希)
几乎所有的主流编程语言都支持哈希结构,在不同的编程语言中它可能有不同的叫法:哈希、字典序、映射......我们的Redis也支持哈希这种数据类型,一个有意思的点是:Redis本身的整体数据结构就是以key-value的哈希的结构存在的,这就相当于是哈希中嵌套哈希:key-(key-value),非常有意思,为了避免混淆,我们可以把第二个key改一下:key-(field-value)
1. 命令
1.1 HSET
设置哈希中指定的字段(field)的值(value)
bash
HSET key field value [field value ...]
- 时间复杂度:插⼊⼀组 field 为 O(1), 插⼊ N 组 field 为 O(N)
- 返回值:添加的字段的个数。
示例:
bash
127.0.0.1:6379> hset myhash field "hello"
(integer) 1
127.0.0.1:6379> hget myhash field
"hello"
1.2 HGET
获取hash中指定字段的值
bash
HGET key field
- 时间复杂度:O(1)
- 返回值:字段对应的值或者 nil。
示例:
bash
127.0.0.1:6379> hset myhash field "hello"
(integer) 1
127.0.0.1:6379> hget myhash field
"hello"
127.0.0.1:6379> hget myhash field2
(nil)
1.3 HEXISTS
判断hash中是否有指定的字段
bash
HEXISTS key field
- 时间复杂度:O(1)
- 返回值:1 表⽰存在,0 表⽰不存在。
示例:
bash
127.0.0.1:6379> hset myhash field1 hello
(integer) 1
127.0.0.1:6379> hexists myhash field1
(integer) 1
127.0.0.1:6379> hexists myhash field2
(integer) 0
1.4 HDEL
删除hash中指定的字段
bash
HDEL key field [field ...]
- 时间复杂度:删除⼀个元素为 O(1). 删除 N 个元素为 O(N).
- 返回值:本次操作删除的字段个数。
示例:
bash
127.0.0.1:6379> hdel myhash field
(integer) 1
127.0.0.1:6379> hdel myhash field1 field2
(integer) 1
1.5 HKEYS
获取hash中的所有字段
bash
HKEYS key
- 时间复杂度:O(N), N 为 field 的个数.
- 返回值:字段列表。
示例:
bash
127.0.0.1:6379> hset myhash field1 hello
(integer) 1
127.0.0.1:6379> hset myhash field2 world
(integer) 1
127.0.0.1:6379> hkeys myhash
1) "field1"
2) "field2"
1.6 HVALS
获取哈希中的所有值
bash
HVALS key
- 时间复杂度:O(N), N 为 field 的个数.
- 返回值:所有的值。
示例:
bash
127.0.0.1:6379> hset myhash field1 hello
(integer) 1
127.0.0.1:6379> hset myhash field2 world
(integer) 1
127.0.0.1:6379> hvals myhash
1) "hello"
2) "world"
1.7 HGETALL
获取hash中所有字段以及对应的值
bash
HGETALL key
- 时间复杂度:O(N), N 为 field 的个数.
- 返回值:字段和对应的值。
示例:
bash
127.0.0.1:6379> hset myhash field1 hello
(integer) 1
127.0.0.1:6379> hset myhash field2 world
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"
3) "field2"
4) "world"
1.8 HMGET
一次性获取hash中多个字段的值
bash
HMGET key field [field ...]
- 时间复杂度:只查询⼀个元素为 O(1), 查询多个元素为 O(N), N 为查询元素个数.
- 返回值:字段对应的值或者 nil。
示例:
bash
127.0.0.1:6379> hset myhash field1 hello
(integer) 1
127.0.0.1:6379> hset myhash field2 world
(integer) 1
127.0.0.1:6379> hmget myhash field1 field2 nofield
1) "hello"
2) "world"
3) (nil)
**注意:**在使用上面的HGETALL时,如果hash中元素过多,可能会造成阻塞Redis的情况,如非必要尽量不要选择查看所有的元素,而是通过HMGET来获取指定的元素,如果一定要获取全部的元素时,可以采用我们下面将要讲的HSCAN的分批次进行获取
1.9 HLEN
获取hash中所有字段的个数
bash
HLEN key
- 时间复杂度:O(1)
- 返回值:字段个数。
示例:
bash
127.0.0.1:6379> hset myhash field1 hello
(integer) 1
127.0.0.1:6379> hset myhash field2 world
(integer) 1
127.0.0.1:6379> hlen myhash
(integer) 2
1.10 HSETNX
在字段不存在的情况下,设置字段以及对应的值
bash
HSETNX key field value
- 时间复杂度:O(1)
- 返回值:1 表⽰设置成功,0 表⽰失败。
示例:
bash
127.0.0.1:6379> hsetnx myhash field1 hello
(integer) 1
127.0.0.1:6379> hsetnx myhash field1 world
(integer) 0
127.0.0.1:6379> hget myhash field1
"hello"
1.11 HINCRBY
将hash中指定字段的数值添加上指定的值
bash
HINCRBY key field increment
- 时间复杂度:O(1)
- 返回值:该字段变化之后的值。
示例:
bash
127.0.0.1:6379> hset myhash field 1
(integer) 1
127.0.0.1:6379> hincrby myhash field 10
(integer) 11
127.0.0.1:6379> hincrby myhash field -10
1.12 HINCRBYFLOAT
HINCRBY的FLOAT版本
bash
HINCRBYFLOAT key field increment
- 时间复杂度:O(1)
- 返回值:该字段变化之后的值
2. 命令小结
命令 | 执⾏效果 | 时间复杂度 |
---|---|---|
hset key field value | 设置值 | O(1) |
hget key field | 获取值 | O(1) |
hdel key field [field ...] | 删除 field | O(k), k 是 field 个数 |
hlen key | 计算 field 个数 | O(1) |
hgetall key | 获取所有的 field-value | O(k), k 是 field 个数 |
hmget field [field ...] | 批量获取 field-value | O(k), k 是 field 个数 |
hmset field value [field value ... | 批量设置 field-value | O(k), k 是 field 个数 |
hexists key field | 判断 field 是否存在 | O(1) |
hkeys key | 获取所有的 field | O(k), k 是 field 个数 |
hvals key | 获取所有的 value | O(k), k 是 field 个数 |
hsetnx key field value | 设置值,但必须在 field 不存在时才能设置成功 | O(1) |
hincrby key field n | 对应 field-value +n | O(1) |
hincrbyfloat key field n | 对应 field-value +n | O(1) |
hstrlen key field | 计算 value 的字符串⻓度 | O(1) |
3.内部编码
- ziplist(压缩列表):当哈希类型元素个数⼩于 hash-max-ziplist-entries 配置(默认 512 个)、同时所有值都⼩于 hash-max-ziplist-value 配置(默认 64 字节)时,Redis 会使⽤ ziplist 作为哈希的内部实现,ziplist 使⽤更加紧凑的结构实现多个元素的连续存储,所以在节省内存⽅⾯⽐hashtable 更加优秀。
- hashtable(哈希表):当哈希类型⽆法满⾜ ziplist 的条件时,Redis 会使⽤ hashtable 作为哈希的内部实现,因为此时 ziplist 的读写效率会下降,⽽ hashtable 的读写时间复杂度为 O(1)。
下面来看一下哈希内部的编码,以及响应类型的变换:
当field个数比较少,且内部的值不是很大时,内部编码为ziplist:
bash
127.0.0.1:6379> hmset myhash f1 v1 f2 v2
OK
127.0.0.1:6379> object encoding myhash
"ziplist"
当有value大于64字节时,内部编码会转变为hashtable:
bash
127.0.0.1:6379> hmset myhash f3 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
OK
127.0.0.1:6379> object encoding myhash
"hashtable"
当field个数超过512个时,内部编码也会转化为hashtable:
bash
127.0.0.1:6379> hmset hashkey f1 v1 h2 v2 f3 v3 ... 省略 ... f513 v513
OK
127.0.0.1:6379> object encoding hashkey
"hashtable"
二、List(列表)
列表类型是用来存储多个字符串,如图,a、b、c、d、e五个元素从左到右组成一个有序的列表,列表中每个字符串被称为一个元素,,一个列表最多有2^32-1个元素。在Redis中,列表可以进行两端插入取出,获取指定范围内的元素,获取指定下标的元素等操作,总之列表是Redis中一种十分好用的数据机构,在很多场景下都能够得到使用

1. 命令
1.1 LPUSH
将一个或多个元素头插到列表中
bash
LPUSH key element [element ...]
- 时间复杂度:只插⼊⼀个元素为 O(1), 插⼊多个元素为 O(N), N 为插⼊元素个数.
- 返回值:插⼊后 list 的⻓度。
示例:
bash
127.0.0.1:6379> lpush mylist hello
(integer) 1
127.0.0.1:6379> lpush mylist world
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "world"
2) "hello"
1.2 LPUSHX
当key存在时,将一个或多个元素头插到列表中
bash
LPUSHX key element [element ...]
- 时间复杂度:只插⼊⼀个元素为 O(1), 插⼊多个元素为 O(N), N 为插⼊元素个数.
- 返回值:插⼊后 list 的⻓度。
示例:
bash
127.0.0.1:6379> lpush mylist hello
(integer) 1
127.0.0.1:6379> lpushx mylist world
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "world"
2) "hello"
127.0.0.1:6379> lpushx mylist2 hello
(integer) 0
127.0.0.1:6379> lrange mylist2 0 -1
1.3 RPUSH
将一个或多个元素尾插到列表中
bash
RPUSH key element [element ...]
- 时间复杂度:只插⼊⼀个元素为 O(1), 插⼊多个元素为 O(N), N 为插⼊元素个数.
- 返回值:插⼊后 list 的⻓度。
示例:
bash
127.0.0.1:6379> rpush mylist hello
(integer) 1
127.0.0.1:6379> rpush mylist world
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
1.4 RPUSHX
当key存在的时候,将一个或多个元素尾插到列表中
bash
RPUSHX key element [element ...]
- 时间复杂度:只插⼊⼀个元素为 O(1), 插⼊多个元素为 O(N), N 为插⼊元素个数.
- 返回值:插⼊后 list 的⻓度。
示例:
bash
127.0.0.1:6379> rpush mylist hello
(integer) 1
127.0.0.1:6379> rpushx mylist world
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
127.0.0.1:6379> rpushx mylist2 hello
(integer) 0
127.0.0.1:6379> lrange mylist2 0 -1
(empty list or set)
1.5 LRANGE
获取从start到end之间的所有元素,左闭右闭
bash
LRANGE key start stop
- 时间复杂度:O(N)
- 返回值:指定区间的元素。
示例:
bash
127.0.0.1:6379> rpush mylist hello
(integer) 1
127.0.0.1:6379> rpush mylist world
(integer) 2
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
1.6 LPOP
头删
bash
LPOP key
- 时间复杂度:O(1)
- 返回值:取出的元素或者 nil。
示例:
bash
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
127.0.0.1:6379> lpop mylist
"hello"
127.0.0.1:6379> lrange mylist 0 -1
1) "world"
1.7 RPOP
尾删
bash
RPOP key
- 时间复杂度:O(1)
- 返回值:取出的元素或者 nil。
示例:
bash
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
127.0.0.1:6379> rpop mylist
"world"
127.0.0.1:6379> lrange mylist 0 -1
1.8 LINDEX
获取从左数第index位置的元素
bash
LINDEX key index
- 时间复杂度:O(N)
- 返回值:取出的元素或者 nil。
示例:
bash
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
127.0.0.1:6379> lindex mylist 0
"hello"
127.0.0.1:6379> lindex mylist -1
"world"
127.0.0.1:6379> lindex mylist 2
1.9 LINSERT
在特定位置插入元素
bash
LINSERT key <BEFORE | AFTER> pivot element
- 时间复杂度:O(N)
- 返回值:插⼊后的 list ⻓度。
示例:
bash
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "world"
127.0.0.1:6379> linsert mylist before world one
(integer) 3
127.0.0.1:6379> linsert mylist after world two
(integer) 4
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "one"
3) "world"
4) "two"
1.10 LLEN
获取列表长度
bash
LLEN key
- 时间复杂度:O(1)
- 返回值:list 的⻓度。
示例:
bash
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "one"
3) "world"
4) "two"
127.0.0.1:6379> llen mylist
(integer) 4
2. 阻塞版本命令
blpop和brpop是lpop和rpop的阻塞版本。两者用法很相似,但也有些不同之处:
- 在列表中有元素的情况下,阻塞和⾮阻塞表现是⼀致的。但如果列表中没有元素,⾮阻塞版本会理 解返回 nil,但阻塞版本会根据 timeout,阻塞⼀段时间,期间 Redis 可以执⾏其他命令,但要求执⾏该命令的客⼾端会表现为阻塞状态
- 命令中如果设置了多个键,那么会从左向右进⾏遍历键,⼀旦有⼀个键对应的列表中可以弹出元素,命令⽴即返回
- 如果多个客⼾端同时多⼀个键执⾏ pop,则最先执⾏命令的客⼾端会得到弹出的元素
2.1 BLPOP
LPOP的阻塞版本
bash
BLPOP key [key ...] timeout
- 时间复杂度:O(1)
- 返回值:取出的元素或者 nil。
我们看这个命令的语法,它与LPOP主要有两处不同,一是它能同时监视多个key,二是它需要设置一个超时时间,当我们设置一个超时时间后,比如5s,那么在5s内,我们所监视的key里面哪个最先有值我们就头删掉,当头删成功或者超时时,命令就会被结束掉
我们开启两个redis客户端来测试一下,其中一个redis客户端监视多个里面为空的key,另一个客户端向其中一个空值key里面插入一个数据,然后观察命令的执行情况:
当未插入时:

如图,当我们监视的key在指定时间内一直为空时,超时后就会返回空,如果在这个时间内插入数据就会返回插入的值
当插入时:

2.2 BRPOP
RPOP的阻塞版本
bash
BRPOP key [key ...] timeout
- 时间复杂度:O(1)
- 返回值:取出的元素或者 nil。
用法方面跟上面的BLPOP同理,这里就不赘述了
3. 内部编码
列表类型的内部编码有两种:
- ziplist(压缩列表):当列表的元素个数⼩于 list-max-ziplist-entries 配置(默认 512 个),同时列表中每个元素的⻓度都⼩于 list-max-ziplist-value 配置(默认 64 字节)时,Redis 会选⽤
ziplist 来作为列表的内部编码实现来减少内存消耗。 - linkedlist(链表):当列表类型⽆法满⾜ ziplist 的条件时,Redis 会使⽤ linkedlist 作为列表的内部实现。
当元素个数较少,且没有大元素时,内部编码为ziplist:
bash
127.0.0.1:6379> rpush listkey e1 e2 e3
OK
127.0.0.1:6379> object encoding listkey
"ziplist"
当元素个数超过512时,内部编码为linkedlist:
bash
127.0.0.1:6379> rpush listkey e1 e2 e3 ... 省略 e512 e513
OK
127.0.0.1:6379> object encoding listkey
"linkedlist"
当某个元素长度超过64字节时,内部编码为linkedlist:
bash
127.0.0.1:6379> rpush listkey "one string is bigger than 64 bytes ... 省略 ..."
OK
127.0.0.1:6379> object encoding listkey
"linkedlist"
三、Set(集合)
集合也是保存多个字符串的类型,但是与列表不同的是,集合内部的元素是无序的,且不能重复,一个集合中最多可以有2^32-1个元素。Redis除了支持集合内部的增删查改,还支持集合间的求交集、并集和差集

1. 普通命令
1.1 SADD
将一个或多个元素添加到set中(不能重复)
bash
SADD key member [member ...]
- 时间复杂度:O(1)
- 返回值:本次添加成功的元素个数。
示例:
bash
127.0.0.1:6379> sadd myset "hello" "world" "world"
(integer) 2
127.0.0.1:6379> smembers myset
1) "world"
2) "hello"
1.2 SMEMBERS
获取一个列表中的所有元素(无序的)
bash
SMEMBERS key
- 时间复杂度:O(N)
- 返回值:所有元素的列表。
示例:
bash
127.0.0.1:6379> sadd myset "hello" "world" "world"
(integer) 2
127.0.0.1:6379> smembers myset
1) "world"
2) "hello"
1.3 SISMEMBER
判断一个元素在不在set中
bash
SISMEMBER key member
- 时间复杂度:O(1)
- 返回值:1 表⽰元素在 set 中。0 表⽰元素不在 set 中或者 key 不存在。
示例:
bash
127.0.0.1:6379> sadd myset one
(integer) 1
127.0.0.1:6379> sismember myset one
(integer) 1
127.0.0.1:6379> sismember myset two
(integer) 0
1.4 SCARD
获取一个set中的元素个数
bash
SCARD key
- 时间复杂度:O(1)
- 返回值:set 内的元素个数。
示例:
bash
127.0.0.1:6379> sadd myset one
(integer) 1
127.0.0.1:6379> scard myset
(integer) 1
1.5 SPOP
从set中随机删除指定个数的元素。
bash
SPOP key [count]
- 时间复杂度:O(N), n 是 count
- 返回值:取出的元素。
示例:
bash
127.0.0.1:6379> sadd myset one two three
(integer) 3
127.0.0.1:6379> smembers myset
1) "two"
2) "one"
3) "three"
127.0.0.1:6379> spop myset 1
1) "three"
127.0.0.1:6379> smembers myset
1) "two"
2) "one"
1.6 SMOVE
将一个元素从源set转入目标set
bash
SMOVE source destination member
- 时间复杂度:O(1)
- 返回值:1 表⽰移动成功,0 表⽰失败。
示例:
bash
127.0.0.1:6379> smembers myset
1) "two"
2) "one"
127.0.0.1:6379> smove myset myset2 one
(integer) 1
127.0.0.1:6379> smembers myset
1) "two"
127.0.0.1:6379> smembers myset2
1) "one"
1.7 SREM
将指定元素从set中删除
bash
SREM key member [member ...]
- 时间复杂度:O(N), N 是要删除的元素个数.
- 返回值:本次操作删除的元素个数。
示例:
bash
127.0.0.1:6379> smembers myset
1) "one"
2) "two"
127.0.0.1:6379> srem myset one two three
(integer) 2
127.0.0.1:6379> smembers myset
(empty list or set)
2. 集合间操作
集合间操作主要是指求交集、并集和差集

2.1 SINTER
获取给定set的交集中的元素
bash
SINTER key [key ...]
时间复杂度:O(N * M), N 是最⼩的集合元素个数. M 是最⼤的集合元素个数.
返回值:交集的元素。
示例:
bash
127.0.0.1:6379> sadd myset1 a b c d e f
(integer) 6
127.0.0.1:6379> sadd myset2 a c f h i
(integer) 5
127.0.0.1:6379> sinter myset1 myset2
1) "a"
2) "f"
3) "c"
2.2 SINTERSTORE
获取给定的两个set的交集并将结果保存到给定的set中
bash
SINTERSTORE destination key [key ...]
- 时间复杂度:O(N * M), N 是最⼩的集合元素个数. M 是最⼤的集合元素个数.
- 返回值:交集的元素个数。
示例:
bash
127.0.0.1:6379> sadd myset1 a b c d e f
(integer) 6
127.0.0.1:6379> sadd myset2 a c f h i
(integer) 5
127.0.0.1:6379> sinter myset1 myset2
1) "a"
2) "f"
3) "c"
127.0.0.1:6379> sinterstore myret myset1 myset2
(integer) 3
127.0.0.1:6379> smembers myret
1) "a"
2) "f"
3) "c"
2.3 SUNION
获取给定set并集中的元素
bash
SUNION key [key ...]
- 时间复杂度:O(N), N 给定的所有集合的总的元素个数.
- 返回值:并集的元素。
示例:
bash
127.0.0.1:6379> sadd myset1 a b c d e f
(integer) 6
127.0.0.1:6379> sadd myset2 a c f h i
(integer) 5
127.0.0.1:6379> sunion myset1 myset2
1) "d"
2) "c"
3) "a"
4) "i"
5) "h"
6) "b"
7) "f"
8) "e"
2.4 SUNIONSTORE
获取给定set并集中的元素并保存到目标的set中
bash
SUNIONSTORE destination key [key ...]
- 时间复杂度:O(N), N 给定的所有集合的总的元素个数.
- 返回值:并集的元素个数。
示例:
bash
127.0.0.1:6379> sadd myset1 a b c d e f
(integer) 6
127.0.0.1:6379> sadd myset2 a c f h i
(integer) 5
127.0.0.1:6379> sunion myset1 myset2
1) "d"
2) "c"
3) "a"
4) "i"
5) "h"
6) "b"
7) "f"
8) "e"
127.0.0.1:6379> sunionstore myret myset1 myset2
(integer) 8
127.0.0.1:6379> smembers myret
1) "d"
2) "c"
3) "a"
4) "i"
5) "h"
6) "b"
7) "f"
8) "e"
2.5 SDIFF
获取给定set的差集中的元素
bash
SDIFF key [key ...]
- 时间复杂度:O(N), N 给定的所有集合的总的元素个数.
- 返回值:差集的元素。
示例:
bash
127.0.0.1:6379> sadd myset1 a b c d e f
(integer) 6
127.0.0.1:6379> sadd myset2 a c f h i
(integer) 5
127.0.0.1:6379> sdiff myset1 myset2
1) "b"
2) "d"
3) "e"
2.6 SDIFFSTORE
获取给定set的差集中的元素并存储到指定的set中
bash
SDIFFSTORE destination key [key ...]
- 时间复杂度:O(N), N 给定的所有集合的总的元素个数.
- 返回值:差集的元素个数。
示例:
bash
127.0.0.1:6379> sadd myset1 a b c d e f
(integer) 6
127.0.0.1:6379> sadd myset2 a c f h i
(integer) 5
127.0.0.1:6379> sdiffstore myret myset1 myset2
(integer) 3
127.0.0.1:6379> smembers myret
1) "b"
2) "d"
3) "e"
- 内部编码
集合类型的内部编码有两种:
- intset(整数集合):当集合中的元素都是整数并且元素的个数⼩于 set-max-intset-entries 配置(默认 512 个)时,Redis 会选⽤ intset 来作为集合的内部实现,从⽽减少内存的使⽤。
- hashtable(哈希):当集合类型⽆法满⾜ intset 的条件时,Redis 会使⽤ hashtable 作为集合
的内部实现。
当元素个数较少且都为整数时,内部编码为intset:
bash
127.0.0.1:6379> sadd setkey 1 2 3
(integer) 3
127.0.0.1:6379> object encoding setkey
"intset"
当元素个数多于512个时,内部编码为hashtable:
bash
127.0.0.1:6379> sadd setkey 1 2 3 4
(integer) 513
127.0.0.1:6379> object encoding setkey
"hashtable
当元素中有非整数类型时,内部编码为hashtable:
bash
127.0.0.1:6379> sadd setkey 1 2 3
(integer) 3
127.0.0.1:6379> object encoding setkey
"intset"
127.0.0.1:6379> sadd setkey hello
(integer) 1
127.0.0.1:6379> object encoding setkey
"hashtable"
四、Zset(有序集合)
有序集合和集合一样,都不能有重复元素,它于集合最大的区别就是它是有序,它是每个元素关联一个分数(score)的方式来确保有序
有序集合提供了获取指定分数和元素范围查找、计算成员排名等功能
1. 普通命令
1.1 ZADD
添加或更新指定的元素及分数到zset中,分数应该符合double类型,+inf/-inf作为正负极限也是合法的
ZADD相关选项:
- XX:仅仅⽤于更新已经存在的元素,不会添加新元素。
- NX:仅⽤于添加新元素,不会更新已经存在的元素。
- CH:默认情况下,ZADD 返回的是本次添加的元素个数,但指定这个选项之后,就会还包含本次更新的元素的个数。
- INCR:此时命令类似 ZINCRBY 的效果,将元素的分数加上指定的分数。此时只能指定⼀个元素和分数。
bash
ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member...]
- 时间复杂度:O(log(N))
- 返回值:本次添加成功的元素个数。
示例:
bash
127.0.0.1:6379> zadd myzset 1 one 2 two 3 three
(integer) 3
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
127.0.0.1:6379> zadd myzset 10 one
(integer) 0
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "two"
2) "2"
3) "three"
4) "3"
5) "one"
6) "10"
127.0.0.1:6379> zadd myzset ch 20 two 30 three
(integer) 2
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "one"
2) "10"
3) "two"
4) "20"
5) "three"
6) "30"
1.2 ZCARD
获取一个zset的基数,即zset中的元素个数
bash
ZCARD key
- 时间复杂度:O(1)
- 返回值:zset 内的元素个数。
示例:
bash
127.0.0.1:6379> zrange myzset 0 -1
1) "one"
2) "two"
3) "three"
127.0.0.1:6379> zcard myzset
(integer) 3
1.3 ZCOUNT
返回分数在min和max之间的元素的个数,默认情况下min和max都是包含的,可以通过( 排除
bash
ZCOUNT key min max
- 时间复杂度:O(log(N))
- 返回值:满⾜条件的元素列表个数。
示例:
bash
127.0.0.1:6379> zadd myzset 1 one 2 two 3 three 4 four
(integer) 4
127.0.0.1:6379> zcount myzset 1 4
(integer) 4
127.0.0.1:6379> zcount myzset (1 (4
(integer) 2
1.4 ZRANGE
返回指定区间内的元素,元素按升序,带上withscores可以把分数也返回
此处的 [start, stop] 为下标构成的区间. 从 0 开始, ⽀持负数.
bash
ZRANGE key start stop [WITHSCORES]
- 时间复杂度:O(log(N)+M)
- 返回值:区间内的元素列表。
示例:
bash
127.0.0.1:6379> zadd myzset 1 one 2 two 3 three 4 four
(integer) 4
127.0.0.1:6379> zrange myzset 1 4
1) "two"
2) "three"
3) "four"
1.5 ZREVRANGE
返回指定区间内的元素,元素按照降序,带上withscores可以把分数也返回
bash
ZREVRANGE key start stop [WITHSCORES]
- 时间复杂度:O(log(N)+M)
- 返回值:区间内的元素列表。
示例:
bash
127.0.0.1:6379> zadd myzset 1 one 2 two 3 three 4 four
(integer) 4
127.0.0.1:6379> zrevrange myzset 1 4
1) "three"
2) "two"
3) "one"
1.6 ZRANGEBYSCORE
返回分数在min和max之间的元素,默认情况下min和max都包含,可以通过( 排除
bash
ZRANGEBYSCORE key min max [WITHSCORES]
- 时间复杂度:O(log(N)+M)
- 返回值:区间内的元素列表。
示例:
bash
127.0.0.1:6379> zadd myzset 1 one 2 two 3 three 4 four
(integer) 4
127.0.0.1:6379> zrangebyscore myzset 1 4
1) "one"
2) "two"
3) "three"
4) "four"
127.0.0.1:6379> zrangebyscore myzset (1 (4
1) "two"
2) "three"
1.7 ZPOPMAX
删除并返回分数最高的count个元素
bash
ZPOPMAX key [count]
- 时间复杂度:O(log(N) * M)
- 返回值:分数和元素列表。
示例:
bash
127.0.0.1:6379> zpopmax myzset
1) "four"
2) "4"
127.0.0.1:6379> zpopmax myzset 3
1) "three"
2) "3"
3) "two"
4) "2"
5) "one"
6) "1"
1.8 ZPOPMIN
删除并返回分数最低的count个元素
bash
ZPOPMIN key [count]
- 时间复杂度:O(log(N) * M)
- 返回值:分数和元素列表。
示例:
bash
127.0.0.1:6379> zadd myzset 1 one 2 two 3 three 4 four
(integer) 4
127.0.0.1:6379> zpopmin myzset
1) "one"
2) "1"
127.0.0.1:6379> zpopmin myzset 3
1) "two"
2) "2"
3) "three"
4) "3"
5) "four"
6) "4"
1.9 BZPOPMIN
zpopmin的阻塞版本
bash
BZPOPMIN key [key ...] timeout
- 时间复杂度:O(log(N))
- 返回值:元素列表。
1.10 ZRANK
按照升序返回指定元素的排名
bash
ZRANK key member
- 时间复杂度:O(log(N))
- 返回值:排名。
示例:
bash
127.0.0.1:6379> zadd myzset 1 one 2 two 3 three 4 four
(integer) 4
127.0.0.1:6379> zrank myzset two
(integer) 1
127.0.0.1:6379> zrank myzset one
(integer) 0
127.0.0.1:6379> zrange myzset 0 -1
1) "one"
2) "two"
3) "three"
4) "four"
1.11 ZREVRANK
按降序返回指定元素的排名
bash
ZREVRANK key member
时间复杂度:O(log(N))
返回值:排名。
示例:
bash
127.0.0.1:6379> zadd myzset 1 one 2 two 3 three 4 four
(integer) 4
127.0.0.1:6379> zrange myzset 0 -1
1) "one"
2) "two"
3) "three"
4) "four"
127.0.0.1:6379> zrevrank myzset one
(integer) 3
127.0.0.1:6379> zrevrank myzset four
(integer) 0
1.11 ZSCORE
返回指定元素的分数
bash
ZSCORE key member
- 时间复杂度:O(1)
- 返回值:分数。
示例:
bash
127.0.0.1:6379> zadd myzset 1 one 2 two 3 three 4 four
(integer) 4
127.0.0.1:6379> zscore myzset one
"1"
1.12 ZREM
删除指定的元素
bash
ZREM key member [member ...]
- 时间复杂度:O(M*log(N))
- 返回值:本次操作删除的元素个数。
示例:
bash
127.0.0.1:6379> zrange myzset 0 -1
1) "one"
2) "two"
3) "three"
4) "four"
127.0.0.1:6379> zrem myzset one two
(integer) 2
127.0.0.1:6379> zrange myzset 0 -1
1) "three"
2) "four"
1.13 ZREMRANGEBYRANK
按照排序,升序删除指定范围内的元素,左闭右闭
bash
ZREMRANGEBYRANK key start stop
- 时间复杂度:O(log(N)+M)
- 返回值:本次操作删除的元素个数。
示例:
bash
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "four"
8) "4"
127.0.0.1:6379> zremrangebyrank myzset 1 2
(integer) 2
127.0.0.1:6379> zrange myzset 0 -1
1) "one"
2) "four"
1.14 ZREMRANGEBYSCORE
按照分数删除指定区间内的元素,左闭右闭
bash
ZREMRANGEBYSCORE key min max
- 时间复杂度:O(log(N)+M)
- 返回值:本次操作删除的元素个数。
示例:
bash
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "four"
8) "4"
127.0.0.1:6379> zremrangebyscore myzset 1 2
(integer) 2
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "three"
2) "3"
3) "four"
4) "4"
1.15 ZINCRBY
为指定元素的关联分数添加指定的分数值
bash
ZINCRBY key increment member
- 时间复杂度:O(log(N))
- 返回值:增加后元素的分数。
示例:
bash
127.0.0.1:6379> zscore myzset four
"4"
127.0.0.1:6379> zincrby myzset 10 four
"14"
127.0.0.1:6379> zscore myzset four
"14"
127.0.0.1:6379> zincrby myzset -10 four
"4"
127.0.0.1:6379> zscore myzset four
"4"
2. 集合间操作
2.1 ZINTERSTORE
求出给定有序集合的交集并保存到目标集合中,在合并中元素按照约定好的权重计算后相加写入目标有序集合中
bash
ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight[weight ...]] [AGGREGATE <SUM | MIN | MAX>]
- 时间复杂度:O(N*K)+O(M*log(M)) N 是输⼊的有序集合中, 最⼩的有序集合的元素个数; K 是输⼊了⼏个有序集合; M 是最终结果的有序集合的元素个数.
- 返回值:⽬标集合中的元素个数
示例:
bash
127.0.0.1:6379> zadd zset1 1 one 2 two
(integer) 2
127.0.0.1:6379> zadd zset2 1 one 2 two
(integer) 2
127.0.0.1:6379> zinterstore myzset 2 zset1 zset2 weights 2 3
(integer) 2
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "one"
2) "5"
3) "two"
4) "10"
2.2 ZUNIONSTORE
求出给定有序集合中元素的并集并保存进⽬标有序集合中,在合并过程中以元素为单位进⾏合并,元素对应的分数按照不同的聚合⽅式和权重得到新的分数。
bash
ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight
[weight ...]] [AGGREGATE <SUM | MIN | MAX>]
- 时间复杂度:O(N)+O(M*log(M)) N 是输⼊的有序集合总的元素个数; M 是最终结果的有序集合的元素个数.
- 返回值:⽬标集合中的元素个数
示例:
bash
redis> ZADD zset1 1 "one"
(integer) 1
redis> ZADD zset1 2 "two"
(integer) 1
redis> ZADD zset2 1 "one"
(integer) 1
redis> ZADD zset2 2 "two"
(integer) 1
redis> ZADD zset2 3 "three"
(integer) 1
redis> ZUNIONSTORE out 2 zset1 zset2 WEIGHTS 2 3
(integer) 3
redis> ZRANGE out 0 -1 WITHSCORES
1) "one"
2) "5"
3) "three"
4) "9"
5) "two"
6) "10"
3. 内部编码
有序集合类型的内部编码有两种:
- ziplist(压缩列表):当有序集合的元素个数⼩于 zset-max-ziplist-entries 配置(默认 128 个),同时每个元素的值都⼩于 zset-max-ziplist-value 配置(默认 64 字节)时,Redis 会⽤ ziplist 来作为有序集合的内部实现,ziplist 可以有效减少内存的使⽤。
- skiplist(跳表):当 ziplist 条件不满⾜时,有序集合会使⽤ skiplist 作为内部实现,因为此时
ziplist 的操作效率会下降。
当元素个数较少且每个元素大小较小时,内部编码为ziplist:
bash
127.0.0.1:6379> zadd zsetkey 50 e1 60 e2 30 e3
(integer) 3
127.0.0.1:6379> object encoding zsetkey
"ziplist"
当元素个数超过128个时,内部编码为skiplist:
bash
127.0.0.1:6379> zadd zsetkey 50 e1 60 e2 30 e3 ... 省略 ... 82 e129
(integer) 129
127.0.0.1:6379> object encoding zsetkey
"skiplist"
当某个元素大于64字节时,内部编码为skiplist:
bash
127.0.0.1:6379> zadd zsetkey 50 "one string bigger than 64 bytes ... 省略 ..."
(integer) 1
127.0.0.1:6379> object encoding zsetkey
"skiplist"
五、总结
以上四个加上String类型就是Redis中最常用的五种数据类型,这五种数据类型已经能囊括大部分的使用场景,在有些特殊场景我们或许还是需要借助另外五个数据类型,那五种数据类型也不是很难,用到的时候再自己查文档学习即可
感谢各位大佬观看,创作不易,还望各位大佬点赞支持!!!