RDB持久化是通过快照完成的,当符合一定条件时Redis会自动将内存中的所有数据进行快照并存储到磁盘上。默认存储在Redis安装目录的data
子目录的dump.rdb
文件中。
一、环境描述
-
主机配置
CPU:单核
内存:2 GB
IP:10.24.16.87 -
操作系统
CentOS 6.6 x86_64 Minimal -
Redis版本
Redis server v=3.2.4 sha=00000000:0 malloc=jemalloc-4.0.3 bits=64 build=431d8e4a684c794b -
Redis安装方式
按照《在CentOS上安装Redis缓存系统》
二、相关命令
1. SAVE命令
SAVE
命令会将Redis内存中的数据集同步保存至磁盘上,产生一个包含所有数据的时间点快照,以RDB文件的形式存储。
你几乎不会在生产环境中调用SAVE
命令,因为这个命令会阻塞所有其他的客户端。相反,你通常可以使用BGSAVE
命令。然而,如果要防止Redis创建在后台保存数据的子进程(例如,调用fork(2)
系统调用时发生错误),那么SAVE
命令可能是用于持久化最近数据集的比较好的最后手段了。
若想了解更详细的信息,请参考《Redis的数据持久化功能详解(1)—— 两种持久化方式》。
SAVE
命令会返回一个简单的字符串,如果执行成功,则返回OK
。
2. BGSAVE命令
这个命令可以在后台保存数据库,运行之后会立即返回OK
代码。Redis会创建子进程,父进程会持续为客户端提供服务,而子进程则会将数据库保存在磁盘上,然后退出。如果想要检查子进程的操作是否成功,那么你可以在客户端中运行LASTSAVE
命令。
若想了解更详细的信息,请参考《Redis的数据持久化功能详解(1)—— 两种持久化方式》。
BGSAVE
命令总是会立即返回OK
代码。
3. LASTSAVE命令
LASTSAVE
命令会返回最后一次成功执行RDB持久化的时间,以UNIX TIME的格式返回结果。你可以在客户端中运行LASTSAVE
命令,检查前一次运行的BGSAVE
命令是否运行成功。然后,再次运行BGSAVE
命令,你可以每隔一段时间(例如,每隔N秒)检查一次LASTSAVE
命令的运行结果是否改变。
LASTSAVE
命令的返回值是一个整数,表示UNIX格式的时间戳。
三、相关配置选项
在本文使用的Redis服务器中,所有配置项都存放在/usr/local/Redis/etc/redis.conf
配置文件中。RDB持久化涉及的配置项包括保存点、数据压缩、数据校验等等。
1. 保存点
这个配置项会将Redis内存中的数据保存至磁盘,格式如下所示:
save <秒数> <修改次数>
如果时间达到给定的秒数,并且对数据库的写操作也达到给定的次数,那么Redis便会将数据保存至磁盘。
在Redis的默认配置中,RDB持久化的行为如下所示:
- 当时间达到900秒(15分钟),并且对数据库的写操作至少达到1次时,Redis便会持久化数据。
- 当时间达到300秒(5分钟),并且对数据库的写操作至少达到10次时,Redis便会持久化数据。
- 当时间达到60秒(1分钟),并且对数据库的写操作至少达到10000次时,Redis便会持久化数据。
注意:如果你想要完全禁用保存点,那么你可以注释所有的“save”配置行。
如果你想要移除所有先前配置的保存点,那么你可以添加一个用空字符串作为参数的save指令,如下所示:
save ""
保存点的默认配置如下所示:
save 900 1
save 300 10
save 60 10000
2. 出错停止写入
在默认情况下,如果启用RDB快照功能(至少有一个保存点),并且最近一次后台持久化数据失败,那么Redis将会停止接受所有的写入操作请求。
这将会使用户注意到,Redis并没有将数据正确地持久化至磁盘上。否则,用户不会注意到已经发生的错误,这样便不能预防某些灾害的发生。
如果后台保存数据的进程再次开始工作,那么Redis将会自动地再次允许执行写入操作。
然而,如果你已经为Redis服务器和持久化建立了完善的监控机制,那么你可能想要禁用这个特性,即使Redis服务器的磁盘、权限或其他部分发生问题,Redis也能够像平时一样持续提供服务。
出错停止写入的默认配置如下所示:
stop-writes-on-bgsave-error yes
3. 数据压缩
当Redis将数据保存为.rdb
文件时,可以使用LZF算法压缩字符串类型的对象。
这个配置项的默认值为yes
,因为这项功能总是能带来好处的。
如果你想要在保存数据的子进程运行时节省一些CPU性能开销,那么你可以将这个配置项设置为no
。但是,如果你的数据中有很多可压缩的值或键,那么保存的数据文件可能会比较大。
数据压缩的默认配置如下所示:
rdbcompression yes
4. 数据校验
从Redis 2.5版本至今,Redis会在持久化文件的末尾添加一个CRC64校验和。
这使得RDB持久化能够最大程度的避免文件损坏。但是,当保存和加载RDB文件时,也会额外消耗一些性能(大约10%左右)。如果想要获得最大化的性能,那么你可以禁用这项功能。
在不使用校验和功能的RDB文件中,Redis会将校验和设为0,这就告诉加载代码跳过数据校验过程。
数据校验的默认配置如下所示:
rdbchecksum yes
5. 转储文件名
这项配置用于指定RDB文件的名称。
转储文件名的默认配置如下所示:
dbfilename dump.rdb
6. 转储文件目录
这项配置用于指定RDB文件的存放目录。
Redis将会在这个目录中将内存数据保存为RDB文件,使用的文件名由dbfilename
配置项指定。
Redis也会在这个目录中创建只增文件(AOF)。
注意,你必须为这项配置指定一个目录路径,而不是一个文件名。
转储文件目录的默认配置如下所示:
dir /usr/local/Redis/data
四、RDB持久化实践
下面将通过实际操作演示RDB持久化的使用方法,本文不会修改redis.conf
配置文件,而是使用redis-cli config set
命令,临时修改Redis的配置,重新启动主机或服务之后,Redis的配置就会还原。
1. 设置RDB文件名和目录
在Redis服务器的Shell中运行以下命令:
redis-cli config set dir /root/Downloads
redis-cli config set dbfilename redisdb.rdb
Redis会将持久化生成的RDB文件保存在/root/Downloads
目录中,文件名为redisdb.rdb
。
2. 导入测试数据集
运行以下Java代码,生成测试数据集文件:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.UUID;
import org.apache.commons.lang.StringUtils;
public class RedisDataGenerator {
public static void main(String[] args) {
// 设置KEY条数
long count = 10000;
int len = 4;
if (args.length > 0 && StringUtils.isNumeric(args[0])) {
count = Long.parseLong(args[0]);
len = args[0].length();
}
// 生成数据导入脚本
FileWriter fw = null;
try {
File f = new File("E:\\RedisData.txt");
fw = new FileWriter(f, true);
PrintWriter pw = new PrintWriter(fw);
for (long i = 0; i < count; i++) {
String key = "key_" + String.format("A" + "%0" + len + "d", i).substring(1);
String value = UUID.randomUUID().toString();
String command = "SET" + " " + key + " " + value;
pw.println(command);
}
pw.flush();
fw.flush();
pw.close();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
上述程序默认生成10000条数据,但本文运行这个程序时,会将运行参数指定为10000000条。
将生成的RedisData.txt
数据文件上传至Redis服务器的/root/Downloads
目录。然后,登录Redis服务器,在Shell中运行以下命令:
cd /root/Downloads/
cat RedisData.txt | redis-cli --pipe
上述命令会利用Redis的管道机制导入测试数据,运行成功之后,返回信息如下图所示:
在Shell中运行以下命令,查看测试数据占用的内存大小:
redis-cli info memory
上述命令的运行结果如下图所示:
从上图中可以看出,测试数据占用了1.02GB的内存空间。
3. 手动执行RDB相关命令
在Redis服务器的Shell中运行以下命令,保存内存中的所有数据:
redis-cli bgsave
Redis会启动一个后台进程持久化内存中的所有数据,可以不断运行以下命令,查看持久化进程是否结束:
redis-cli lastsave
当上述命令的返回值发生变化时,表示数据持久化已经完成,查看是否已经生成RDB文件,如下图所示:
由上图可知,持久化生成的RDB文件就是/root/Downloads/redisdb.rdb
文件,文件大小为487MB。
4. 配置保存点
在Redis服务器的Shell中运行以下命令,清除默认的保存点,然后设置新的保存点:
redis-cli config set save ""
redis-cli config set save "30 1000"
新保存点会在时间经过30秒,并且写入操作至少有1000次时,执行RDB持久化操作。
5. 配置数据压缩
在Redis服务器的Shell中运行以下命令,启用数据压缩功能:
redis-cli config set rdbcompression yes
如果启用数据压缩功能,那么每次执行持久化的时间就会延长,因为会耗费更多的CPU性能。
6. 配置数据校验
数据校验必须修改redis.conf
配置文件,然后重新启动Redis服务才能生效。在Redis服务器的Shell中运行以下命令,查看是否启用数据校验功能:
redis-cli config get rdbchecksum
如果启用数据校验功能,那么每次执行持久化的时间就会延长,因为会耗费更多的CPU性能。
7. 重建缓存
在Redis服务器的Shell中运行以下命令,将RDB文件拷贝至默认目录,然后清除Redis中的所有数据:
cp /root/Downloads/redisdb.rdb /usr/local/Redis/data/dump.rdb
redis-cli flushall
查看Redis中的数据是否被清除,如下图所示:
运行以下命令,重新启动Redis服务:
service redis_6379 restart
重启服务之后,Redis存放RDB文件的目录会恢复为默认值/usr/local/Redis/data/
,RDB文件名会恢复为默认值dump.rdb
。从RDB文件恢复数据时,可以通过redis-cli
运行ping
命令,若返回错误信息,则表示数据恢复尚未完成,如下图所示:
若返回PONG
,则表示数据恢复已经完成,如下图所示:
数据恢复完成之后,检查恢复后的数据是否完整,如下图所示: