Redis持久化机制RDB的实现
作者:shark-chili
基础
了解过Redis持久化RDB嘛?可不可以解释一下什么是RDB。
答: RDB
持久化机制是将内存中的数据生成快照并持久化到磁盘的过程,RDB
可以通过手动或者自动的方式实现持久化。
那RDB触发的方式有哪几种方式知道吗?
答: 有两种,分别是手动触发和自动触发:
手动触发
首先是save命令了,这个指令会直接阻塞当前redis服务器,知道RDB完成了为止,对于线上生产环境数据的备份,我们非常非常不建议使用这种方式。
127.0.0.1:6379> save OK
接下来就是bgsave
指令了,bgsave
则是主进程fork一个子进程,由子进程完成持久化操作,而主进程继续处理客户端的读写请求,如果我们需要手动实现持久化,非常推荐使用这种方式。
# 从输出我们就可以看出这种方式会将持久化的操作放在后台执行 127.0.0.1:6379> bgsave Background saving started
接下来就是自动触发了
自动触发我们可以通过配置实现redis.conf
的save
参数实现,如下所示,假如我们希望用户20s内写入3次就进行持久化,只需在配置中加一条save 20 3
即可。
save 20 3
需要注意的是save 20 3
的20s是以redis的时间间隔为主,并不是用户第1次写入后的20s内再写入两次进行持久化。
哦,那你能不能给我讲一下bgsave的工作流程呢?
答: bgsave
的工作流程如下图所示,整体可以简述为:
- 主进程fork出一个子进程,这时候主进程会被阻塞。
- 子进程创建完成后,
redis
客户端会输出Background saving started
,这就意味子进程开始进行持久化操作了。 - 子进程持久化完成后,会生成一个rdb文件,将本次的rdb文件通过原子替换的方式将上一次备份的rdb覆盖。
- 子进程发送信号通知父进程本次任务完成。
RDB常见的配置参数有哪些了解嘛?
答: 首先是dbfilename
,它可以指定rdb
的文件名
# The filename where to dump the DB dbfilename dump.rdb
接下来就是dir,它可以指定rdb文件的持久化的位置,默认取redis服务端的位置。
dir ./
当reids
无法将文件写入磁盘,我们可以讲stop-writes-on-bgsave-error
设置为yes
,直接关掉redis的写操作,默认为yes
stop-writes-on-bgsave-error yes
rdbcompression
开启后,redis
默认会通过LZF
算法压缩rdb
文件。这种方式会消耗CPU
,但是压缩后的大小远远小于内存,但是带来的收益却远远大于这点开销,通过压缩的文件无论是通过网络发送到从节点还是存储到硬盘的空间都是非常可观的。
rdbcompression yes
rdbchecksum
开启后,在存储快照后,还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。
rdbchecksum yes
说了那么多,可不可以给我演示一下RDB的使用方式
答: 没问题,我们首先需要存点数据,20s存3个值
127.0.0.1:6379> set k1 v1 OK 127.0.0.1:6379> set k2 v2 OK 127.0.0.1:6379> set k3 v3 OK
完成后查看是否生成rdb文件,确认无误后,我们将这个文件备份,并强制关闭redis服务端,模拟断电的场景
# 重命名rdb文件 [root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# mv dump.rdb dump.rdb.bak
此时我们再启动redis就会发现数据为空
127.0.0.1:6379> keys * (empty array)
我们将rdb文件还原,并重启redis,可以发现备份数据还原了
# 强制关闭redis [root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# ps -ef |grep redis |grep -v grep root 8956 1 0 23:22 ? 00:00:00 redis-server 127.0.0.1:6379 [root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# kill -9 8956 # 还原rdb,并启动redis [root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# mv dump.rdb.bak dump.rdb [root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# redis-server /root/redis/redis.conf [root@iZ8vb7bhe4b8nhhhpavhwpZ sbin]# redis-cli # 可以看到之前设置的数据都回来了 127.0.0.1:6379> keys * 1) "k3" 2) "k2" 3) "k1"
注:当我们使用shutdown指令也会自动触发bgsave,读者可以自行测试。
不错,那你可以说说RDB有哪些优缺点嘛?
答: 首先说说优点吧:
- rdb是紧凑压缩的二进制文件,非常实用与备份或者全景复制等场景。
- rdb恢复数据效率远远高于aof
而缺点如下:
- 无法做到毫秒级别的实时性持久化,尽管我们可以通过设置紧凑的save完成持久化,但是频繁的fork子进程进行持久化,很可能造成redis主进行长期阻塞。
- 存储的文件是二进制,不够直观,可能还存在某些兼容问题。
进阶
生产环境大内存的redis数据如何在持久化的时候保持数据一致性呢?
答: redis的rdb持久化是基于Copy on write (写时复制思想)
,redis
会fork
一个子进程完成数据持久化,再此期间发生的原数据修改或者写入的新数据都会生成一个数据副本存到一个新的内存区域中,bgsave
子进程快照完成后,再将这块内存区域同步到原来的内存区域中,等待下一次快照。
这样做的缺点也很明显,极端情况下,如果在bgsave
期间主进程数据都被改了,那么内存占用就是原来的两倍。
哦,那在进行快照操作的这段时间,如果发生服务崩溃怎么办?
答: 服务恢复的数据只会是上一次备份的rdb
文件数据,因为bgsave
子进程只会将操作成功的文件生成rdb
文件覆盖上一次备份的文件。
可以每秒做一次快照吗?
答: emmm,可以倒是可以,但是可能会有下面这几个问题:
- 频繁写入内存数据会给磁盘带来很大的压力,多个
fork
子进程抢占优先的磁盘带宽,前一个子进程没写完,后一个子进程又来写入。 rdb
持久化每次fork
子进程都会阻塞主进程,频繁fork
很可能导致主进程长期处于阻塞状态。
参考文献
到此这篇关于Redis持久化机制RDB的实现的文章就介绍到这了,更多相关Redis持久化机制RDB内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!