【Redis进阶】RDB持久化策略

1. 浅谈持久化

持久化:能够在重启主机/进程的时候,将数据从硬盘中恢复到内存的特性。
持久化相信大家都是不陌生的,毕竟MySQL中事务ACID四大特性中就包含持续性这样的特点,所谓持久化,本质上就是将数据保存在硬盘上;不持久化就意味着将数据保存在内存中。
Redis的持久化机制:对于Redis而言,将数据保存在内存中是其效率高的重要原因,但是为了保证数据的可靠性,Redis也提供了持久化机制。那么问题来了,Redis的持久化机制会影响到Redis的性能吗?大概率是不会的,因为Redis查询数据的时候仍然是从内存中读取,只是额外将数据多保存了一份在硬盘上,额外内存开销也没有很大,Redis具体提供了RDB、AOF两种机制进行持久化。

2. RDB机制

RDB(Redis DataBase):简单来说,Redis会定期的将内存的全量数据生成一个快照(dump.rdb文件),然后保存在硬盘中。
这个快照就类似于警察到达案发现场后,就会在周围设立警戒线,然后拍照保存现场状态。当Redis遇到特殊情况(断电)进程异常退出后,尽管内存数据丢失,仍旧可以通过这个快照文件进行恢复

2.1 RDB触发时机

RDB的触发时机有两种情况:

  1. 手动触发:即通过客户端命令的方式执行生成快照的过程
    1. save命令:当执行save命令后,redis服务器就会全力以赴的生成这个RDB快照文件,进而阻塞其余redis客户端命令的执行(不推荐×)
    2. bgsave命令:即通过后台方式运行,此处redis服务器会fork出一个子进程,然后由子进程完成生成RDB快照的任务,此时主进程仍然可以处理其余的redis客户端命令
  2. 自动触发:在redis的配置文件(redis.conf)配置经过多长时间 / 经过多少次修改。

关于RDB快照文件的存储位置在redis的配置文件(redis.conf)中有明确定义:
image.png
此处我的云服务器默认dump.rdb文件就生成在./的工作目录下,当我们使用vim dump.rdb查看这个文件
image.png
我们观察该文件的格式,可以发现该RDB文件是一个二进制文件,后续redis重启后,就会尝试该文件,如果格式出现错误,就有可能会出现加载失败!

由于dump.rdb文件非常重要,因此不要随意修改!redis还提供了一些客户端命令例如redis-check-rdb等用于检查rdb文件是否正确

总结:

  • redis默认开启了RDB策略,会自动生成dump.rdb快照文件,该文件路径可以在配置文件redis.conf目录进行配置
  • dump.rdb文件是一个二进制压缩文件
  • 可以通过手动触发/自动触发两种方式来生成RDB镜像文件

2.2 bgsave执行流程

当redis服务器处理bgsave命令就会执行以下流程:

执行流程:

  1. 服务器接收bgsave命令
  2. 服务器主进程就会fork出一个子进程,此时主进程可以继续执行其余客户端命令
  3. 子进程具有和父进程相同的内存数据,就可以依据这些数据生成rdb二进制文件(存放在一个临时文件中),处理完后才会将新的临时文件覆盖原先的rdb文件
  4. 当子进程任务完成之后就会使用信号机制通知父进程

2.3 RDB自动触发策略

由于rdb文件并不是实时更新的,因此我们还需要查看redis.conf配置的触发条件:
image.png
上述配置项就配置了RDB的触发策略:save 经过时间 修改次数,因此上面三项配置就是:

  • 在3600s内修改次数达到1次,就会在3600s(1小时)生成RDB文件
  • 在360s内修改次数达到100次,就会在300s(5分钟)生成RDB文件
  • 在60s内修改次数达到10000次,就会在60s(1分钟)生成RDB文件

事实上我们可以在配置项中任意更改,但需要满足一定条件:生成RDB的频率不能太高,因为生成一次RDB快照需要将内存中的全量数据全部压缩,成本比较大

RDB的缺点:正是因为RDB采用的是每隔一定时间进行RDB快照生成,例如如果配置为save 5 1,那么当前执行过一次RDB策略,但是接下来5min之类有大量请求涌入,就在某一刻,系统断电了,此时RDB文件没有进行更新,导致了数据不一致的情况

2.4 实操

理论大致讲完了,现在我们进行实操验证:
场景一:手动执行save/bgsave生成快照

127.0.0.1:6379> set k1 111
OK
127.0.0.1:6379> set k2 222
OK
127.0.0.1:6379> set k3 333
OK
127.0.0.1:6379> bgsave
Background saving started

image.png
当我们尝试强制杀死redis进程的时候,重启redis服务,观察能否恢复内存数据:

[root@VM-16-5-opencloudos redis]# ps -aux | grep 6379
redis        672  0.1  0.2 136452  5108 ?        Ssl  Jun11   6:39 /www/server/redis/src/redis-server 0.0.0.0:6379
root     2667081  0.0  0.1   6792  2048 pts/0    S+   14:58   0:00 grep --color=auto 6379
[root@VM-16-5-opencloudos redis]# kill -9 672
[root@VM-16-5-opencloudos redis]# systemctl restart redis
[root@VM-16-5-opencloudos redis]# redis-cli
127.0.0.1:6379> keys *
1) "k3"
2) "k1"
3) "k2"

可以看到内存数据已经被恢复到内存中了!
场景二:插入新数据后不执行bgsave命令

127.0.0.1:6379> keys *
1) "k3"
2) "k1"
3) "k2"
127.0.0.1:6379> set k4 444
OK
127.0.0.1:6379> exit
[root@VM-16-5-opencloudos redis]# ps -aux | grep redis
redis    2667513  0.1  0.6 136452 11640 ?        Ssl  14:59   0:01 /www/server/redis/src/redis-server 0.0.0.0:6379
root     2673606  0.0  0.1   6792  2048 pts/0    S+   15:11   0:00 grep --color=auto redis
[root@VM-16-5-opencloudos redis]# kill -9 2667513
[root@VM-16-5-opencloudos redis]# systemctl restart redis
[root@VM-16-5-opencloudos redis]# redis-cli
127.0.0.1:6379> keys *
1) "k3"
2) "k2"
3) "k1"

此时就可以证明redis是根据dump.rdb快照文件恢复数据的,但是其中没有新添加的k4信息,因此不会恢复到内存中

这里需要注意:我们必须要通过kill -9的方式杀死进程,如果使用一些例如systemctl stop redis等命令,redis会在shutdown之前进行生成RDB的过程,如下几种方式都可以生成RDB快照

  1. 执行save/bgsave/自动触发
  2. 进行主从复制
  3. 执行shutdown等命令

场景三:观察执行bgsave文件替换过程
前面我们提到过,当执行bgsave命令时子进程会将数据文件存放到临时文件中,然后再替换原有的RDB文件,我们可以通过Linux文件系统的stat命令查看文件inode编号:

[root@VM-16-5-opencloudos redis]# stat dump.rdb
  File: dump.rdb
  Size: 2151      	Blocks: 8          IO Block: 4096   regular file
Device: 252,1	Inode: 829479      Links: 1
[root@VM-16-5-opencloudos redis]# redis-cli
127.0.0.1:6379> bgsave
Background saving started
127.0.0.1:6379> exit
[root@VM-16-5-opencloudos redis]# stat dump.rdb
  File: dump.rdb
  Size: 2151      	Blocks: 8          IO Block: 4096   regular file
Device: 252,1	Inode: 819717      Links: 1

可以发现dump.rdb文件的编号已经发生了改变

补充:在Linux上常见的文件系统组织方式(ext4)将整个文件系统分为了以下三大部分:

  1. 超级块(存放一些管理信息)
  2. inode区(存放inode节点,每个文件都会被分配一个inode数据结构,存放各种元数据信息)
  3. block区(存放文件的具体数据内容)

场景四:通过配置自动生成RDB
image.png
新增配置项:save 10 1(注意:更改完配置文件后一定要重启redis服务)

127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> set k1 111
OK
127.0.0.1:6379> exit

在10s后重新观察dump.rdb文件就可以发现重新执行了RDB生成过程
场景五:故意改坏RDB文件,观察启动现象
当我们尝试在dump.rdb中间修改一些数据,使用kill -9 强制杀死redis服务,就会出现启动失败的现象,查看日志文件redis.log(在配置文件redis.conf可以配置)
image.png
我们也可以通过一些客户端工具,例如redis-check-rdb检查RDB文件格式:
image.png

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值