本章将按照单个键,遍历键,数据库管理三个维度对一些通用命令进行介绍.java
针对单个键的命令,前面几节已经介绍过一部分了,例如type
,del
,object
,exists
,expire
等,下面介绍几个重要命令.node
rename key newkey
例如一个键名为node
值为jedis
:python
127.0.0.1:6379> get node "jedis"
下面操做将键node
改成java
:redis
127.0.0.1:6379> rename node java OK 127.0.0.1:6379> get java "jedis"
若是在rename
以前,键java
已经存在,那么它的值也将被覆盖.
为了防止被强行rename
,redis
提供了renamenx
命令,确保只有newkey
不存在时候才被修改.
在使用重命名时,有两点须要注意:shell
因为重命名键期间会执行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
randomkey
例如,当数据库中有1000个键值对,randomkey
命令会随机从中挑选一个.dom
127.0.0.1:6379> dbsize 1000 127.0.0.1:6379> randomkey hello 127.0.0.1:6379> randomkey java
除了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
的组合,不可是原子执行,同时减小了一次网络通信时间.
迁移键功能很是重要,由于有时候咱们只想把部分数据由一个redis
迁移到另外一个redis
(例如从生产环境迁移到测试环境),redis
发展历程中提供了move
,dump+restore
和migrate
三组迁移键的方法.
move key db
如上图所示,move
命令因为在redis
内部进行数据迁移,redis
内部能够有多个数据库,move key db
就是把指定的键从源数据库移动到目标数据库中,但不建议在生产环境使用.
dump key restore key ttl value
dump+restore
能够实现不一样的redis
实例之间进行数据迁移的功能,整个迁移的过程分为两步:
在源redis下使用dump
命令将键值序列化,格式采用的是RDB
格式.
在目标redis
上,restore
命令将上面序列化的的值进行复原,其中ttl
参数表明过时时间,若是ttl=0
表明没有过时时间.
有关dump+restore
有两点须要注意:第一:整个迁移过程并不是原子性,而是经过客户端分步完成的.第二:迁移过程是开启了两个客户端链接,因此dump
的结果不是在源redis
和目标redis
之间进行传输的.
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 实例之间 |
是 | 是 |
redis
提供了两个命令遍历全部的键,分别是keys
和scan
.
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
命令渐进式的遍历全部键,能够有效防止阻塞.
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"
redis
提供了几个面向redis
数据的操做,他分别是dbsize
,select
,flushdb
,flushall
命令.
select dbIndex
许多关系型数据库,例如MySQL
支持在一个实例下有多个数据库存在,可是与关系型数据库用字符来区分不一样数据库名不一样,redis
只是用数字做为多个数据库的实现.redis
默认配置中是有16个数据库:
databases 16
redis 3.0
中已经开始逐渐弱化这个功能,例如redis
的分布式实现redis cluster
只容许使用0
号数据库,只不过为了向下兼容老版本的数据库功能,该功能没有彻底废弃掉.
废弃多数据库的缘由:
redis
是单线程的,若是使用多个数据库,那么这些数据库仍然是使用一个CPU
,彼此之间会受到影响.
多数据库的使用方式,会在调试和运维不一样业务的数据库变得困难,假若有一个慢查询存在,依然会影响其余数据库,这样会使得别的业务方定位问题很是困难.
部分redis
的客户端根本就不支持这种方式,及时支持,在开发的时候来回切换数字形式的数据库,很容易弄乱.
flushdb/flushall
命令用于清除数据库,二者的区别是:
flushdb
是清除当前数据库的全部数据.
flushall
是清除实例的全部数据.
flushdb/flushall
命令能够很是方便的清理数据,可是也带来两个问题:
flushdb/flushall
命令会将全部数据清除,一旦误操做后果不堪设想.
若是当前数据库键值数量比较多,flushdb/flushall
存在阻塞的可能.因此在使用flushdb/flushall
必定要当心谨慎.