目录
1. 什么是RDB
2. save 和 bgsave 命令主动保存数据
2.1 save
2.2 bgsave
3. Redis 内部自动RDB机制
4. RDB 底层是如何实现 bgsave 的?
5. RDB 的缺点
6. 什么是AOF?
7. AOF文件的缺点?
8. AOF 重写文件配置
9. RDB 与 AOF 的区别
1. 什么是RDB
RDB全称是 Redis Database file(Redis数据备份文件),也被叫做Redis数据快照。
它的原理也很好理解,因为Redis本身是基于内存的,一旦服务器宕机或停电,数据就会丢失,因此 Redis 它本身就带有数据备份的一个功能,它会每隔一段时间将数据从内存写入到磁盘进行保存,保存的数据形成的文件我们就称它为快照,当我们重启 Redis 之后,它就会再次读取快照文件中的数据,将数据恢复,防止数据的丢失,RDB文件默认保存在当前运行目录。
如下图所示,我使用 FinalShell 启动了Redis 的客户端server与服务端cli,pingPong正常,set存和get取也没问题,我们可以看到,在当前运行目录 "myredis" 下,就有一个dump.rdb的文件。它就是数据快照文件
2. save 和 bgsave 命令主动保存数据
2.1 save
save 命令是由 Redis 主进程来执行RDB操作,因为Redis 是单线程的,所以该命令会阻塞所有命令,我们只需要输入 save 即可开启快照保存。
如下图所示,我使用 save 命令保存数据,然后关闭Redis再重新启动,此时我没有存储数据,再次 get 获取刚才存储的 name1,可以看到我仍然可以获取到,这就是 save 的功能,可以将我们的数据进行持久化保存。
但一般情况下我们不推荐使用这个命令,因为它会阻塞命令,而且如果内存中保存的数据量较大,写操作是非常耗费时间的。
2.2 bgsave
bgsave 全称也叫 Background saving started,意味后台保存,它是来开启一个子进行保存工作,而主进程则不受影响。
这里的话也很简单,就和刚才一样运行以下命令即可,就不做演示了。
3. Redis 内部自动RDB机制
除了刚才我所说的手动保存数据的两个命令以外,Redis 内部还提供了自动触发RDB机制,我们可以在 redis.conf 配置文件中找到。
这里补充一点,Redis 内部的RDB机制默认也是使用的 bgsave 命令。
图中的 save 3600 1 表示3600秒之内有一次修改则进行RDB,save 300 100 表示300秒内有100此操作进行一次RDB,save 60 10000 表示60秒内有一万次操作进行一次RDB。
我们的RDB触发机制应该根据实际业务需求做设置,不能让 basave 过于频繁,尽管是子进程在保存,但还是会消耗资源;但也不能设置的较难触发,否则一旦长时间数据未保存,宕机造成数据丢失的后果也是较为严重的,因此我们需要在这两个方面做取舍,设置一个合理的触发时机,通常我们就可以选择 save 300 100,也可以自定义设置。
4. RDB 底层是如何实现 bgsave 的?
当 Redis 在进行bgsave 持久化操作时,刚才我们知道了,该操作是开启了一个子进程来执行的。bgsave 命令虽然开启了一个子进程避免主进程阻塞,但是在 fork 主进程的这个过程中,主进程仍然是处于阻塞状态的。此时主进程就不能接受用户请求。
得到子进程之后,子进程就可以共享主进程的内存数据,然后读取内存中的数据写入到 RDB 文件。大致流程如下图所示
Redis 是把数据存储在内存中的,但是在 Linux 操作系统底层,操作系统它是不会让这些线程去直接接触内存中的数据的,而是给进程一个页表,你可以把它理解为名单,你要做什么操作,直接在名单上去做,然后操作系统会代替你去执行。而我们在进行 fork 时,其实就是 fork 的页表,然后从页表中去读取数据,再写入到磁盘中。
但是这种情况下会有个问题,如果我的子进程正在读写数据,而主进程却要去修改数据,这个时候就会产生冲突。
因此,为了解决这种情况的发生,fork 采用的是copy-on-write 的技术。
当我们子进程向磁盘去写数据的时候,fork 会把内存中的可能产生冲突的共享数据标记为 readOnly(只读),任何一个进程都只能来读数据而不能写数据,当我们的主进程想要去修改数据的时候,它会先把要写的数据完整的拷贝一份出来(如下图数据B副本),然后对拷贝的数据进行写操作,当我们主进程再去读的时候,也会读到拷贝的数据,主进程页表与内存中数据的映射关系发生了改变。如下图所示
这是少数数据发生修改时可能出现的情况,还有一种比较罕见的情况,如果我们的数据较多,写的过程比较慢,在这个过程中,大量的数据都发生了修改,那么在操作系统底层会把这些修改的数据全部复制一份,如果再复制数据之前,内存已经快要被Redis 的数据占满了,那么在复制数据的过程中,就会出现内存溢出的情况各位明白吧,就是你现在需要这么多内存空间去复制数据,但是内存不够了,导致内存溢出。这种情况虽然比较罕见,但我们仍需要考虑在内,因此,我们Linux 操作系统在给 Redis 分配内存的时候,通常不会把全部的内存全部交给Redis,而是会保留一部分,防止内存溢出这种情况的发生。
5. RDB 的缺点
通过上面的描述,我们也大概能总结出RDB持久化方案的两个缺点
(1)RDB 执行时间间隔长,两次RDB之间写入数据有丢失风险;
(2)fork 子进程,压缩,写出RDB文件都比较耗时;
6. 什么是AOF?
AOF 全程 Append Only File(追加文件)。Redis 处理的每一个命令都会记录在AOF文件中,可以把它看作是命令日志文件。
AOF在Redis 中是默认关闭的,需要我们在配置文件中去开启,在配置文件中找到相关配置如下。
appendonly:默认为no,改为yes即可进行开启;
appendfilename:"appendonly.aop" 是AOF的文件名称,这里不需要改;
下面还有一个 appendfsync 表示命令记录的频率。
always:表示每执行一次写命令,立即记录到AOF文件中;
everysec:写命令执行先放入AOF缓冲区,然后每隔一秒将缓冲区数据写到AOF文件中,是默认选项;
no:写命令执行先放入缓冲区,由操作系统决定何时写入到磁盘;
三者的对比如下图所示
7. AOF文件的缺点?
AOF 文件它会把所有的操作命令全部都记录下来,就算你对同一个数据进行多次修改操作,但是AOF文件仍然还是会把所有之前的操作命令全部都记录下来,所以AOF文件的大小通常都会比RDB文件要大。
但是,我们可以通过 "bgrewriteaof" 命令让 AOF 文件执行重写功能,用最少的命令达到小童的效果。
举例,我在对 Redis 进行了三次操作,set name zhangsan;set age 18;set name lisi;
经过AOF重写功能之后,上面的三个命令就会转化成 mset name lisi age 18;将三个命令简化成一个命令,减少了所占的存储空间。
8. AOF 重写文件配置
Redis 的AOF文件重写也是有触发阈值的,我们可以使用默认的,也可以在 redis.conf 配置文件中自行配置,这里我截取了配置文件中的一段
auto-aof-rewrite-percentage:后面表示的是百分数,这次的文件相比上次的文件体积增加了百分之百时,就会触发重写;
auto-aof-rewrite-min-size:表示AOF 文件最小为64mb 时会触发重写;
9. RDB 与 AOF 的区别
RDB与AOF都有各自的优缺点,它们的区别大致就如下表中所呈现的,在实际开发过程中往往会结合二者来使用。