Redis开发与运维学习笔记---(4)

2020-03-31 15:30:20 浏览数 (1)

redis中针对单个键有很多命令,之前我们已经接触到了type、del、object、exists、expire等等,再来看其他命令。开始之前,来看一个小插曲:

---------------------开始----------------

set hello world的时候,竟然提示read-only。使用info replication的方法查看当前复制状态,发现role变成了slave,所以使用slaveof no one来修改下属性。

代码语言:javascript复制
[root@VM_48_10_centos ~]# redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> set hello world
(error) READONLY You can't write against a read only slave.
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:xxx.xx.5.121
master_port:20556
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:1
master_link_down_since_seconds:1585363887
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6379> slaveof no one
OK
127.0.0.1:6379> set hello world
OK

---------------------小插曲结束----------------

正式开始看其他键操作

1

键重命名

rename key newkey

举例如下:

代码语言:javascript复制
127.0.0.1:6379> get hello
"world"
127.0.0.1:6379> rename hello hi
OK
127.0.0.1:6379> get hello
(nil)
127.0.0.1:6379> get hi
"world"
127.0.0.1:6379> set hello world2
OK
127.0.0.1:6379> get hello
"world2"
127.0.0.1:6379> rename hi hello
OK
127.0.0.1:6379> get hello
"world"
127.0.0.1:6379> get hi
(nil)

收件创建hello-->world键值对,然后将hello重命名为hi,发现hello键的value为空,而hi键的value为world,再重新设置hello,再次重命名,发现hello键被覆盖。

通过这个例子,我们发现,使用rename操作是有可能覆盖已经存在的键值的,这在线上可能不安全,因此,redis提供了renamenx命令,表示仅在rename的新键不存在的时候,在进行重命名,如果存在,则重命名返回数字0,而不是返回ok,这样避免了线上的键被覆盖。

除此之外,还有2点需要注意:

1、由于重命名期间会执行del命令删除旧的键,如果键对应的值比较大,则会存在阻塞redis的风险。这一点和MySQL中的rename不同,mysql中的rename操作为原子操作,本质上是对底层文件句柄的操作。

2、如果key和newkey相同,在3.2版本之前返回错误,在3.2版本之后,返回0

2

随机返回一个键

使用randomkey可以随机返回一个键。这个功能可以测试当前redis中是否有键值

3

键过期

expire和expireat

关于键过期,之前说过expire的命令,该命令可以通过:

expire key seconds

来让键在seconds秒之后过期。

但是,这个命令不够精确,我们可以使用expireat命令来指定精确的过期时间:

expireat key timestamp:键在秒级时间戳timestamp之后过期。其中timestamp需要取整数。

ttl和pttl

这两个命令是查看redis的键剩余过期时间的。pttl精度更高,可以达到毫秒级别,有3种返回值:

1、大于0的整数,值得是键剩余过期时间

2、返回1,代表键没有设置过期时间

3、返回-2,代表键不存在

代码语言:javascript复制
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
127.0.0.1:6379> pttl hello
(integer) 4461

毫秒级过期方案pexpire和pexpireat

这两兄弟和expire不同之处在于,最后跟的时间是毫秒。其他的使用方法都一样,本质上,redis会将expire的命令转换成pexpire的命令。

几点注意:

a、如果expire的键不存在,则会返回0

b、如果时间为负值,则键会被立即删除。

代码语言:javascript复制
127.0.0.1:6379> get hello
"world"
127.0.0.1:6379> 
127.0.0.1:6379> expire hello -2
(integer) 1
127.0.0.1:6379> get hello
(nil)
127.0.0.1:6379> expire hello 10
(integer) 0

c、persist命令可以将键的过期时间清除

代码语言:javascript复制
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> expire hello 50
(integer) 1
127.0.0.1:6379> ttl hello
(integer) 46
127.0.0.1:6379> persist hello
(integer) 1
127.0.0.1:6379> ttl hello
(integer) -1
127.0.0.1:6379> get hello
"world"

d、set命令会导致过期时间失败

代码语言:javascript复制
127.0.0.1:6379> get hello
"world"
127.0.0.1:6379> expire hello 50
(integer) 1
127.0.0.1:6379> ttl hello
(integer) 47
127.0.0.1:6379> set hello world~~
OK
127.0.0.1:6379> ttl hello
(integer) -1

e、redis不支持二级数据结构(哈希、列表)内部元素的过期功能。

f、setex命令作为set expire的组合,不但是原子执行,同时减少了一次网络通讯时间。

4

迁移键

redis中,提供了3中迁移键的方法:

move

dump restore

migrate

下面分别介绍:

1、move

move命令用户在多个数据库中进行键迁移。它的主要功能是将键从一个数据库迁移到另外一个数据库,但是,多数据库的功能,本身是不建议在线上使用的,这个命令大家了解一下即可。

代码语言:javascript复制
127.0.0.1:6379> get hello
"world~~"
127.0.0.1:6379> move hello 1
(integer) 1
127.0.0.1:6379> get hello
(nil)
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> get hello
"world~~"

2、dump restore

dump restore可以实现在不同的redis实例之间进行数据迁移的功能,整个迁移的过程分为两步:

a、在源redis上,dump命令会将键值序列化,格式采用的是rdb格式。

b、在目标redis上,restore命令将上面序列化的值进行复原,其中ttl参数代表过期时间。

这里有2点需要注意:

第一:dump restore并非原子性的,而是通过客户端分布完成的。

第二:迁移过程是开启了2个客户端的连接,所以dump的结果不是在源redis和目标redis之间进行传输,需要有个中间过程。

举例如下:

代码语言:javascript复制
###6379端口
127.0.0.1:6379> get hello
"world~~"
127.0.0.1:6379> dump hello
"x00aworld~~x06x00xe9x02ixcfnxd0xa5:"

###6380端口
127.0.0.1:6380> get hello
(nil)
127.0.0.1:6380> restore hello 0 "x00aworld~~x06x00xe9x02ixcfnxd0xa5:"
OK
127.0.0.1:6380> get hello
"world~~"

3、migrate

该命令也是在redis实例间进行数据迁移的,实际上migrate命令就是讲dump、restore、del3个命令进行组合,从而简化了操作流程。

它跟dump restore的方法有3点不同:

第一、整个过程是源自执行的,不需要要在多个redis实例上开启客户端,只需要在源redis上执行migrate命令即可

第二、migrate命令的数据传输直接在源redis和目标redis上完成的

第三、目标redis完成restore后发送ok给源redis,源redis接受后会根据migrate对应的选项来决定是否在源redis上删除对应的键。

migrate的参数如下:

host:目标redis的IP地址

port:目标redis的端口

key|“” :redis3.0.6之前,migrate只支持迁移一个键,当需要迁移多个键,此处字符串为空

destination-db:目标redis的数据库索引,例如要迁移到0号数据库,此处写0即可。

timeout:迁移的超时时间

copy:添加该参数,迁移之后不删除源键

replace:添加改参数,会覆盖目标端redis的键

keys key [key1 key2]:迁移多个键的时候用,如果要迁移多个,则使用keys key1 key2 key3

下面我们从6379端口将键迁移到6380端口:

代码语言:javascript复制
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> set yeyz handsome
OK
127.0.0.1:6379> get yeyz
"handsome"
127.0.0.1:6379> migrate 127.0.0.1 6380 yeyz 0 1000
OK
127.0.0.1:6379> get yeyz
(nil)
127.0.0.1:6379> exit
[root@VM_48_10_centos ~]# redis-cli -p 6380
127.0.0.1:6380> get yeyz
"handsome"

注意:

a、如果没有加replace参数,但是目标端已经有同名键了,此时会报错,提示busykey target key name already exists.

b、如果源redis没有要迁移的键,则会提示nokey

最后,批量迁移举例:

代码语言:javascript复制
[root@VM_48_10_centos ~]# redis-cli
127.0.0.1:6379> set key0 value0
OK
127.0.0.1:6379> set key1 value1
OK
127.0.0.1:6379> set key2 value2
OK
127.0.0.1:6379> migrate 127.0.0.1 6380 "" 0 1000 keys key0 key1 key2
OK
127.0.0.1:6379> get key0
(nil)
127.0.0.1:6379> get key1
(nil)
127.0.0.1:6379> get key2
(nil)
127.0.0.1:6379> exit

[root@VM_48_10_centos ~]# redis-cli -p 6380
127.0.0.1:6380> get key0
"value0"
127.0.0.1:6380> get key1
"value1"
127.0.0.1:6380> get key2
"value2"

0 人点赞