Fork me on GitHub

redis数据结构及键命令学习

前言

前面也有几篇文章提到了redis。关于redis连接池及Jedis封装API可以看这篇文章。redis连接池及常用API封装,如果你想下载安装redis可以看这篇文章,如何安装redis和简单使用. 那么这篇文章就会说一说Redis当中数据结构和常用的一些键命令。

Key(键)

DEL

删除给定的一个或者多个key,不存在的key会被忽略。del key [key...]

时间复杂度:O(N) N为被删除的key的数量。删除单个字符串类型的key时,时间复杂度为O(1);删除单个列表、集合、有序集合或者哈希表类型的key时,时间复杂度为O(M),M为上述数据结构中的元素数量。

返回值: 被删除key的数量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# set 一个值 key=name value=chencong
127.0.0.1:6379> set name chencong
OK

# 查看redis当中所有的key
127.0.0.1:6379> keys *
1) "name"

# get redis当中key=name 的value的值
127.0.0.1:6379> get name
"chencong"

# 删除redis当中 key = name 的值 ,返回删除成功的数量
127.0.0.1:6379> del name
(integer) 1
127.0.0.1:6379>

# redis 当中已经不存在key=name的值,删除一个不存在的key 返回0
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> del name
(integer) 0
127.0.0.1:6379>

# 向redis当中存入多个<K,V>
127.0.0.1:6379> set name chencong
OK
127.0.0.1:6379> set age 20
OK
127.0.0.1:6379> set phone 110
OK

# redis当中已存在的key
127.0.0.1:6379> keys *
1) "age"
2) "name"
3) "phone"

# 同时删除多个key 返回删除成功的数量
127.0.0.1:6379> del name age phone
(integer) 3
127.0.0.1:6379>

DUMP

序列化给定的key,并且返回被序列化的值,使用RESTORE命令可以将这个值反序列化成redis的键。序列化的值不包括任何生产时间的信息。

时间复杂度:查找给定key的时间复杂度为O(1),对键key进行序列化的复杂度为O(N*M),其中N是构成key的redis对象的数量,M则是这些对象的平均大小。如果序列化的对象为较小的字符串时,那么复杂度为O(1)

返回值:如果key不存在则返回nil,否则返回序列化之后的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
127.0.0.1:6379> set name chencong
OK
127.0.0.1:6379> keys *
1) "name"
# 对key=name的键进行序列化
127.0.0.1:6379> dump name
"\x00\bchencong\b\x00\xaf\xb3.\xc0v\x8c_\a"
127.0.0.1:6379> del name
(integer) 1
127.0.0.1:6379> keys *
(empty list or set)
# 此时不存在key=name的键,对其进行序列化返回nil
127.0.0.1:6379> dump name
(nil)
127.0.0.1:6379>

RESTORE

反序列化给定的序列化值,并将其和给定的key进行关联。参数ttl以毫秒为单位设置其生存时间,如果ttl=0则不设置生存时间。

注意:RESTORE在执行反序列化之前会对序列化值的RDB版本和数据校验和进行检查,如果RDB版本不相同或者数据不完整,那么RESTORE会拒绝序列化,并返回一个错误.

时间复杂度:查找给定键的复杂度为 O(1) ,对键进行反序列化的复杂度为 O(NM) ,其中 N 是构成 key 的 Redis 对象的数量,而 M 则是这些对象的平均大小。有序集合(Sorted set)的时间复杂度为O(NM*log(N)),因为有序集合每次插入的复杂度为O(log(N))

返回值:如果反序列化成功则返回OK,否则返回一个错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
127.0.0.1:6379> set name chencong
OK
# 序列化
127.0.0.1:6379> dump name
"\x00\bchencong\b\x00\xaf\xb3.\xc0v\x8c_\a"

# 反序列化 使用的key=name 的键已经存在
127.0.0.1:6379> restore name 0 "\x00\bchencong\b\x00\xaf\xb3.\xc0v\x8c_\a"
(error) BUSYKEY Target key name already exists.

# 反序列化成功
127.0.0.1:6379> restore cc 0 "\x00\bchencong\b\x00\xaf\xb3.\xc0v\x8c_\a"
OK
127.0.0.1:6379> restore cc 0 "\x00\bchencong\b\x00\xaf\xb3.\xc0v\x8c_\a11111111"
(error) BUSYKEY Target key name already exists.
# 反序列化失败,检验序列化值进行校验
127.0.0.1:6379> restore aa 0 "\x00\bchencong\b\x00\xaf\xb3.\xc0v\x8c_\a11111111"
(error) ERR DUMP payload version or checksum are wrong
127.0.0.1:6379>

EXISTS

检查给定key是否存在

时间复杂度:O(1)

返回值:若key存在则返回1,否则返回0

1
2
3
4
5
6
7
8
127.0.0.1:6379> keys *
1) "name"
2) "cc"
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> exists age
(integer) 0
127.0.0.1:6379>

EXPIRE

为指定key设置生存时间,当key的生存时间为0时,将会被自动删除。使用rename命令对一个key进行改名,改名后的key的生存时间和改名之前一样。

更新生存时间:可以对一个已经带有生存时间的key执行expire命令,该key的生存时间为新指定的生存时间。

生存时间精确度:在 Redis 2.4 版本中,过期时间的延迟在 1 秒钟之内 —— 也即是,就算 key 已经过期,但它还是可能在过期之后一秒钟之内被访问到,而在新的 Redis 2.6 版本中,延迟被降低到 1 毫秒之内。

Redis 2.1.3 之前的不同之处:在 Redis 2.1.3 之前的版本中,修改一个带有生存时间的 key 会导致整个 key 被删除,这一行为是受当时复制(replication)层的限制而作出的,现在这一限制已经被修复。

时间复杂度:O(1)

返回值:设置成功返回1,当key不存在或者不能够为key设置生存时间(低于2.1.3版本的redis更新key的生存时间时),返回0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
127.0.0.1:6379> set name chencong
OK
# 设置key=name的生存时间为30秒
127.0.0.1:6379> expire name 30
(integer) 1
# 命令ttl 为查看当前key的生存时间
127.0.0.1:6379> ttl name
(integer) 27

# 给指定key更新生存时间
127.0.0.1:6379> expire name 10000
(integer) 1
127.0.0.1:6379> ttl name
(integer) 9997
127.0.0.1:6379>

# 当key=age的键不存在时为其指定生存时间,将返回0
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> expire age 1000
(integer) 0
127.0.0.1:6379>

# 此处使用redis版本高于2.1.3
[root@iZj1fkye8uu7o0Z src]# ./redis-cli -v
redis-cli 4.0.6
[root@iZj1fkye8uu7o0Z src]#

EXPIREAT

EXPIREAT的作用和expire类似,都是用于为key设置生存时间。不同的在于expire设置时间长度,而expireat设置的为时间戳。

时间复杂度:O(1)

返回值:如果生存时间设置成功则返回1,当key不存在或没办法设置生存时间时返回0.

1
2
3
4
5
6
7
8
127.0.0.1:6379> set name chencong
OK
# 设置key=name的生存时间 1522159200 为 2018-03-27 22:00:00 过期
127.0.0.1:6379> expireat name 1522159200
(integer) 1
127.0.0.1:6379> ttl name
(integer) 629
127.0.0.1:6379>

KEYS

查找所有符合给定规则的key

  • keys * ——匹配redis当中所有的key
  • keys h?llo ——匹配hello hallo hcllo等内容,只此一个位置不同
  • keys h*llo ——匹配hllo heeeeeeello hallo 等内容,该位置可任意字符
  • keys h[ae]llo ——匹配hallo hello 等内容,但是不匹配hillo,该位置字符从[]中取

时间复杂度:O(N),N为redis当中key的数量

返回值:返回符合给定规则的key的列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 匹配所有的key
127.0.0.1:6379> keys *
1) "name"
2) "name_set"
3) "name_list"

# 匹配key当中存在`_`的key列表
127.0.0.1:6379> keys *_*
1) "name_set"
2) "name_list"

# 匹配所有以name_开头的key
127.0.0.1:6379> keys name[_]*
1) "name_set"
2) "name_list"

#匹配所有以name开头的key
127.0.0.1:6379> keys name*
1) "name"
2) "name_set"
3) "name_list"
127.0.0.1:6379>

MIGRATE

MOVE

将当前数据库当中的key移到给定的数据库db当当中。在这里说明一下:redis默认配置当中database:16个数据库,分别是0-15.默认使用0 如果当前数据库和给定的数据库,也就是源数据库和目标数据库当中有相同的key,或者是key不存在当前数据库(源数据库)当中,那么命令MOVE是没有任何效果的

时间复杂度:O(1)

返回值:成果返回1,失败返回0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 设置一个key=name的键
127.0.0.1:6379> set name 'tom'
OK
# 选择第一个数据库,默认就是第一个(0号)数据
127.0.0.1:6379> select 0
OK

# 移动当前0号数据库当中key=name的键到目标数据(1号)
127.0.0.1:6379> move name 1
(integer) 1

# 切换到1号数据库
127.0.0.1:6379> select 1
OK
# 查看1号数据库下的所有键,可以看到key=name的键已经移动过来了
127.0.0.1:6379[1]> keys *
1) "name"

# 切换到0号数据库,可以看到这个数据库下面已经没有key=name的键了
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379>

OBJECT

PERSIST

PEXPIRE

PEXPIREAT

PTTL

以毫秒为单位返回key的生存时间,类似于ttl,但是ttl是以秒为单位

时间复杂度:O(1)

返回值

  • 当key不存在时,返回-2
  • 当key存在,但是并没有为其设置生存时间时,返回-1
  • 否则,以毫秒为单位,返回key的生存时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 首先清空所有的key
127.0.0.1:6379> flushdb
OK
# 当key=name 的键不存在时,返回-2
127.0.0.1:6379> pttl name
(integer) -2
127.0.0.1:6379> set name tom
OK

# 没有为key=name 的键设置生存时间 返回-1
127.0.0.1:6379> pttl name
(integer) -1

# 为key=name 的键设置生存时间,pexpire 单位为毫秒
127.0.0.1:6379> pexpire name 10086
(integer) 1

# 查看key=name的键的剩余生存时间
127.0.0.1:6379> pttl name
(integer) 7073
127.0.0.1:6379> pttl name
(integer) 906

# 由于key=name的键的生存时间已经过期,已被删除,已经不存在key=name的键了,返回-2
127.0.0.1:6379> pttl name
(integer) -2
127.0.0.1:6379> pttl name
(integer) -2
127.0.0.1:6379>

RANDOMKEY

RENAME

RENAMENX

TTL

以秒为单位,返回给定key的一个生存时间

时间复杂度:O(1)
返回值:

  • 当key不存在时,返回-2
  • 当key存在但是没有设置生存时间时,返回-1
  • 否则,以秒为单位,返回key所剩的生存时间
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    # 清空redis的所有缓存
    127.0.0.1:6379> flushdb
    OK
    # key不存在时,返回-2
    127.0.0.1:6379> ttl name
    (integer) -2
    127.0.0.1:6379> set name tom
    OK
    # key存在,但是没有设置生存时间时,返回-1
    127.0.0.1:6379> ttl name
    (integer) -1
    # 对key进行设置生存时间
    127.0.0.1:6379> expire name 1000
    (integer) 1
    # key存在且有生存时间,返回剩余生存时间,单位:秒
    127.0.0.1:6379> ttl name
    (integer) 997
    127.0.0.1:6379>

TYPE

返回key所存储的值的类型

时间复杂度:O(1)
返回值:

  • none——key不存在情况
  • string——字符创
  • list——列表
  • set——集合
  • zset——有序集合
  • hash——哈希表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
127.0.0.1:6379> keys *
(empty list or set)

# 设置key=name的字符串
127.0.0.1:6379> set name tom
OK
127.0.0.1:6379> type name
string

# 设置key=name_list的list集合
127.0.0.1:6379> lpush name_list "tom"
(integer) 1
127.0.0.1:6379> type name_list
list

# 设置key=name_set的set集合
127.0.0.1:6379> sadd name_set "dog"
(integer) 1
127.0.0.1:6379> type name_set
set
127.0.0.1:6379>

SCAN

String(字符串)

Hash(哈希表)

List(列表)

Set(集合)

SortedSet(有序集合)

联系

聪聪的独立博客 ,一个喜欢技术,喜欢钻研的95后。如果你看到这篇文章,千里之外,我在等你联系。

坚持原创技术分享,您的支持将鼓励我继续创作!