本章将按照单个键,遍历键,数据库管理三个维度对一些通用命令进行介绍.
1. 单键管理
针对单个键的命令,前面几节已经介绍过一部分了,例如type
,del
,object
,exists
,expire
等,下面介绍几个重要命令.
1) 键重命名
rename key newkey
例如一个键名为node
值为jedis
:
127.0.0.1:6379> get node
"jedis"
下面操作将键node
改为java
:
127.0.0.1:6379> rename node java
OK
127.0.0.1:6379> get java
"jedis"
如果在rename
之前,键java
已经存在,那么它的值也将被覆盖.
为了防止被强行rename
,redis
提供了renamenx
命令,确保只有newkey
不存在时候才被修改.
在使用重命名时,有两点需要注意:
由于重命名键期间会执行del命令删除旧的键,如果键对应的值比较大,会存在阻塞
redis
的可能性,这点不要忽视.如果
rename
和renamenx
中的key
和newkey
如果是相同的,在redis 3.2
和之前版本返回结果会不同.
在redis 3.2
会返回OK:
127.0.0.1:6379> rename key key
OK
在redis 3.2
之前会提示错误:
127.0.0.1:6379> rename key key
(error) ERR source and destination objects are the same
2) 随机返回一个键
randomkey
例如,当数据库中有1000个键值对,randomkey
命令会随机从中挑选一个.
127.0.0.1:6379> dbsize
1000
127.0.0.1:6379> randomkey
hello
127.0.0.1:6379> randomkey
java
3) 键过期
除了expire
,ttl
命令以外,redis
还提供了expireat
,pexpire
,pttl
,persist
等一系列命令,下面分别进行说明:
expire key seconds
:键在seconds
秒后过期删除.pexpireat key timestamp
:健在秒级时间戳timestamp
后过期删除.
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> expire hello 10
(integer) 1
127.0.0.1:6379> ttl hello
(integer) 7 # 还剩7秒
ttl
命令和pttl
都可以查询键的剩余时间,但是pttl
的时间精度更高可以达到毫秒级.有三种返回值:
大于等于
0
的整数:键剩余的时间(ttl
单位是秒,pttl
单位是毫秒.)-1
:键没有设置过期时间.-2
:键不存在.
expirereat
命令可以设置键的秒级时间戳,例如如果需要将键hello
在2017-05-02 00:00:00
过期.
初次之外,redis 2.6
版本后提供了毫秒级的过期方案.
pexpire key milliseconds
:键在milliseconds
毫秒后过期.pexpireat key milliseconds
:健在毫秒级时间戳timestamp
后过期删除.
但无论是使用过期时间还是时间戳,秒级还是毫秒级,在redis
内部最终使用的都是pexpireat
.
在使用redis
相关过期命令时,需要注意以下几点.
1) 如果expire key
的键不存在,返回结果为:0
.
127.0.0.1:6379> expire not_exists_key 10
(integer) 0
2) 如果过期时间是负值,键将会被立即删除,与del
命令一样.
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> expire hello -1
(integer) 1
127.0.0.1:6379> get hello
(nil)
3) persist
命令可以将键的过期时间清除.
127.0.0.1:6379> setex hello 30 world
OK
127.0.0.1:6379> ttl hello
(integer) 29
127.0.0.1:6379> persist hello
(integer) 1
127.0.0.1:6379> ttl hello
(integer) -1
4) 对于字符串类型键,执行set
命令会去掉过期时间,这个问题很容易在开发中被忽视.
127.0.0.1:6379> setex hello 30 world
OK
127.0.0.1:6379> ttl hello
(integer) 29
127.0.0.1:6379> set hello redis
OK
127.0.0.1:6379> ttl hello
(integer) -1
5) redis
不支持二级数据结构(例如:hash
,list
)内部元素的过期功能,例如不能对列表类型的一个元素做过期时间设置.
6) setex
命令作为set+expire
的组合,不但是原子执行,同时减少了一次网络通讯时间.
2.迁移键
迁移键功能非常重要,因为有时候我们只想把部分数据由一个redis
迁移到另一个redis
(例如从生产环境迁移到测试环境),redis
发展历程中提供了move
,dump+restore
和migrate
三组迁移键的方法.
1) move
move key db
如上图所示,move
命令由于在redis
内部进行数据迁移,redis
内部可以有多个数据库,move key db
就是把指定的键从源数据库移动到目标数据库中,但不建议在生产环境使用.
2) dump+restore
dump key
restore key ttl value
dump+restore
可以实现不同的redis
实例之间进行数据迁移的功能,整个迁移的过程分为两步:
在源redis下使用
dump
命令将键值序列化,格式采用的是RDB
格式.在目标
redis
上,restore
命令将上面序列化的的值进行复原,其中ttl
参数代表过期时间,如果ttl=0
代表没有过期时间.
有关dump+restore
有两点需要注意:第一:整个迁移过程并非原子性,而是通过客户端分步完成的.第二:迁移过程是开启了两个客户端连接,所以dump
的结果不是在源redis
和目标redis
之间进行传输的.
3) migrate
migrate host port key|"" target-db timeout [copy] [replace] [keys key [key...]]
migrate
命令也是用于在redis
实例间进行数据迁移,实际上migrate
命令就是将dump
,restore
,del
三个命令进行组合,从而简化了操作流程.migrate
命令具有原子性,从而从redis 3.0.6
版本以后已经支持迁移多个键的功能,有效地提高了迁移效率,migrate
在集群中起到了重要的作用.
参数说明:
host
:目标redis
实例的ip.port
:目标redis
实例的端口.key|""
:在redis 3.0.6
版本之前migrate
只支持迁移一个键,所以在此处填写要迁移的键.但redis 3.0.6
之后支持多个键的迁移,如果当前需要迁移多个键,此处填写为空字符串:""
.target-db
:目标redis
的数据库索引,例如要迁移到0号数据库,这里就写0
.timeout
:迁移的超时时间.[copy]
:如果添加此选项,迁移后并不删除键.[replace]
:如果添加此选项,migrate
不管目标redis
是否存在该键都会将键正常的迁移进行覆盖.[keys key [key...]]
:迁移多个键,例如要迁移key1
,key2
,key3
就填写keys key1 key2 key3
.
move
,dump+restore
,migrate
比较
命令 | 作用域 | 原子性 | 支持多个键 |
---|---|---|---|
move |
redis 实例内部 |
是 | 否 |
dump+store |
redis 实例之间 |
否 | 否 |
migrate |
redis 实例之间 |
是 | 是 |
3.遍历键
redis
提供了两个命令遍历所有的键,分别是keys
和scan
.
1) 全量遍历键
keys pattern
例:
查询所有键:
127.0.0.1:6379> keys *
1) "node"
2) "hello"
3) "java"
4) "python"
使用表达式:
127.0.0.1:6379> keys *e*
1) "node"
2) "hello"
127.0.0.1:6379> keys [n,h]*
1) "node"
2) "hello"
通配符:
*
代表匹配任意字符.?
代表匹配一个字符.[]
代表匹配部分字符串,例如:[1,2]
代表匹配1,2
,[1-10]
代表匹配1
到10
的任意数字.\x
用来转义,例如要匹配星号,问号需要进行转义.
如果redis
包含了大量的键,执行keys
命令很可能会造成redis
阻塞,所有一般建议不要在生产环境下使用keys
命令,但有时候确实有遍历键的需求怎么办,可以在一下三种情况下使用:
在一个不对外提供服务的
redis
从节点上执行,这样不会阻塞到客户端的请求.当
redis
实例下的键总数比较少,可执行此命令.使用
scan
命令渐进式的遍历所有键,可以有效防止阻塞.
2) 渐进式遍历
redis
从2.8
版本后,提供一个新命令scan
,它能有效的解决keys
命令存在的问题.和keys
命令执行时会遍历所有键不同,scan
采用渐进式遍历的方式来解决keys
命令可能带来的阻塞问题,每次scan
命令的时间复杂度是O(1),但是要真正实现keys
的功能,需要多次使用scan
命令,redis
存储键值对实际使用的是hashtable
的数据结构.
scan cursor [match pattern] [count number]
cursor
是必须参数,实际上cursor
是一个游标,第一次遍历从0
开始,每次scan
遍历玩都会返回当前游标的值,直到游标值为0
,表示遍历结束.match pattern
是可选参数,它的作用是做模式匹配,这点和keys
的模式匹配相同.count number
是可选参数,它的作用是每次遍历的键个数,默认值为10
.
127.0.0.1:6379> scan 0
1) "0" # 游标值
2) 1) "node"
2) "hello"
3) "java"
4) "python"
4.数据库管理
redis
提供了几个面向redis
数据的操作,他分别是dbsize
,select
,flushdb
,flushall
命令.
1.切换数据库
select dbIndex
许多关系型数据库,例如MySQL
支持在一个实例下有多个数据库存在,但是与关系型数据库用字符来区分不同数据库名不同,redis
只是用数字作为多个数据库的实现.redis
默认配置中是有16个数据库:
databases 16
redis 3.0
中已经开始逐渐弱化这个功能,例如redis
的分布式实现redis cluster
只允许使用0
号数据库,只不过为了向下兼容老版本的数据库功能,该功能没有完全废弃掉.
废弃多数据库的原因:
redis
是单线程的,如果使用多个数据库,那么这些数据库仍然是使用一个CPU
,彼此之间会受到影响.多数据库的使用方式,会在调试和运维不同业务的数据库变得困难,假如有一个慢查询存在,依然会影响其他数据库,这样会使得别的业务方定位问题非常困难.
部分
redis
的客户端根本就不支持这种方式,及时支持,在开发的时候来回切换数字形式的数据库,很容易弄乱.
2.flushdb/flushall
flushdb/flushall
命令用于清除数据库,两者的区别是:
flushdb
是清除当前数据库的所有数据.flushall
是清除实例的所有数据.
flushdb/flushall
命令可以非常方便的清理数据,但是也带来两个问题:
flushdb/flushall
命令会将所有数据清除,一旦误操作后果不堪设想.如果当前数据库键值数量比较多,
flushdb/flushall
存在阻塞的可能.所以在使用flushdb/flushall
一定要小心谨慎.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。