redis持久化之RDB(Redis DataBase)
1.什么是redis的RDB
RDB (Redis DataBase) 是 Redis 的一种持久化方式,它通过将 Redis 服务器在特定时间点的数据状态保存到磁盘上的 RDB 文件中(dump.rdb),从而实现数据的持久化存储。RDB 采用快照的方式来保存数据,它可以在指定条件下进行自动保存或手动触发保存
2.redis的RDB触发机制
自动触发
修改配置文件 save参数,rdb文件路径以及rdb文件名称(按需修改),保存配置
并且重启redis服务。
连接redis客户端,执行命令
set k1 v1
set k2 v2
在我配置的存放rdb文件的路径下生成了一个dump.rdb文件,因为配置文件里记录的是5秒钟内有2次变化,就会生成rdb文件,我们的操作满足这个要求,因此生成了rdb文件。
同时我们记录下文件大小
然后我再执行两次set操作
set k3 v3
set k4 v4
再看一下dump.rdb文件的大小,redis再一次生成了快照文件,将内存中的全部数据都写入到了磁盘中的rdb文件中
注意:按照我现在的配置,如果我只对数据做一次变更,例如我只set k1 v1,此时是不会生成rdb文件的。因为不满足我们配置文件中设置的快照生成条件。
我们先把之前生成的dump.rdb文件删除掉,验证一下上述的结论。
执行命令 rm -rf dump6999.rdb
连接redis客户端,执行命令 set k5 v5
此时不会生成dump.rdb文件,直到我再一次变更数据,执行了set k6 v6 才会生成dump.rdb文件,这里就引出了rdb持久化方式的一个缺点:数据丢失
隐藏彩蛋
*当我们执行shutdown命令结束redis进程的时候,redis也会生成一个dump.rdb文件。感兴趣的小伙伴可以试试。
*
手动触发
手动触发有两条指令
第一条是save命令
第二条是bgsave命令
上述两条命令都会生成一个dump.rdb文件,区别在于
save命令生成dump.rdb文件是阻塞的,生产环境禁用!!!!!
bgsave命令生成dump.rdb文件是非阻塞的
3.RDB文件数据还原
首先我们删除一下之前生成的dump.rdb文件。
然后我们执行以下flushdb/flushall 指令清空redis库。
奇妙的事情就发生了,你会发现执行flushdb或者flushall,也会生成一个dump.rdb文件,但是这个文件是空的,没有任何意义。
没意义的文件同样我们删除一下
执行命令set k1 v1
执行命令set k2 v2
我们使用kill -9 命令模拟redis服务器宕机,将redis进程杀死后重启
我们发现刚才的k1 k2对应的数据还在redis内存中
4.RDB持久化的优点
数据迁移和备份:RDB 文件可以用于进行数据的迁移和备份。通过复制 RDB 文件,可以将数据从一个 Redis 实例迁移到另一个实例,也可以用于创建数据库的备份。
RDB最大限度的提高了Redis的性能:生成RDB文件是通过fork子进程来实现的,父进程不会进行磁盘的I/O操作
数据恢复:RDB 文件可以用于在 Redis 服务器宕机后进行数据的快速恢复。通过加载 RDB 文件,可以将数据还原到宕机前的状态。
5.RDB持久化的缺点
数据丢失风险:由于 RDB 是定时或手动快照数据保存,因此如果在保存点之后发生宕机或故障,可能会丢失从上一次保存点到故障之间的数据。
写入时的性能影响:当 RDB 持久化方式执行数据快照时,会占用服务器磁盘I/O,特别是在数据量较大的情况下,可能会影响服务器性能。
RDB依赖于主进程的fork,在大数据集的情况下,fork的时候内存中的数据被克隆了一份,大致2倍的膨胀,需要考虑。
6.redis生成dump.rdb文件的真相
前面我们说到,手动触发生成dump.rdb文件的指令其中一个是bgsave,它是非阻塞的,他是在后台执行的。
redis生成dump.rdb文件,也是在后台执行的。
本质都是redis服务端在linux系统中,fork一个子进程,子进程将内存中的数据写入到磁盘上的dump.rdb文件,此时redis的主进程仍然能处理redis客户端发送的指令。
7.关于fork
在 Linux 系统中,fork 是一个系统调用,它用于创建一个新的进程,新进程是原始进程的副本。调用 fork 后,原始进程(称为父进程)被复制成一个完全相同的子进程。这意味着子进程会继承父进程的所有内存空间、文件描述符和其他资源。
在 fork 调用后,父进程和子进程将在相同的执行点继续执行,但它们有各自独立的地址空间。这意味着对于内存中的任何修改在一个进程中不会影响另一个进程。
通过该调用,操作系统创建一个新的进程,这样就可以在新的进程中执行不同的操作,而不会影响原始的父进程。fork 调用是 Unix/Linux 系统中进程管理的基础,它允许创建出一个新的进程作为父进程的副本,以此实现并发执行和多任务处理。