Redis-1-数据类型

本文深入解析Redis中的五大数据结构:字符串、哈希、列表、集合和有序集合。详细介绍了每种数据结构的底层实现、常用命令及时间复杂度,帮助读者全面理解Redis的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1. 字符串

1.1 命令

1.1.1 设置值

1.1.2 获取值

1.1.3 批量设置值

1.1.4 批量获取值

1.1.5 自增

1.1.6 追加值

1.1.7 字符串长度

1.1.8 设置并返回原值

1.1.9 设置指定位置的字符

1.1.10 获取部分字符串

1.1.11 命令与时间复杂度

1.2 底层实现

1.3 String命令总结

2. 哈希

2.1 命令

2.1.1 设置值

2.1.2 获取值

2.1.3 删除field

2.1.4 计算field个数

2.1.5 批量设置/获取field

2.1.6 判断field是否存在

2.1.7 获取所有field

2.1.8 获取所有value

2.1.9 获取所有的field-value

2.1.10 自增

2.1.1 1 计算value的字符串长度

2.1.12 时间复杂度

2.2 底层实现

2.3 Hash命令总结

3. 列表

3.1 命令

3.1.1 从右边插入元素

3.1.2 从左边插入元素

3.1.3 向某个元素前/后插入元素

3.1.4 获取指定范围内的元素列表

3.1.5 获取列表指定索引下标的元素

3.1.6 获取列表长度

3.1.7 从列表左侧弹出元素

3.1.8 从列表右侧弹出

3.1.9 删除指定元素

3.1.10 按照索引范围修剪列表

3.1.11 修改指定索引下标的元素

3.1.12 阻塞式弹出

3.1.13 时间复杂度

3.2 底层实现

3.3 List命令总结

4. 集合

4.1 命令

4.1.1 添加元素

4.1.2 删除元素

4.1.3 计算元素个数

4.1.4 判断元素是否在集合中

4.1.5 随机从集合返回指定个数元素

4.1.6 从集合随机弹出元素

4.1.7 获取所有元素

4.1.8 求多个集合的交集

4.1.9 求多个集合的并集

4.1.10 求多个集合的差集

4.1.11 将交集、并集、差集的结果保存

4.1.12 时间复杂度

4.2 底层实现

4.3 Set集合总结

5. 有序集合

5.1 命令

5.1.1 添加成员

5.1.2 计算成员个数

5.1.3 计算某个成员的分数

5.1.4 计算成员的排名

5.1.5 删除成员

5.1.6 增加成员的分数

5.1.7 返回指定排名范围的成员

5.1.8 返回指定分数范围的成员

5.1.9 返回指定分数范围成员个数

5.1.10 删除指定排名内的升序元素

5.1.11 删除指定分数范围的成员

5.1.12 交集

5.1.13 并集

5.1.14 时间复杂度

5.2 底层实现

5.3 有序集合命令总结

6. 键通用操作命令

6.1 键重命名

6.2 随机返回一个键

6.3 键过期

6.4 迁移键

6.5 遍历键

6.6 数据库管理




1. 字符串

Redis中键都是字符串类型。字符串类型的值实际可以是简单字符串、复杂字符串(XML、JSON等)、整数、浮点数、二进制(图片、视频、音频,但不能超过512MB)。

1.1 命令

1.1.1 设置值

命令:set key value [ex seconds] [px milliseconds] [nx|xx]

注意事项:返回结果为OK即代表设置成功,返回0则代表设置失败;

选项:ex seconds:为key设置秒级过期时间。

px milliseconds:为key设置毫秒级过期时间。

nx:key必须不存在的前提下,set才能执行成功。

xx:key必须存在的前提下,set才能执行成功。

除了set选项,还提供了setex、setnx命令:

setex key seconds value(作用跟ex选项一致)

setnx key value(作用跟nx选项一致)

1.1.2 获取值

命令:get key

注意事项:如果key存在则返回对应的value,否则返回nil

1.1.3 批量设置值

命令:mset key value [key value......]

1.1.4 批量获取值

命令:mget key [key......]

注意事项:如果key不存在则返回nil。mget比get优点在于只发送一次网络请求,例如发送10次get则经过网络10次,而mget只需经过网络1次,当然1次mget也不能获取太多数据,数据太多也能造成Redis阻塞/网络拥堵。

1.1.5 自增

命令:incr key

注意事项:如果value不是整数则返回错误,如果value是整数则返回自增后的结果,如果key不存在则按照0开始自增并返回结果1。

自增:incr key

自增指定数字:incrby key increment

自减:decr key

自减指定数字:decrby key decrement

自增浮点数:incrbyfloat key increment

1.1.6 追加值

命令:append key value

注意事项:向字符串尾部追加值,

1.1.7 字符串长度

命令:strlen key

1.1.8 设置并返回原值

命令:getset key value

1.1.9 设置指定位置的字符

命令:setrange key offeset value

注意事项:索引从0开始。

1.1.10 获取部分字符串

命令:getrange key start end

注意事项:start和end分别代表开始、结束的偏移量,偏移量从0开始计算,包头包尾。

1.1.11 命令与时间复杂度

命令

时间复杂度

set

O(1)

get

O(1)

del

O(k)k为键的个数

mset

O(k)k为键的个数

mget

O(k)k为键的个数

incr

O(1)

decr

O(1)

incrby

O(1)

decrby

O(1)

incrbyfloat

O(1)

append

O(1)

strlen

O(1)

setrange

O(1)

getrange

O(n)n为字符串长度,由于获取字符串非常快,所以如果字符串不是很长的话可以等同为O(1)

 

1.2 底层实现

int:8个字节的长整型

embstr:小于等于39个字节的字符串

raw:大于39个字节的字符串

Redis会根据value类型和长度,去决定使用哪种底层实现。

1.3 String命令总结

指令

解释

指令时间复杂度

set key value [ex seconds]

[px milliseconds] [nx|xx]

ex seconds为键设置秒级过期时间

px milliseconds为键设置毫秒级过期时间

nx键必须不存在才可以设置成功,用于新增

xx键必须存在才可以设置成功,用于更新

O(1)

setex key seconds value

跟ex seconds同样含义

 

setnx key value

跟set nx同样含义

 

get key

获取值,不存在则返回nil

O(1)

mset key value [key value...]

批量设置值

O(k),k是键的个数

mget key [key...]

批量获取值,结果是按照传入键的顺序返回,如果键不存在则返回nil

O(k),k是键的个数

incr key

计数,当值不是整数返回错误,

当值是整数返回自增后的结果,当键不存在按照值为0自增返回结果为1

O(1)

decr key

自减

O(1)

incrby key increment

自增指定数字

O(1)

decrby key decrement

自减指定数字

O(1)

incrbyfloat key increment

自增浮点数

O(1)

append key value

追加值

O(1)

strlen key

字符串长度

O(1)

getset key value

设置并返回原值

 

setrange key offeset value

设置指定位置的字符

O(1)

getrange key start end

获取部分字符串

O(n),n是字符串长度,由于获取字符串非常快,所以如果字符串不是很长,可以约等于O(1)

 字符串内部,会根据值不同而采取不同的内部结构,目前其内部结构有3种:int代表8个字节的长整型、embstr小于等于39个字节的字符串、raw大于39个字节的字符串。

2. 哈希

哈希类型是指value自身又是一个键值对结构。

2.1 命令

2.1.1 设置值

命令:hset key field value

注意事项:设置成功返回1,否则返回0;还有hsetnx命令。

2.1.2 获取值

命令:hget key field

注意事项:如果key或者field不存在则返回nil,否则返回对应value

2.1.3 删除field

命令:hdel key field [field ......]

注意事项:返回结果为成功删除field的个数。

2.1.4 计算field个数

命令:hlen key

2.1.5 批量设置/获取field

命令:hmset key field value [field value......]

  hmget key filed [field......]

2.1.6 判断field是否存在

命令:hexists key field

注意事项:存在则返回1,否则返回0.

2.1.7 获取所有field

命令:hkeys key

注意事项:返回key对应的、所有的field。

2.1.8 获取所有value

命令:hvals key

2.1.9 获取所有的field-value

命令:hgetall key

注意事项:在使用hgetall时,如果哈希元素个数比较多会存在阻塞Redis的可能。如果只需获取部分field则可以使用hmget。如果一定要获取全部field-value则可以使用hscan命令。

2.1.10 自增

命令:hincrby key field/hincrbyfloat key field

2.1.1 1 计算value的字符串长度

命令:hstrlen key field

注意事项:需要Redis3.2以上

2.1.12 时间复杂度

命令

时间复杂度

hset

O(1)

hget

O(1)

hdel

O(k)k为field个数

hlen

O(1)

hgetall

O(k)k为field个数

hmget

O(k)k为field个数

hmset

O(k)k为field个数

hexists

O(1)

hkeys

O(k)k为field个数

hvals

O(k)k为field个数

hsetnx

O(1)

hincrby

O(1)

hincrbyfloat

O(1)

hstrlen

O(1)

 

2.2 底层实现

ziplist压缩列表:当哈希类型元素数量小于hash-max-ziplist-entries参数(默认512个)、同时value都小于hash-max-ziplist-value参数(默认64字节)时,Redis使用ziplist作为哈希的内部实现。Ziplist使用更加紧凑的结构实现多个元素的连续存储,在节省内存方面比hashtable更加优秀。

hashtable哈希表:无法满足ziplist使用条件时,Redis则使用hashtable作为哈希的内部实现,因为此时的ziplist读写效率会下降而hashtable的读写时间复杂度反而为O(1)。

2.3 Hash命令总结

Redis是key-value形式,只不过value自身又是field-value形式。

指令

解释

指令时间复杂度

hset key field value

设置值,设置成功返回1,否则返回0

O(1)

hget key field

获取值,如果key或field不存在则返回nil

O(1)

hdel key field [field...]

删除field,返回结果是成功删除field的个数

O(k),k是field个数

hlen key

计算field个数

O(1)

hmget key field [field...]

批量获取field

O(k),k是field个数

hmset key field value [filed value...]

批量设置field

O(k),k是field个数

hexists key field

判断field是否存在,存在返回1,不存在返回0

O(1)

hkeys key

获取所有field

O(n),n是field总数

hvals key

获取所有value

O(n),n是field总数

hgetall key

获取所有的field-value

O(n),n是field总数

hscan

 

 

hincrby key field

对field自增

O(1)

hincrbyfloat key field

对field自增

O(1)

hstrlen key field

计算value的字符串长度

O(1)

Hash类型的内部结构有2种:

ziplist:当哈希类型元素field个数小于hash-max-ziplist-entries配置(默认512个)、或者,所有值value都小于hash-max-ziplist-value配置(默认64字节)时,Redis会使用ziplist作为哈希的内部实现,ziplist使用更加紧凑的结构实现多个元素的连续存储,基于小对象压缩技术,因此在节省内存方面比hashtable更加优秀。

hashtable:当哈希类型无法满足ziplist的条件时,Redis会使用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降,而hashtable的读写时间复杂度为O(1)。

3. 列表

用来存储多个有序的字符串,每个字符串称为元素element,一个列表最多可以存储2^32-1个元素。在Redis中可以对列表两端插入push和弹出pop、还可以获取指定范围的元素列表、获取指定索引下标的元素等等。可以充当栈和队列的角色。

列表类型有2个特点:①列表中的元素是有序的,可以通过索引下标来获取某个元素/某个范围内的元素列表,索引从0开始。②列表中的元素可以重复。

3.1 命令

3.1.1 从右边插入元素

命令:rpush key value [value......]

3.1.2 从左边插入元素

命令:lpush key value [value......]

3.1.3 向某个元素前/后插入元素

命令:linsert key before/after pivot value

注意事项:linsert命令会从列表中找到等于pivot的元素,然后在其前before或后after插入一个新元素value

3.1.4 获取指定范围内的元素列表

命令:lrange key start end

注意事项:索引下标从左到右分别是0到(N-1),但从右到左分别是-1到-N,另外lrange的end选项包含了自身即包头包尾

3.1.5 获取列表指定索引下标的元素

命令:lindex key index

注意事项:例如当前列表最后一个元素为a:lindex listkey -1.这里可以参考lrange中从右到左的索引下标排序。

3.1.6 获取列表长度

命令:llen key

3.1.7 从列表左侧弹出元素

命令:lpop key

3.1.8 从列表右侧弹出

命令:rpop key

3.1.9 删除指定元素

命令:lrem key count value

注意事项:lrem命令从列表中找到等于value的元素进行删除,根据count选项的不同而分为3种情况:

①count>0,从左到右,删除最多count个元素

②count<0,从右到左,删除最多count绝对值个元素

③count=0,删除所有

3.1.10 按照索引范围修剪列表

命令:ltrim key start end

注意事项:包头包尾

3.1.11 修改指定索引下标的元素

命令:lset key index newValue

3.1.12 阻塞式弹出

命令:blpop key [key...] timeout/brpop key [key...] timeout

注意事项:

①在列表为空的前提下,如果timeout>0则客户端等待timeout秒后才能拿到结果,

如果timeout=0则客户端一直处于等待状态,直到有新数据插入后客户端才拿到数据。

②在列表不为空的前提下,timeout=0则立即返回给客户端

3.1.13 时间复杂度

操作类型

命令

时间复杂度

添加

rpush

O(k)k是元素个数

lpush

O(k)k是元素个数

linsert

O(n)n是pivot距离到表头/表尾的距离

查找

lrange

O(s+n)s是start偏移量,n是start到end的范围

lindex

O(n)n是索引的偏移量

llen

O(1)

删除

lpop

O(1)

rpop

O(1)

lrem

O(n)n是列表长度

ltrim

O(n)n是要裁剪的元素总数

修改

lset

O(n)n是索引的偏移量

blpop

O(1)

brpop

O(1)

 

3.2 底层实现

ziplist压缩列表:当列表元素个数小于list-max-ziplist-entries参数(默认512个),同时列表中每个元素的值都小于list-max-ziplist-value参数(默认64字节),Redis会选用ziplist来作为列表的内部实现来减少内存的使用。

linkedlist链表:当列表类型无法满足ziplist条件时,Redis会使用linkedlist作为列表的内部实现。

quicklist:Redis3.2提供,以ziplist为节点的linkedlist。

3.3 List命令总结

指令

解释

指令时间复杂度

rpush key value [value...]

从右边插入元素

O(k),k是元素个数

lpush key value [value...]

从左边插入元素

O(k),k是元素个数

linsert key before|after pivot value

向某个元素前或者后插入元素,linsert命令会从列表中找到等于pivot的元素,在其前before或者后after插入一个新元素value

O(n),n是pivot距离列表头或尾的距离

lrange key start end

查找,lrange会获取列表指定索引范围所有的元素。索引下标取值范围有如下特点:

①索引从左到右分别是0到N-1,从右到左分别是-1到-N

②lrange中的end选项包含自身,start选项也包含自身

O(s+n),s是start偏移量,n是start到end 的范围

lindex key index

获取列表指定索引下标的元素

O(n),n是索引的偏移量

llen key

获取列表长度

O(1)

lpop key

从列表左侧弹出元素

O(1)

rpop key

从列表右侧弹出元素

O(1)

lrem key count value

删除指定元素value,根据count取值不同分为3种情况:

①count为正数,从左到右,删除最多count个元素

②count为负数,从右到左,删除最多count绝对值个元素

③count=0,删除所有元素

O(n),n是列表长度

ltrim key start end

按照索引范围修剪列表

O(n),n是要裁剪的元素总数

lset key index newValue

修改指定索引下标的元素

O(n),n是索引的偏移量

blpop key [key...] timeout

lpop的阻塞形式,timeout表示阻塞时间(单位:秒),当timeout=0时则永远阻塞下去直到有元素弹出。

当[key...]如果某个key有值则立即返回给客户端;

O(1)

brpop key [key...] timeout

rpop的阻塞形式,timeout表示阻塞时间(单位:秒),当timeout=0时则永远阻塞下去直到有元素弹出。

当[key...]如果某个key有值则立即返回给客户端;)

O(1)

内部编码:

其实,在Redis原理章节中,有个“小对象压缩技术”,说白了就是尽量减少对内存的占用,避免因为内存崩溃。

ziplist:当列表的元素个数小于list-max-ziplist-entries配置(默认512个),同时列表中每个元素的值都小于list-max-ziplist-value配置时(默认64字节),Redis会选用ziplist来作为列表的内部实现来减少内存的使用。

linkedlist:当列表类型无法满足ziplist的条件时,Redis会使用linkedlist作为列表的内部实现。

4. 集合

集合set不允许有重复元素,并且集合中元素是无序的,因此不能通过索引下标来获取元素。一个集合最多可以存储2^32-1个元素。

4.1 命令

4.1.1 添加元素

命令:sadd key element [element...]

注意事项:返回结果为添加成功的元素个数

4.1.2 删除元素

命令:srem key element [element...]

注意事项:返回结果为成功删除元素个数

4.1.3 计算元素个数

命令:scard key

注意事项:scard命令并不会遍历集合set所有元素,而是直接用Redis内部变量,因此该命令的时间复杂度为O(1)。

4.1.4 判断元素是否在集合中

命令:sismember key element

注意事项:存在则返回1,否则返回0.

4.1.5 随机从集合返回指定个数元素

命令:srandmember key [count]

注意事项:count是可选参数,不写默认为1.

4.1.6 从集合随机弹出元素

命令:spop key

注意事项:spop从Redis3.2版本开始也支持count参数,srandmember和spop都是随机从集合选出元素,两者不同的是spop命令执行后,元素会从集合中删除而srandmember则不会。

4.1.7 获取所有元素

命令:smembers key

注意事项:smembers、lrange、hgetall都属于比较重的命令,如果元素过多则存在阻塞Redis的可能性,可以用sscan来完成。

4.1.8 求多个集合的交集

命令:sinter key [key...]

4.1.9 求多个集合的并集

命令:suinon key [key...]

4.1.10 求多个集合的差集

命令:sdiff key [key...]

4.1.11 将交集、并集、差集的结果保存

命令:

sinterstore destination key [key...]

suionstore destination key [key...]

sdiffstore destination key [key...]

4.1.12 时间复杂度

命令

时间复杂度

sadd

O(k)k是元素个数

srem

O(k)k是元素个数

scard

O(1)

sismember

O(1)

sradmember key [count]

O(count)

spop

O(1)

smembers

O(n)n是元素总数

sinter/sinterstore

O(m*k)k是多个集合中元素最少的个数,m是键个数

suinon/suinonstore

O(k)k是多个集合元素个数和

sdiff/sdiffstore

O(k)k是多个集合元素个数和

 

4.2 底层实现

intset整数集合:当集合中元素都是整数、元素个数小于set-max-intset-entries配置(默认512个)时,Redis会选择intset来作为集合的内部实现从而减少内存使用。

hashtable哈希表:当无法满足intset条件时则选择hashtable作为集合内部实现。

4.3 Set集合总结

集合(set)类型也是用来保存多个的字符串元素,但和列表类型不一样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引下标获取元素。一个集合最多可以存储232-1个元素。Redis除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集。

指令

解释

指令时间复杂度

sadd key element

[element...]

添加元素,返回结果为添加成功的元素个数

O(k),k是元素个数

srem key element

[element...]

删除元素,返回结果为成功删除元素个数

O(k),k是元素个数

scard key

计算元素个数,该指令不会遍历集合所有元素,而是直接用内部变量

O(1)

sismember key element

判断元素是否在集合中,如果给定元素element在集合内则返回1,否则返回0

O(1)

srandmember key [count]

随机从集合返回指定个数元素,count不写则默认为1

O(count)

spop key

从集合中随机弹出元素,然后从集合中删除被弹出的元素

O(1)

smembers key

获取所有元素,如果元素过多,该指令会导致Redis阻塞,建议使用sscan

O(n),n是元素总数

sinter key [key....]

求多个集合的交集

O(m*k),k是多个集合中元素最少的个数,m是键个数

suinon key [key...]

求多个集合的并集

O(k),k是多个集合元素个数总和

sdiff key [key...]

求多个集合的差集

O(k),k是多个集合元素个数总和

sinterstore destination key [key...]

保存交集结果,destination是目标集合

O(m*k),k是多个集合中元素最少的个数,m是键个数

suionstore destination key [key...]

保存并集结果,destination是目标集合

O(k),k是多个集合元素个数总和

sdiffstore destination key [key...]

保存差集结果,destination是目标集合

O(k),k是多个集合元素个数总和

集合类型的内部编码有两种:

intset:当集合中的元素都是整数且元素个数小于set-maxintset-entries配置(默认512个)时,Redis会选用intset来作为集合的内部实现,从而减少内存的使用。

hashtable:当集合类型无法满足intset的条件时,Redis会使用hashtable作为集合的内部实现。

5. 有序集合

保留了集合不能重复成员的特性,同时还可以排序。有序集合给每个元素设置一个分数score作为排序的依据。

数据结构

是否允许重复元素

是否有序

有序实现方式

列表

索引下标

集合

有序集合

分值

 

5.1 命令

5.1.1 添加成员

命令:zadd key score member [score member...]

注意事项:返回结果代表成功添加成员的个数.有序集合比集合提供了排序字段,因此zadd的时间复杂度O(log(n)),sadd时间复杂度为O(1)。

参数选项:Redis3.2为zadd添加了nx、xx、ch、incr四个选项:

nx:member必须不存在才可以设置成功

xx:member必须存在才可以设置成功

ch:返回此次操作后有序集合元素和分数发生变化的个数

incr:对score做增加,相当于zincrby

5.1.2 计算成员个数

命令:zcard key

注意事项:跟集合类型的scard命令一样,zcard时间复杂度为O(1)

5.1.3 计算某个成员的分数

命令:zscore key member

注意事项:如果成员不存在则返回nil

5.1.4 计算成员的排名

命令:zrank key member/zrevrank key member

注意事项:zrank是分数从低到高返回排名,zrevrank反之。

5.1.5 删除成员

命令:zrem key member [member...]

注意事项:返回结果为成功删除的个数。

5.1.6 增加成员的分数

命令:zincrby key increment member

5.1.7 返回指定排名范围的成员

命令:zrange key start end [withscores]/zrevrange key start end [withscores]

注意事项:zrange是从低到高返回,zrevrange反之。

5.1.8 返回指定分数范围的成员

命令:

zrangebyscore key min max [withscores] [limit offset count]

zrevrangebyscore key max min [withscores] [limit offset count]

注意事项:zrangebyscore按照分数从低到高返回,zrevrangebyscore反之。

参数选项:

  1. withscores选项会同时返回每个成员的分数。
  2. [limit offset count]选项可以限制输出的起始位置和个数。
  3. 同时min和max还支持开区间(小括号)和闭区间(中括号),-inf和+inf分别代表无限小和无限大。

5.1.9 返回指定分数范围成员个数

命令:zcount key min max

5.1.10 删除指定排名内的升序元素

命令:zremrangebyrank key start end

5.1.11 删除指定分数范围的成员

命令:zremrangebyscore key min max

5.1.12 交集

命令:

zinterstore  destination  numkeys  key [key ...]  [weights weight [weight ...]]    [aggregate sum|min|max]

参数选项:

  1. destination:交集计算结果保存到这个键。
  2. numkeys:需要做交集计算键的个数。
  3. key[key...]:需要做交集计算的键。   
  4. weights weight[weight...]:每个键的权重,在做交集计算时,每个键中的每个member会将自己分数乘以这个权重,每个键的权重默认是1。
  5. aggregate sum|min|max:计算成员交集后,分值可以按照sum(和)、min(最小值)、max(最大值)做汇总,默认值是sum。

5.1.13 并集

命令:

zunionstore   destination   numkeys   key [key ...]   [weights weight [weight ...]]    [aggregate sum|min|max]

注意事项:该命令的所有参数和zinterstore是一致的。

5.1.14 时间复杂度

命令

时间复杂度

Zadd

O(K*log(n))。K是添加成员的个数,n是当前有序集合成员个数。

Zcard

O(1)

zscore

O(1)

Zrank/zrevrank

O(log(n))

Zrem

O(k*log(n))。K是删除成员的个数,n是当前有序集合成员个数

Zincrby

O(log(n))

Zrange/zrevrange

O(log(n)+k)。K是要获取的成员个数,n是当前有序集合成员个数

Zrangebyscore/zrevrangebyscore

O(log(n)+k)。K是要获取的成员个数,n是当前有序集合成员个数

zcount

O(log(n))

Zremrangebyrank/zremrangebyscore

O(log(n)+k)。K是要获取的成员个数,n是当前有序集合成员个数

Zinterstore

O(n*k)+O(m*log(m))。n是成员数最小的有序集合成员个数,k是有序集合的个数,m是结果集中成员个数

zunionstore

O(n)+O(m*log(m))。n是所有有序集合成员个数和,m是结果集中成员个数。

 

5.2 底层实现

Ziplist压缩列表:当有序集合的元素个数小于zset-max-ziplistentries

配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配

置(默认64字节)时,Redis会用ziplist来作为有序集合的内部实现,ziplist

可以有效减少内存的使用。

Skiplist跳跃表:当ziplist条件不满足时,有序集合会使用skiplist作

为内部实现,因为此时ziplist的读写效率会下降。

5.3 有序集合命令总结

它保留了集合不能有重复成员的特性,但不同的是,有序集合中的元素可以排序。

指令

解释

指令时间复杂度

zadd key score member

[score member...]

添加成员,返回结果代表成功添加成员的个数。

nx:member必须不存在才能设置成功。

xx:member必须存在才能设置成功。

ch:返回此次操作后有序集合元素和分数发生变化的个数。

incr:对score做增加。

O(k * log(n)),k是添加成员的个数,n是当前有序集合成员个数

zcard key

计算成员个数

O(1)

zscore key member

计算某个成员的分数,如果成员不存在则返回nil

O(1)

zrank key member

zrevrank key member

计算成员的排名,zrank是分数从低到高返回排名,zrevrank是分数从高到低返回排名

O(log(n)),n是当前有序集合成员个数

zrem key member[member...]

删除成员,返回结果为成功删除的个数

O(k * log(n)),k是删除成员的个数,n是当前有序集合成员个数

zincrby key increment

member

增加成员的分数

O(log(n)),n是当前有序集合成员个数

zrange key start end [withscores]

Zrevrange key start end [withscores]

返回指定排名范围的成员,

zrange是从低到高返回,zrevrange反之。加上withscores选项则同时返回分数

O(log(n) + k),k是要获取的成员个数,n是当前有序集合成员个数

zrangebyscore key min max [withscores][limit offset count]

zrevrangebyscore key max min [withscores][limit offset count]

返回指定分数范围的成员。zrangebyscore按照分数从低到高返回,zrevrangebyscore反之。

Withscores同时返回每个成员的分数,而limit offset count则限制输出的起始位置和个数。

同时min和max还支持开区间(小括号)和闭区间(中括号),-inf和+inf分别代表无限小和无限大。

O(log(n) + k),k是要获取的成员个数,n是当前有序集合成员个数

zcount key min max

返回指定分数范围成员个数

O(log(n)),n是当前有序集合成员个数

zremrangebyrank key start end

删除指定排名内的升序元素,返回结果为成功删除的个数

O(log(n) + k),k是要删除的成员个数,n是当前有序集合成员个数

zremrangebyscore key min max

删除指定分数范围的成员,返回结果为成功删除的个数

O(log(n) + k),k是要删除的成员个数,n是当前有序集合成员个数

zinterstore destination numkeys key [key...][weights weight [weight...]][aggregate sum|min|max]

交集

Destination交集计算结果保存到这个键

Numkeys需要做交集计算键的个数

Key[key...]需要做交集计算的键

Weights weight[weight]每个键的权重,默认值为1

Aggregate sum|min|max计算成员交集后,分值可以按照sum和、min最小值、max最大值做汇总,默认值是sum

O(n*k)+O(m*log(m)),n是成员数最小的有序集合成员个数,k是有序集合的个数,m是结果集合中成员个数

zunionstore destination numkeys key [key...][weights weight[weight...]][aggregate sum|min|max]

并集运算,该命令的所有参数和zinterstore是一致的

O(n)+O(m*log(m)),n是所有有序集合成员个数和,m是结果集合中成员个数

有序集合类型的内部编码有两种:

ziplist:当有序集合的元素个数小于zset-max-ziplistentries配置(默认128个),同时每个元素的值都小于zset-max-ziplist-value配置(默认64字节)时,Redis会用ziplist来作为有序集合的内部实现,ziplist可以有效减少内存的使用。

skiplist:当ziplist条件不满足时,有序集合会使用skiplist作为内部实现,因为此时ziplist的读写效率会下降。

6. 键通用操作命令

6.1 键重命名

命令:rename key newkey

注意事项:

①如果在rename之前,键newkey已经存在则将被覆盖。为了防止被强行rename,Redis提供了renamenx命令,确保只有newkey不存在时才能被覆盖,返回结果是0则代表没有完成重命名操作;

②由于重命名键期间会执行del命令删除旧的键,如果键对应的值比较大,会存在阻塞Redis的可能性;

③如果rename和renamenx中的key和newkey如果是相同的,在Redis3.2和之前版本返回结果略有不同:Redis3.2中会返回OK,Redis3.2之前的版本会提示错误。

6.2 随机返回一个键

命令:randomkey

6.3 键过期

命令:

expireat key seconds键在seconds秒后过期;

expireat key timestamp键在秒级时间戳timestamp后过期;

ttl和pttl命令都可以查询键的剩余过期时间,但pttl精度更高,可以达到毫秒级别,pttl有3种返回值:正整数代表键剩余的过期毫秒;-1则代表没有设置过期时间;-2键不存在;

pexpire key milliseconds键在milliseconds毫秒后过期;

pexpireat key milliseconds-timestamp键在毫秒级时间戳timestamp后过期;

注意事项:

①如果expire key的键不存在,返回结果为0:

②如果过期时间为负值,键会立即被删除,犹如使用del命令一样:

③persist命令可以将键的过期时间清除:

④对于字符串类型键,执行set命令会去掉过期时间;

⑤Redis不支持二级数据结构(例如哈希、列表)内部元素的过期功能;

⑥setex命令作为set+expire的组合,不但是原子执行,同时减少了一次网络通讯的时间;

6.4 迁移键

命令:move key db

注意事项:move命令用于在Redis内部进行数据迁移,Redis内部可以有多个数据库,彼此在数据上是相互隔离的,move key db就是把指定的键从源数据库移动到目标数据库中。

命令:dump + restore

dump key

restore key ttl value

迁移过程:dump+restore实现在不同Redis实例之间进行数据迁移的功能,整个迁移过程分为2步:

1.在源Redis上,dump命令将键和值都序列化,格式采用的是RDB格式;

2.在目标Redis上,restore命令将上面序列化的值进行复原,其中ttl参数代表过期时间,如果ttl=0代表没有过期时间;

注意事项:一方面整个迁移过程并非原子性的而是通过客户端分步完成的,另一方面迁移过程是开启了两个客户端连接

命令:migrate host port key|”” destination-db timeout [copy] [replace] [keys key [key...]]

参数说明:

host:目标Redis的IP地址

port:目标Redis的端口

key|””:3.0.6之前migrate只支持迁移一个键,因此这里是要迁移的键;3.0.6之后支持迁移多个键,如果当前需要迁移多个键,此处为空字符串

destination-db:目标Redis的数据库索引,例如要迁移到0号数据库,这里就写0

Timeout:迁移的超时时间,单位为毫秒

[copy]:如果添加此选项,迁移后并不删除源键

[replace]:如果添加此选项,migrate不管目标Redis是否存在该键都会正常迁移并进行数据覆盖

[keys key[key...]]:要迁移的多个键,例如要迁移key1、key2、key3,此处填写:keys key1 key2 key3

迁移过程:migrate命令也用于在Redis实例之间进行数据迁移,实际上migrate命令就是把dump+restore+del命令进行组合从而简化了操作流程。Migrate命令具有原子性,从3.0.6版本以后支持迁移多个键功能从而提高迁移效率。

注意事项:

第一整个过程是原子执行的,不需要在多个Redis实例上开启客户端的,只需要在源Redis上执行migrate命令即可。

第二migrate命令的数据传输直接在源Redis与目标Redis完成。

第三目标Redis完成restore后会发送OK给源Redis,源Redis接收后会根据migrate对应的选项来决定是否在源Redis上删除对应的键

6.5 遍历键

命令:keys pattern,又叫全量遍历键

注意事项:pattern可以使用glob风格的通配符,例如:*代表匹配任意字符、.代表匹配一个字符、[]代表匹配部分字符、\x用来做转义,由于Redis是单线程架构,如果Redis包含了大量的键,使用pattern可能会造成Redis阻塞

命令:scan,又叫渐进式遍历

scan cursor [match pattern] [count number]

参数说明:

Cursor必须参数,cursor是一个游标,第一次遍历从0开始,每次scan遍历完都会返回当前游标的值,直到游标值为0表示遍历结束

Match pattern是可选参数,它的作用是做模式匹配

Count number是可选参数,作用是表明每次要遍历的键个数,默认值是10,该参数可以适当增大

注意事项:从2.8后才提供scan命令用来弥补keys缺点,keys命令执行时会遍历所有键,而scan采用渐进式遍历,每次scan命令的时间复杂度是O(1)。Scan并非完美无瑕,如果在scan过程中键发生增加、修改、删除,那么新增的键可能没有遍历到,遍历出重复的键等情况

6.6 数据库管理

切换数据库:select dbIndex,Redis只用数字作为多个数据库的实现且默认配置有16个数据库;

清除数据库:flushdb/flushall,flushdb只清除当前数据库而flushall会清除所有数据库,如果当前数据库键值数量比较多时,flushdb/flushall存在阻塞Redis的可能性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值