DEL key [key …]
起始版本:1.0.0
时间复杂度:O(N) 将要被删除的key的数量,当删除的key是字符串以外的复杂数据类型时比如List,Set,Hash删除这个key的时间复杂度是O(1)。
删除指定的一批keys,如果删除中的某些key不存在,则直接忽略。
返回值
integer-reply: 被删除的keys的数量
例子
redis> SET key1 "Hello"
OK
redis> SET key2 "World"
OK
redis> DEL key1 key2 key3
(integer) 2
redis>
DUMP key
起始版本:2.6.0
时间复杂度:O(1) to access the key and additional O(NM) to serialized it, where N is the number of Redis objects composing the value and M their average size. For small string values the time complexity is thus O(1)+O(1M) where M is small, so simply O(1).
序列化给定 key ,并返回被序列化的值,使用 RESTORE 命令可以将这个值反序列化为 Redis 键。
序列化生成的值有以下几个特点:
- 它带有 64 位的校验和,用于检测错误,RESTORE 在进行反序列化之前会先检查校验和。
- 值的编码格式和 RDB 文件保持一致。
- RDB 版本会被编码在序列化值当中,如果因为 Redis 的版本不同造成 RDB 格式不兼容,那么 Redis 会拒绝对这个值进行反序列化操作。
返回值
如果 key 不存在,那么返回 nil。
否则,返回序列化之后的值。
例子
redis> SET mykey 10
OK
redis> DUMP mykey
"\u0000\xC0\n\u0006\u0000\xF8r?\xC5\xFB\xFB_("
redis>
EXISTS key [key …]
起始版本:1.0.0
时间复杂度:O(1)
返回key是否存在。
返回值
integer-reply,如下的整数结果
- 1 如果key存在
-
例子
redis> SET key1 "Hello"
OK
redis> EXISTS key1
(integer) 1
redis> EXISTS key2
(integer) 0
redis>
EXPIRE key seconds
起始版本:1.0.0
时间复杂度:O(1)
设置key
的过期时间,超过时间后,将会自动删除该key
。在Redis的术语中一个key
的相关超时是不确定的。
超时后只有对key
执行DEL命令或者SET命令或者GETSET时才会清除。 这意味着,从概念上讲所有改变key
的值的操作都会使他清除。 例如,INCR递增key的值,执行LPUSH操作,或者用HSET改变hash的field
所有这些操作都会触发删除动作。
使用PERSIST命令可以清除超时,使其变成一个永久的key
。
如果key
被RENAME命令修改,相关的超时时间会转移到新key
上面。
如果key
被RENAME命令修改,比如原来就存在Key_A
,然后调用RENAME Key_B Key_A
命令,这时不管原来Key_A
是永久的还是设置为超时的,都会由Key_B
的有效期状态覆盖。刷新过期时间
对已经有过期时间的
key
执行EXPIRE
操作,将会更新它的过期时间。有很多应用有这种业务场景,例如记录会话的session。返回值
integer-reply, 具体的:
1
如果成功设置过期时间。0
如果key
不存在或者不能设置过期时间。例子
redis> SET mykey "Hello"
OK
redis> EXPIRE mykey 10
(integer) 1
redis> TTL mykey
(integer) 10
redis> SET mykey "Hello World"
OK
redis> TTL mykey
(integer) -1
redis>
案例: Navigation session
想象一下,你有一个网络服务器,你对用户最近访问的N个网页感兴趣,每一个相邻的页面设置超时时间为60秒。在概念上你为这些网页添加Navigation session,如果你的用户,可能包含有趣的信息,他或她正在寻找什么样的产品,你可以推荐相关产品。
你可以使用下面的策略模型,使用这种模式:每次用户浏览网页调用下面的命令:
如果用户60秒没有操作,这个key将会被删除,不到60秒的话,后续网页将会被继续记录。MULTI
RPUSH pagewviews.user:<userid> http://.....
EXPIRE pagewviews.user:<userid> 60
EXEC
这个案例很容易用INCR代替RPUSH附录: Redis 过期时间
Keys的过期时间
通常Redis keys创建时没有设置相关过期时间。他们会一直存在,除非使用显示的命令移除,例如,使用DEL命令。EXPIRE
一类命令能关联到一个有额外内存开销的key。当key执行过期操作时,Redis会确保按照规定时间删除他们。
key的过期时间和永久有效性可以通过EXPIRE
和PERSIST命令(或者其他相关命令)来进行更新或者删除过期时间。过期精度
在 Redis 2.4 及以前版本,过期期时间可能不是十分准确,有0-1秒的误差。
从 Redis 2.6 起,过期时间误差缩小到0-1毫秒。过期和持久
Keys的过期时间使用Unix时间戳存储(从Redis 2.6开始以毫秒为单位)。这意味着即使Redis实例不可用,时间也是一直在流逝的。
要想过期的工作处理好,计算机必须采用稳定的时间。 如果你将RDB文件在两台时钟不同步的电脑间同步,有趣的事会发生(所有的 keys装载时就会过期)。
即使正在运行的实例也会检查计算机的时钟,例如如果你设置了一个key的有效期是1000秒,然后设置你的计算机时间为未来2000秒,这时key会立即失效,而不是等1000秒之后。Redis如何淘汰过期的keys
Redis keys过期有两种方式:被动和主动方式。
当一些客户端尝试访问它时,key会被发现并主动的过期。
当然,这样是不够的,因为有些过期的keys,永远不会访问他们。 无论如何,这些keys应该过期,所以定时随机测试设置keys的过期时间。所有这些过期的keys将会从密钥空间删除。
具体就是Redis每秒10次做的事情:
- 测试随机的20个keys进行相关过期检测。
- 删除所有已经过期的keys。
- 如果有多于25%的keys过期,重复步奏1.
这是一个平凡的概率算法,基本上的假设是,我们的样本是这个密钥控件,并且我们不断重复过期检测,直到过期的keys的百分百低于25%,这意味着,在任何给定的时刻,最多会清除1/4的过期keys。
在复制AOF文件时如何处理过期
为了获得正确的行为而不牺牲一致性,当一个key过期,DEL
将会随着AOF文字一起合成到所有附加的slaves。在master实例中,这种方法是集中的,并且不存在一致性错误的机会。
然而,当slaves连接到master时,不会独立过期keys(会等到master执行DEL命令),他们任然会在数据集里面存在,所以当slave当选为master时淘汰keys会独立执行,然后成为master。
EXPIREAT key timestamp
起始版本:1.2.0
时间复杂度:O(1)
EXPIREAT 的作用和 EXPIRE类似,都用于为 key 设置生存时间。不同在于 EXPIREAT 命令接受的时间参数是 UNIX 时间戳 Unix timestamp 。
返回值
integer-reply,如下的整数结果
1 如果设置了过期时间 0 如果没有设置过期时间,或者不能设置过期时间
例子
redis> SET mykey "Hello"
OK
redis> EXISTS mykey
(integer) 1
redis> EXPIREAT mykey 1293840000
(integer) 1
redis> EXISTS mykey
(integer) 0
redis>
KEYS pattern
起始版本:1.0.0
时间复杂度:O(N) with N being the number of keys in the database, under the assumption that the key names in the database and the given pattern have limited length.
查找所有符合给定模式pattern(正则表达式)的 key 。
时间复杂度为O(N),N为数据库里面key的数量。
例如,Redis在一个有1百万个key的数据库里面执行一次查询需要的时间是40毫秒 。
警告: KEYS
的速度非常快,但在一个大的数据库中使用它仍然可能造成性能问题,如果你需要从一个数据集中查找特定的 KEYS
, 你最好还是用 Redis 的集合结构 SETS 来代替。
支持的正则表达模式:
h?llo
匹配hello
,hallo
和hxllo
h*llo
匹配hllo
和heeeello
h[ae]llo
匹配hello
和hallo,
但是不匹配hillo
h[^e]llo
匹配hallo
,hbllo
, … 但是不匹配hello
h[a-b]llo
匹配hallo
和hbllo
如果你想取消字符的特殊匹配(正则表达式,可以在它的前面加\
。
返回值
array-reply: 所有符合条件的key
例子
redis> MSET one 1 two 2 three 3 four 4
OK
redis> KEYS *o*
1) "four"
2) "one"
3) "two"
redis> KEYS t??
1) "two"
redis> KEYS *
1) "four"
2) "three"
3) "one"
4) "two"
redis>
MIGRATE host port key destination-db timeout [COPY] [REPLACE]
起始版本:2.6.0
时间复杂度:This command actually executes a DUMP+DEL in the source instance, and a RESTORE in the target instance. See the pages of these commands for time complexity. Also an O(N) data transfer between the two instances is performed.
将 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 命令没有关系)。
返回值
simple-string-reply: 迁移成功时返回 OK ,否则返回相应的错误。
MOVE key db
起始版本:1.0.0
时间复杂度:O(1)
将当前数据库的 key 移动到给定的数据库 db 当中。
如果当前数据库(源数据库)和给定数据库(目标数据库)有相同名字的给定 key ,或者 key 不存在于当前数据库,那么 MOVE 没有任何效果。
因此,也可以利用这一特性,将 MOVE
当作锁(locking)原语(primitive)。
返回值
- 移动成功返回 1
-
OBJECT subcommand [arguments [arguments …]]
起始版本:2.2.3
时间复杂度:O(1) for all the currently implemented subcommands.OBJECT
命令可以在内部调试(debugging)给出keys的内部对象,它用于检查或者了解你的keys是否用到了特殊编码 的数据类型来存储空间z。 当redis作为缓存使用的时候,你的应用也可能用到这些由OBJECT
命令提供的信息来决定应用层的key的驱逐策略(eviction policies)OBJECT
支持多个子命令: OBJECT REFCOUNT 该命令主要用于调试(debugging),它能够返回指定key所对应value被引用的次数.
- OBJECT ENCODING 该命令返回指定key对应value所使用的内部表示(representation)(译者注:也可以理解为数据的压缩方式).
- OBJECT IDLETIME 该命令返回指定key对应的value自被存储之后空闲的时间,以秒为单位(没有读写操作的请求) ,这个值返回以10秒为单位的秒级别时间,这一点可能在以后的实现中改善
对象可以用多种方式编码:
- 字符串可以被编码为 raw (常规字符串) 或者int (用字符串表示64位无符号整数这种编码方式是为了节省空间).
- 列表类型可以被编码为ziplist 或者 linkedlist. ziplist 是为了节省较小的列表空间而设计一种特殊编码方式.
- 集合被编码为 intset 或者 hashtable. intset 是为了存储数字的较小集合而设计的一种特殊编码方式.
- 哈希表可以被编码为 zipmap 或者hashtable. zipmap 是专为了较小的哈希表而设计的一种特殊编码方式
- 有序集合被编码为ziplist 或者 skiplist 格式. ziplist可以表示较小的有序集合, skiplist 表示任意大小多的有序集合.
一旦你做了一个操作让redis无法再使用那些节省空间的编码方式,它将自动将那些特殊的编码类型转换为普通的编码类型.
返回值
不同的子命令会对应不同的返回值.
- refcount 和 idletime 返回整数.
- encoding 返回编码类型.
如果你尝试检查的参数缺失,将会返回为空
#例子
redis> lpush mylist "Hello World"
(integer) 4
redis> object refcount mylist
(integer) 1
redis> object encoding mylist
"ziplist"
redis> object idletime mylist
(integer) 10
接下来的例子你可以看到redis一旦不能够实用节省空间的编码类型时编码方式的改变.
redis> set foo 1000
OK
redis> object encoding foo
"int"
redis> append foo bar
(integer) 7
redis> get foo
"1000bar"
redis> object encoding foo
"raw"
PERSIST key
起始版本:2.2.0
时间复杂度:O(1)
移除给定key的生存时间,将这个 key 从『易失的』(带生存时间 key )转换成『持久的』(一个不带生存时间、永不过期的 key )。
返回值
integer-reply, 只有以下两种值:
- 当生存时间移除成功时,返回 1 .
如果 key 不存在或 key 没有设置生存时间,返回 0 .
例子
redis> SET mykey "Hello"
OK
redis> EXPIRE mykey 10
(integer) 1
redis> TTL mykey
(integer) 10
redis> PERSIST mykey
(integer) 1
redis> TTL mykey
(integer) -1
redis>
PEXPIRE key milliseconds
起始版本:2.6.0
时间复杂度:O(1)
这个命令和EXPIRE命令的作用类似,但是它以毫秒为单位设置 key 的生存时间,而不像EXPIRE命令那样,以秒为单位。返回值
integer-reply, 只有以下两种值:
设置成功,返回 1
- key 不存在或设置失败,返回 0
例子
redis> SET mykey "Hello"
OK
redis> PEXPIRE mykey 1500
(integer) 1
redis> TTL mykey
(integer) 1
redis> PTTL mykey
(integer) 1499
redis>