路漫漫其修远兮
吾将上下而求索

redis学习:key操作

redis命令很多,这里先执行一遍看看都是什么作用

redis测试版本:redis-3.2.9

del命令

DEL key [key ...]:
    删除给定的一个或多个 key 。不存在的 key 会被忽略。
可用版本:
    >= 1.0.0
时间复杂度:
    O(N), N 为被删除的 key 的数量。
    删除单个字符串类型的 key ,时间复杂度为O(1)。
    删除单个列表、集合、有序集合或哈希表类型的 key ,时间复杂度为O(M), M 为以上数据结构内的元素数量。
返回值:被删除 key 的数量。
127.0.0.1:6380> set name andy
OK
127.0.0.1:6380> get name
"andy"
127.0.0.1:6380> del name
(integer) 1
127.0.0.1:6380> del name
(integer) 0
127.0.0.1:6380> exists name
(integer) 0

# 同时删除多个 key
127.0.0.1:6380> set name andy
OK
127.0.0.1:6380> set age 18
OK
127.0.0.1:6380> set website andblog.cn
OK
127.0.0.1:6380> keys *
1) "name"
2) "age"
3) "website"
127.0.0.1:6380> del name age website
(integer) 3
127.0.0.1:6380> keys *
(empty list or set)

dump命令

DUMP key
    序列化给定 key ,并返回被序列化的值,使用 RESTORE 命令可以将这个值反序列化为 Redis 键。
序列化生成的值有以下几个特点:
    它带有 64 位的校验和,用于检测错误, RESTORE 在进行反序列化之前会先检查校验和。
    值的编码格式和 RDB 文件保持一致。
    RDB 版本会被编码在序列化值当中,如果因为 Redis 的版本不同造成 RDB 格式不兼容,那么 Redis 会拒绝对这个值进行反序列化操作。
    序列化的值不包括任何生存时间信息。
可用版本:
    >= 2.6.0
时间复杂度:
    查找给定键的复杂度为 O(1) ,对键进行序列化的复杂度为 O(N*M) ,其中 N 是构成 key 的 Redis 对象的数量,而 M 则是这些对象的平均大小。
    如果序列化的对象是比较小的字符串,那么复杂度为 O(1) 。
返回值:
    如果 key 不存在,那么返回 nil 。
    否则,返回序列化之后的值。

127.0.0.1:6380> set greet "hello,world!"
OK
127.0.0.1:6380> get greet
"hello,world!"
127.0.0.1:6380> dump greet
"\x00\x0chello,world!\a\x00z:\a\xfb!\xd8#D"
127.0.0.1:6380> get greet
"hello,world!"

exists命令

EXISTS key
    检查给定 key 是否存在。
可用版本:
    >= 1.0.0
时间复杂度:
    O(1)
返回值:
    若 key 存在,返回 1 ,否则返回 0 。

127.0.0.1:6380> set name andy
OK
127.0.0.1:6380> exists name
(integer) 1
127.0.0.1:6380> exists name1
(integer) 0

expire命令

EXPIRE key seconds
    为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。
    在 Redis 中,带有生存时间的 key 被称为『易失的』(volatile)。
    生存时间可以通过使用 DEL 命令来删除整个 key 来移除,或者被 SET 和 GETSET 命令覆写(overwrite),这意味着,如果一个命令只是修改(alter)一
    个带生存时间的 key 的值而不是用一个新的 key 值来代替(replace)它的话,那么生存时间不会被改变。
    比如说,对一个 key 执行 INCR 命令,对一个列表进行 LPUSH 命令,或者对一个哈希表执行 HSET 命令,这类操作都不会修改 key 本身的生存时间。
    另一方面,如果使用 RENAME 对一个 key 进行改名,那么改名后的 key 的生存时间和改名前一样。
    RENAME 命令的另一种可能是,尝试将一个带生存时间的 key 改名成另一个带生存时间的 another_key ,这时旧的 another_key (以及它的生存时间)
    会被删除,然后旧的 key 会改名为 another_key ,因此,新的 another_key 的生存时间也和原本的 key 一样。
    使用 PERSIST 命令可以在不删除 key 的情况下,移除 key 的生存时间,让 key 重新成为一个『持久的』(persistent) key 。
更新生存时间
    可以对一个已经带有生存时间的 key 执行 EXPIRE 命令,新指定的生存时间会取代旧的生存时间。
可用版本:
    >= 1.0.0
时间复杂度:
    O(1)
返回值:
    设置成功返回 1 。
    当 key 不存在或者不能为 key 设置生存时间时,返回 0 。


127.0.0.1:6380> set cache_page "www.google.com"
OK
127.0.0.1:6380> expire cache_page 30
(integer) 1
127.0.0.1:6380> ttl cache_page
(integer) 24
127.0.0.1:6380> get cache_page
"www.google.com"

此时查看info信息,会发现expires值为1,表示有一个有过期时间但是没有过期的key
# Keyspace
db0:keys=3,expires=1,avg_ttl=220927

127.0.0.1:6380> ttl cache_page
(integer) 3
127.0.0.1:6380> ttl cache_page
(integer) 0
127.0.0.1:6380> ttl cache_page
(integer) -2
127.0.0.1:6380> ttl cache_page
(integer) -2

127.0.0.1:6380> get cache_page
(nil)

此时查看info信息,会发现key被删除,只剩下两个key,也没有有过期时间的key存在
# Keyspace
db0:keys=2,expires=0,avg_ttl=220927

重新设置ttl值
127.0.0.1:6380> ttl cache_page
(integer) 15
127.0.0.1:6380> expire cache_page 300
(integer) 1

对key进行rename后,ttl值不受rename改变,继续减少
127.0.0.1:6380> set cache_page "www.google.com"
OK
127.0.0.1:6380> expire cache_page 300
(integer) 1
127.0.0.1:6380> ttl cache_pag
(integer) -2
127.0.0.1:6380> ttl cache_page
(integer) 290
127.0.0.1:6380> rename cache_page cache_pages
OK
127.0.0.1:6380> ttl cache_page
(integer) -2
127.0.0.1:6380> ttl cache_pages
(integer) 271

expireat命令

EXPIREAT key timestamp
    EXPIREAT 的作用和 EXPIRE 类似,都用于为 key 设置生存时间。
    不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳(unix timestamp)。
可用版本:
    >= 1.2.0
时间复杂度:
    O(1)
返回值:
    如果生存时间设置成功,返回 1 。
    当 key 不存在或没办法设置生存时间,返回 0 。

[root@master ~]#date +%s
1503157061
    
127.0.0.1:6380> set cache_page "www.google.com"
OK
127.0.0.1:6380> expireat cache_page 1503157361
(integer) 1
127.0.0.1:6380> ttl cache_page
(integer) 276

keys命令

KEYS pattern
    查找所有符合给定模式 pattern 的 key 。globbing风格的匹配机制
    KEYS * 匹配数据库中所有 key 。
    KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
    KEYS h*llo 匹配 hllo 和 heeeeello 等。
    KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo 。
    特殊符号用 \ 隔开
可用版本:
    >= 1.0.0
时间复杂度:
    O(N), N 为数据库中 key 的数量。
返回值:
    符合给定模式的 key 列表。

migrate命令

MIGRATE host port key destination-db timeout [COPY] [REPLACE]
    将 key 原子性地从当前实例传送到目标实例的指定数据库上,一旦传送成功, key 保证会出现在目标实例上,而当前实例上的 key 会被删除。
    这个命令是一个原子操作,它在执行的时候会阻塞进行迁移的两个实例,直到以下任意结果发生:迁移成功,迁移失败,等待超时。
    命令的内部实现是这样的:它在当前实例对给定 key 执行 DUMP 命令 ,将它序列化,然后传送到目标实例,目标实例再使用 RESTORE 对数据进
    行反序列化,并将反序列化所得的数据添加到数据库中;当前实例就像目标实例的客户端那样,只要看到 RESTORE 命令返回 OK ,它就会调用 DEL 删除自己数据库上的 key 。
    timeout 参数以毫秒为格式,指定当前实例和目标实例进行沟通的最大间隔时间。这说明操作并不一定要在 timeout 毫秒内完成,只是说数据传送的时间不能超过这个 timeout 数。
    MIGRATE 命令需要在给定的时间规定内完成 IO 操作。如果在传送数据时发生 IO 错误,或者达到了超时时间,那么命令会停止执行,并返回一个特殊的错误: IOERR 。
当 IOERR 出现时,有以下两种可能:
    key 可能存在于两个实例
    key 可能只存在于当前实例
    唯一不可能发生的情况就是丢失 key ,因此,如果一个客户端执行 MIGRATE 命令,并且不幸遇上 IOERR 错误,那么这个客户端唯一要做的就是
    检查自己数据库上的 key 是否已经被正确地删除。
    如果有其他错误发生,那么 MIGRATE 保证 key 只会出现在当前实例中。(当然,目标实例的给定数据库上可能有和 key 同名的键,不过这和 MIGRATE 命令没有关系)。
可选项:
    COPY :不移除源实例上的 key 。
    REPLACE :替换目标实例上已存在的 key 。
可用版本:
    >= 2.6.0
时间复杂度:
    这个命令在源实例上实际执行 DUMP 命令和 DEL 命令,在目标实例执行 RESTORE 命令,查看以上命令的文档可以看到详细的复杂度说明。
    key 数据在两个实例之间传输的复杂度为 O(N) 。
返回值:
    迁移成功时返回 OK ,否则返回相应的错误。


重新启动一个redis-6390,这里是发送到6390的db0上面,超时时间1s
127.0.0.1:6380> set cache_page "www.google.com"
OK
127.0.0.1:6380> migrate 127.0.0.1 6390 cache_page 0 1000
OK
127.0.0.1:6380> keys *
(empty list or set)

move命令

MOVE key db
    将当前数据库的 key 移动到给定的数据库 db 当中。
    如果当前数据库(源数据库)和给定数据库(目标数据库)有相同名字的给定 key ,或者 key 不存在于当前数据库,那么 MOVE 没有任何效果。
    因此,也可以利用这一特性,将 MOVE 当作锁(locking)原语(primitive)。
可用版本:
    >= 1.0.0
时间复杂度:
    O(1)
返回值:
    移动成功返回 1 ,失败则返回 0 。



127.0.0.1:6380> select 0
OK
127.0.0.1:6380> set name andy
OK
127.0.0.1:6380> move name 1
(integer) 1
127.0.0.1:6380> keys *
(empty list or set)
127.0.0.1:6380> select 1
OK
127.0.0.1:6380[1]> keys *
1) "name"
127.0.0.1:6380[1]> get name
"andy"

当两个库中有相同的key名字,移动会失败
127.0.0.1:6380[1]> select 0
OK
127.0.0.1:6380> set name bob
OK
127.0.0.1:6380> move name 1
(integer) 0
127.0.0.1:6380> get name
"bob"
127.0.0.1:6380> select 1
OK
127.0.0.1:6380[1]> get name
"andy"

此时两个库中各有一个key,执行info命令
# Keyspace
db0:keys=1,expires=0,avg_ttl=0
db1:keys=1,expires=0,avg_ttl=0

persist命令

PERSIST key
    移除给定 key 的生存时间,将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )。
可用版本:
    >= 2.2.0
时间复杂度:
    O(1)
返回值:
    当生存时间移除成功时,返回 1 .
    如果 key 不存在或 key 没有设置生存时间,返回 0 。

127.0.0.1:6380> keys *
1) "name"
127.0.0.1:6380> expire name 300
(integer) 1
127.0.0.1:6380> ttl name
(integer) 297
127.0.0.1:6380> persist name
(integer) 1
127.0.0.1:6380> ttl name
(integer) -1

pexpire命令

PEXPIRE key milliseconds
    这个命令和 EXPIRE 命令的作用类似,但是它以毫秒为单位设置 key 的生存时间,而不像 EXPIRE 命令那样,以秒为单位。
可用版本:
    >= 2.6.0
时间复杂度:
    O(1)
返回值:
    设置成功,返回 1
    key 不存在或设置失败,返回 0

过期时间:1.5s
127.0.0.1:6380> pexpire name 1500
(integer) 1

pexpireat命令

PEXPIREAT key milliseconds-timestamp
    这个命令和 EXPIREAT 命令类似,但它以毫秒为单位设置 key 的过期 unix 时间戳,而不是像 EXPIREAT 那样,以秒为单位。
可用版本:
    >= 2.6.0
时间复杂度:
    O(1)
返回值:
    如果生存时间设置成功,返回 1 。
    当 key 不存在或没办法设置生存时间时,返回 0 。(查看 EXPIRE 命令获取更多信息)

randomkey命令

RANDOMKEY
    从当前数据库中随机返回(不删除)一个 key 。
可用版本:
    >= 1.0.0
时间复杂度:
    O(1)
返回值:
    当数据库不为空时,返回一个 key 。
    当数据库为空时,返回 nil 。

redis> MSET fruit "apple" drink "beer" food "cookies"   # 设置多个 key
OK

redis> RANDOMKEY
"fruit"

redis> RANDOMKEY
"food"

redis> KEYS *    # 查看数据库内所有key,证明 RANDOMKEY 并不删除 key
1) "food"
2) "drink"
3) "fruit"

rename命令

RENAME key newkey
    将 key 改名为 newkey 。
    当 key 和 newkey 相同,或者 key 不存在时,返回一个错误。
    当 newkey 已经存在时, RENAME 命令将覆盖旧值。
可用版本:
    >= 1.0.0
时间复杂度:
    O(1)
返回值:
    改名成功时提示 OK ,失败时候返回一个错误。



当且仅当 newkey 不存在时,将 key 改名为 newkey 。
    当 key 不存在时,返回一个错误。
可用版本:
    >= 1.0.0
时间复杂度:
    O(1)
返回值:
    修改成功时,返回 1 。
    如果 newkey 已经存在,返回 0 。

restore命令

RESTORE key ttl serialized-value [REPLACE]
    反序列化给定的序列化值,并将它和给定的 key 关联。
    参数 ttl 以毫秒为单位为 key 设置生存时间;如果 ttl 为 0 ,那么不设置生存时间。
    RESTORE 在执行反序列化之前会先对序列化值的 RDB 版本和数据校验和进行检查,如果 RDB 
    版本不相同或者数据不完整的话,那么 RESTORE 会拒绝进行反序列化,并返回一个错误。
    如果键 key 已经存在, 并且给定了 REPLACE 选项, 那么使用反序列化得出的值来代替键 key 原有的值;
    相反地, 如果键 key 已经存在, 但是没有给定 REPLACE 选项, 那么命令返回一个错误。
可用版本:
    >= 2.6.0
时间复杂度:
    查找给定键的复杂度为 O(1) ,对键进行反序列化的复杂度为 O(N*M) ,其中 N 是构成 key 的 Redis 对象的数量,而 M 则是这些对象的平均大小。
    有序集合(sorted set)的反序列化复杂度为 O(N*M*log(N)) ,因为有序集合每次插入的复杂度为 O(log(N)) 。
    如果反序列化的对象是比较小的字符串,那么复杂度为 O(1) 。
返回值:
    如果反序列化成功那么返回 OK ,否则返回一个错误。

127.0.0.1:6380> set greet "hello,world!"
OK
127.0.0.1:6380> dump greet
"\x00\x0chello,world!\a\x00z:\a\xfb!\xd8#D"

127.0.0.1:6380> restore hello 0 "\x00\x0chello,world!\a\x00z:\a\xfb!\xd8#D"
OK
127.0.0.1:6380> keys *
1) "hello"
2) "greet"
127.0.0.1:6380> get hello
"hello,world!"

ttl命令

TTL key
    以秒为单位,返回给定 key 的剩余生存时间(TTL, time to live)。
可用版本:
    >= 1.0.0
时间复杂度:
    O(1)
返回值:
    当 key 不存在时,返回 -2 。
    当 key 存在但没有设置剩余生存时间时,返回 -1 。
    否则,以秒为单位,返回 key 的剩余生存时间。

type命令

TYPE key
    返回 key 所储存的值的类型。
可用版本:
    >= 1.0.0
时间复杂度:
    O(1)
返回值:
    none (key不存在)
    string (字符串)
    list (列表)
    set (集合)
    zset (有序集)
    hash (哈希表)

127.0.0.1:6380> keys *
1) "hello"
2) "greet"
127.0.0.1:6380> type greet
string
127.0.0.1:6380> lpush book math
(integer) 1
127.0.0.1:6380> type book
list
127.0.0.1:6380> sadd pat 'dog'
(integer) 1
127.0.0.1:6380> type pat
set

scan命令

SCAN cursor [MATCH pattern] [COUNT count]
    SCAN 命令及其相关的 SSCAN 命令、 HSCAN 命令和 ZSCAN 命令都用于增量地迭代(incrementally iterate)一集元素(a collection of elements):

    SCAN 命令用于迭代当前数据库中的数据库键。
    SSCAN 命令用于迭代集合键中的元素。
    HSCAN 命令用于迭代哈希键中的键值对。
    ZSCAN 命令用于迭代有序集合中的元素(包括元素成员和元素分值)。
    以上列出的四个命令都支持增量式迭代, 它们每次执行都只会返回少量元素, 所以这些命令可以用于生产环境, 而不会出现像 KEYS 命令、 
    SMEMBERS 命令带来的问题 —— 当 KEYS 命令被用于处理一个大的数据库时, 又或者 SMEMBERS 命令被用于处理一个大的集合键时, 它们可能会阻塞服务器达数秒之久。

    不过, 增量式迭代命令也不是没有缺点的: 举个例子, 使用 SMEMBERS 命令可以返回集合键当前包含的所有元素, 但是对于 SCAN 这类增
    量式迭代命令来说, 因为在对键进行增量式迭代的过程中, 键可能会被修改, 所以增量式迭代命令只能对被返回的元素提供有限的保证 
    (offer limited guarantees about the returned elements)。

    因为 SCAN 、 SSCAN 、 HSCAN 和 ZSCAN 四个命令的工作方式都非常相似, 所以这个文档会一并介绍这四个命令, 但是要记住:
    SSCAN 命令、 HSCAN 命令和 ZSCAN 命令的第一个参数总是一个数据库键。
    而 SCAN 命令则不需要在第一个参数提供任何数据库键 —— 因为它迭代的是当前数据库中的所有数据库键。

SCAN 命令是一个基于游标的迭代器(cursor based iterator): SCAN 命令每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代
时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。
当 SCAN 命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。
以下是一个 SCAN 命令的迭代过程示例:


127.0.0.1:6380> keys *
 1) "key3"
 2) "key16"
 3) "key17"
 4) "key18"
 5) "key2"
 6) "key11"
 7) "key10"
 8) "key14"
 9) "key20"
10) "key8"
11) "key9"
12) "key1"
13) "key13"
14) "key19"
15) "key5"
16) "key15"
17) "key4"
18) "key12"
19) "key7"
20) "key6"
127.0.0.1:6380> scan 0
1) "9"
2)  1) "key5"
    2) "key7"
    3) "key6"
    4) "key3"
    5) "key16"
    6) "key11"
    7) "key4"
    8) "key18"
    9) "key8"
   10) "key9"
   11) "key1"
   12) "key13"
127.0.0.1:6380> scan 9
1) "0"
2) 1) "key15"
   2) "key20"
   3) "key17"
   4) "key19"
   5) "key10"
   6) "key14"
   7) "key12"
   8) "key2"


在上面这个例子中, 第一次迭代使用 0 作为游标, 表示开始一次新的迭代。
第二次迭代使用的是第一次迭代时返回的游标, 也即是命令回复第一个元素的值 —— 9 。
从上面的示例可以看到, SCAN 命令的回复是一个包含两个元素的数组, 第一个数组元素是用于进行下一次迭代的新游标, 
而第二个数组元素则是一个数组, 这个数组中包含了所有被迭代的元素。
在第二次调用 SCAN 命令时, 命令返回了游标 0 , 这表示迭代已经结束, 整个数据集(collection)已经被完整遍历过了。
以 0 作为游标开始一次新的迭代, 一直调用 SCAN 命令, 直到命令返回游标 0 , 我们称这个过程为一次完整遍历(full iteration)。

增量式迭代命令并不保证每次执行都返回某个给定数量的元素。
增量式命令甚至可能会返回零个元素, 但只要命令返回的游标不是 0 , 应用程序就不应该将迭代视作结束。
不过命令返回的元素数量总是符合一定规则的, 在实际中:
对于一个大数据集来说, 增量式迭代命令每次最多可能会返回数十个元素;
而对于一个足够小的数据集来说, 如果这个数据集的底层表示为编码数据结构(encoded data structure,适用于是小集合键、
小哈希键和小有序集合键), 那么增量迭代命令将在一次调用中返回数据集中的所有元素。
最后, 用户可以通过增量式迭代命令提供的 COUNT 选项来指定每次迭代返回元素的最大值。

和 KEYS 命令一样, 增量式迭代命令也可以通过提供一个 glob 风格的模式参数, 让命令只返回和给定模式相匹配的元素, 
这一点可以通过在执行增量式迭代命令时, 通过给定 MATCH <pattern> 参数来实现。
127.0.0.1:6380> scan 0 match key1*
1) "9"
2) 1) "key16"
   2) "key11"
   3) "key18"
   4) "key1"
   5) "key13"

文档:redis命令参考

未经允许不得转载:江哥架构师笔记 » redis学习:key操作

分享到:更多 ()

评论 抢沙发

评论前必须登录!