# 6.3 RDB持久化机制实战

注:本小节开始前,请检查上一小节中执行`redis-server`位置处是否存在`dump.rdb`文件,若存在则删除.否则启动`redis-server`会失败

## 6.3.1 编写配置文件,生成RDB快照

* step1. 编写配置文件

```
(base) root@yuanhong section6-3 % cat redis.conf 
# 5秒内有1个或1个以上的键被修改时生成快照
save 5 1

# 300秒内有100个或100个以上的键被修改时生成快照
save 300 100

# 60秒内有1000个或1000个以上的键被修改时生成快照
save 60 1000

# 快照文件存储路径
dir /StudyRedisBaseOnDocker/conf/chpater6/section6-3

# 快照文件名
dbfilename my_dump.rdb
```

其中3个`save`选项之间是逻辑或关系,即只要有1个条件被满足,就会生成快照.可以看到,RDB持久化文件只是当条件满足后生成快照,因此无法即时保存当前状态的内存数据.也就是说,通过RDB恢复数据时,会丢失上次生成快照后更新的数据

注:此处设置`save 5 1`是为了触发快照机制,生产环境不会设置这么频繁的条件的

* step2. 启动redis-server

```
(base) root@yuanhong section6-3 % redis-server /StudyRedisBaseOnDocker/conf/chpater6/section6-3/redis.conf
```

* step3. 连接该redis-server并设置一些键值对

```
SET empID 001
SET empName "Mike"
```

此时满足了"5秒内有1个或1个以上的键被修改时生成快照"这个条件,因此已经有持久化文件被存储到配置文件指定的路径中了

* step4. 观察redis-server的日志

```
14021:M 15 Aug 2023 15:55:18.285 # Server initialized
14021:M 15 Aug 2023 15:55:18.285 * Ready to accept connections
14021:M 15 Aug 2023 15:55:27.866 * 1 changes in 5 seconds. Saving...
14021:M 15 Aug 2023 15:55:27.867 * Background saving started by pid 14036
14036:C 15 Aug 2023 15:55:27.868 * DB saved on disk
14021:M 15 Aug 2023 15:55:27.967 * Background saving terminated with success
14021:M 15 Aug 2023 15:55:33.715 * 1 changes in 5 seconds. Saving...
14021:M 15 Aug 2023 15:55:33.716 * Background saving started by pid 14042
14042:C 15 Aug 2023 15:55:33.723 * DB saved on disk
14021:M 15 Aug 2023 15:55:33.817 * Background saving terminated with success
```

* step5. 查看日志指定的路径下是否存在rdb日志文件

```
(base) root@yuanhong section6-3 % ls
my_dump.rdb	redis.conf
```

其他和RDB持久化有关的配置参数:

* `stop-writes-on-bgsave-error`:该参数默认是`yes`,表示当执行`BGSAVE`持久化命令时如果有错误,Redis服务器会终止写入操作;如果取值是`no`,那么即使出现错误也会继续写入
* `rdbcompression`:该参数默认是`yes`,表示在持久化时会压缩文件
* `rdbchecksum`:该参数默认是`yes`,表示在用RDB快照文件进行数据恢复时开启对快照文件的校验.如果设置为`no`,就无法确保快照文件的正确性

在实际项目里,上述参数一般会使用默认值

## 6.3.2 用快照文件恢复数据

和之前的思路一样,起一个容器来验证数据是否恢复:

* step1. 启动容器

```
(base) root@yuanhong section6-3 % docker run -itd --name redis-server -v /StudyRedisBaseOnDocker/conf/chpater6/section6-3/redis.conf:/redisConfig/redis.conf:rw -v /StudyRedisBaseOnDocker/conf/chpater6/section6-3/my_dump.rdb:/StudyRedisBaseOnDocker/conf/chpater6/section6-3/my_dump.rdb:rw redis:latest redis-server /redisConfig/redis.conf
9e2f67eb841dde2ce31b58edb32468b88ebe58da7232f9d67ce1a89c18bbda76
```

* step2. 检查容器状态

```
(base) root@yuanhong section6-3 % docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS        PORTS      NAMES
9e2f67eb841d   redis:latest   "docker-entrypoint.s…"   2 seconds ago   Up 1 second   6379/tcp   redis-server
```

* step3. 进入容器确认数据

```
(base) root@yuanhong section6-3 % docker exec -it redis-server /bin/bash
root@9e2f67eb841d:/data# redis-cli
127.0.0.1:6379> GET empID
"001"
127.0.0.1:6379> GET empName
"Mike1"
```

## 6.3.3 `SAVE`和`BGSAVE`命令

* `SAVE`:执行该命令后,Redis服务器会把当前内存里的数据写入快照文件,在写入的过程中会暂停执行其他命令,直到写完快照文件之后,才会执行其他命令.若执行成功,则返回OK.在实际项目里,**如果当前Redis内存数据很多,那么一旦执行`SAVE`命令,服务器就会长时间暂停执行命令,造成大量连接阻塞,从而导致线上问题,所以一般在执行`SAVE`命令时需要非常谨慎**
* `BGSAVE`:执行该命令后,Redis服务器会创建一个新的进程,在该进程里把内存数据写入快照文件里,在写的过程中Redis服务器能继续执行其他来自客户端的命令.该命令的返回值为`Background saving started`,表示已经启动后台写操作进程了
* `LASTSAVE`:查看`BGSAVE`的操作结果.该命令返回的是一个时间戳,表示最近一次把内存数据存入快照文件的时间.如果该时间和`BGSAVE`命令的运行时间能对应上,则能说明`BGSAVE`命令成功执行

例:

客户端执行`SAVE`:

```
127.0.0.1:6379> SAVE
OK
```

此时服务端日志为:

```
15341:M 15 Aug 2023 16:31:12.133 * DB saved on disk
```

客户端执行`BGSAVE`:

```
127.0.0.1:6379> BGSAVE
Background saving started
```

此时服务端日志为:

```
15341:M 15 Aug 2023 16:31:58.071 * Background saving terminated with success
```

查看上一次成功创建快照的时间戳:

```
127.0.0.1:6379> LASTSAVE
(integer) 1692088318
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://redis.sai.show/di-6-zhang-redis-shu-ju-chi-jiu-hua-cao-zuo/6.3-rdb-chi-jiu-hua-ji-zhi-shi-zhan.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
