前文已经提及过Redis中对于键值对操作的一些命令,如DEL、EXPIRE / PEXPIRE、TTL / PTTL以及EXISTS。今天我们继续介绍Redis中对键值对操作的相关命令。
TYPE命令用于获取指定键值对的类型,返回的值有string、list、set、zset、hash以及stream。当键值对不存在时返回none。
TYPE keyRENAME命令用于将指定键名重命名,并在键值对不存在时返回一个错误。若新的键名已存在,将会覆盖旧值(无论旧值是否和新值是同一类型)。当Redis版本小于等于3.2.0时,若新键名与旧键名相同将返回错误。
RENAME key newkey若原键key有关联过期时间,则无论新键是否关联有过期时间,都将被覆盖。
当新键名已经存在时,执行RENAME命令时会先隐式地调用DEL操作删除对应的键值对,再执行重命名的操作。
RENAMENX命令与RENAME相似,二者的区别为RENAMENX仅在新键名不存在的情况下才完成重命名的操作。若新键名newkey已存在将会返回0,否则在正确完成重命名操作后返回0。同样,当原键名不存在时将返回错误。
RENAMENX key newkey当键名key1和key2都且类型不同时,使用RENAME也将覆盖key2的值:
redis> SET key1 "value1" OK redis> LPUSH key2 "value2" (integer) 1 redis> RENAME key1 key2 OK redis> TYPE key2 string使用RENAME重命名关联过期时间的键:
# 新键继承原键的过期时间 redis> SET key1 EX 100 OK redis> RENAME key1 key2 OK redis> TTL key2 (integer) 98 # 新键原先的过期时间被覆盖 redis> SET key3 EX 300 OK redis> RENAME key2 key3 OK redis> TTL key3 (integer) 92使用RENAMENX命令:
redis> SET key1 "value" OK redis> RENAMENX key1 key2 (integer) 1 # 新键名key3已存在的情况下 redis> SET key3 "value" OK redis> RENAMENX key2 key3 (integer) 0PERSIST命令用于移除指定键的过期时间。
PERSIST keyEXPIREAT命令与之前介绍过的EXPIRE及PEXPIRE命令类似,用于设置已存在的键值对的过期时间。与前两个命令不同的是,EXPIREAT和PEXPIREAT接受的参数是以秒为单位的Unix时间戳。当过期时间被成功设置,该命令将返回1,反之返回0。
EXPIREAT key timestamp与EXPIRE相同,若指定的过期时间戳早于当前时间,该键将被删除。
PEXPIREAT与EXPIREAT相同,它通过传递的以毫秒为单位的Unix时间戳设置过期的时间。
EXPIREAT key milliseconds-timestamp通过PEXPIREAT设置毫秒为单位的过期时间:
# 毫秒为单位的时间戳1577836900000 (2020-01-01T00:01:40) redis> PEXPIREAT greeting 1577836900000 (integer) 1 redis> PTTL greeting (integer) 98805 redis> TTL greeting (integer) 98KEYS用于获取所有符合给定模式(pattern)要求的键。
KEYS pattern由于KEYS会扫描当前数据库中所有的键值对,在生产环境中应当尽量避免使用该命令。如果需要相应的功能,可以使用下面将介绍的SCAN命令替代,或者另外使用set保存可能需要访问的键名。
KEYS命令支持glob-style的模式,包括有:
?代表匹配任意单个字符,例如h?llo匹配hello、hallo等;*代表匹配0个或多个任意字符,例如h*llo匹配hello、hllllllo等;[characters]匹配一个方括号内的字符,例如h[ae]llo匹配hello以及hallo;[^character]匹配一个非括号内^符号后的字符,例如h[^e]llo匹配hallo、hbllo等,但不匹配hello;[character-character]匹配一个方括号内两个字符范围内的所有字符,例如h[a-e]llo匹配hallo、hbllo、hcllo、hdllo以及hello。若模式内需要保护以上提到的?、*、[、]、^、-字符,可以使用\进行转义。
SCAN命令用于增量式迭代元素集合,与其相似的还有SSCAN、HSCAN以及ZSCAN。SCAN用于迭代当前数据库中的所有键,其它几个分别是对集合、哈希、有序集合类型进行迭代,我们将在后续的文章中对其它几个命令进行介绍。
增量迭代的命令每次执行只会返回少数结果,不同于KEYS命令返回所有的结果(可能导致服务阻塞)。但是使用增量式迭代的过程中可能会发现键被修改的情况,它只能对返回的结果提供有限的保证。
SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]SCAN命令是一个基于游标cursor的迭代器,每次执行后将会返回一个新的游标,以作为下一轮迭代的游标参数。一次的迭代以游标0为开始,并在返回游标0时结束,称之为一次完整的迭代。若在迭代的途中使用了错误的游标,命令执行的结果将不能保证正确,但不会对服务器本身造成影响。
SCAN命令将会返回一个包含两个值的数组,数组的第一个值为下一轮迭代的新游标,第二个元素为一个数组,其中包含本轮迭代遍历到的元素。
对于SCAN命令,以及上面提到的SCAN族中的其它命令,只能在完整迭代下提供保证对于完整遍历开始至结束期间都存在的所有元素,必然在某次迭代中被返回;而对于在完整迭代中不存在的元素(如迭代开始前被删除或迭代结束后被添加的元素),必然不会被返回。
在一次完整的迭代中,一个元素可能会被多次返回,需要客户端自己处理重复的情况。在迭代中若存在元素并非一直存在(中途添加或删除),则不能确定是否会被返回,这是一个未定义的行为。增量迭代的算法只能保证数据集在有界的情况下停止,若在迭代的途中不断添加新的数据,迭代可能将用于不会结束。
SCAN命令不能保证每次迭代返回的元素数量,返回0个元素也是被允许的,只要是返回的游标不为0迭代都仍未结束。对于一个较大的数据集,每次迭代可能会返回数十个元素;而对于一个较小的数据集,一次迭代可能会返回全部的元素。另外,可以通过COUNT参数设置每次迭代返回元素的最大值。
Redis可同时正确处理来自多个客户端的迭代请求,迭代中的游标记录包含了迭代的所有状态,服务器无须另外记录迭代的状态。同时,客户端也可在任意时刻停止迭代,且不会对服务器造成影响。
当当前数据库为空时使用SCAN命令:
redis> SCAN 0 1) "0" 2) (empty array)使用MATCH参数:
redis> MSET firstname John lastname Doe age 25 OK redis> SCAN 0 MATCH *name* 1) "0" 2) 1) "firstname" 2) "lastname"RANDOMKEY命令用于随机取出一个存在的键。若当前数据库中不存在任何键,则返回nil。
RANDOMKEYUNLINK命令与DEL命令相似,它被用于删除指定键名中存在的键,并忽略不存在的键。此命令与DEL命令的区别是,它在另一个线程中执行删除的操作。其执行删除操作时会先将需要删除的键从键空间中移除,再异步地释放资源。UNLINK命令是非阻塞的删除操作,而DEL命令是阻塞的删除操作,在一些较复杂的情况下可采用UNLINK命令避免Redis阻塞(在6.0版本前Redis是单线程处理的)。
UNLINK key [key ...]UNLINK命令与DEL命令相同,都将返回删除键的个数。
本文中介绍了Redis中对键进行操作的相关命令,对于Redis文档中Keys类别下的诸如DUMP、MOVE、OBJECT等命令,将会在后续介绍Redis的迁移、服务、调试等相关命令时会提及,本文中便暂时不深入介绍。
欢迎大家关注我的公众号“风纸”,或是扫下面的二维码关注👇