Redis持久化的方式与实现原理

Redis是一款非关系型数据库,Redis之所以性能很好是因为它将所有的数据都保存在内存中,然而当Redis重启之后所有在内存中的数据都会丢失。在某些情况下我们会希望重启之后数据能够不丢失例如:

1.将Redis作为数据库使用的时候

2.将Redis作为缓存服务器使用,但是缓存击穿后会对性能造成很大的影响,所有缓存失效会造成缓存雪崩,使得服务器无法响应

这时候我们需要Redis能够对数据进行持久化,Redis支持两种方式的持久化一种是RDB方式,另一种是AOF方式。

一.RDB
RDB方式的持久化是通过快照来完成的,Redis会将内存中的数据生成一个副本并保存在硬盘上,在以下几种情况下Redis会进行RDB方式的持久化。

1.通过配置自动进行的持久化
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。

save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。

save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照
2.通过SAVE与BGSAVE命令进行持久化
执行SAVE命令的时候服务器会阻塞所有客户端的请求,当数据库中的数据较多时可能会导致长时间无响应,所以不推荐这种方式。BGSAVE命令会以异步的方式进行持久化,此时服务器还可以继续响应请求

3.通过执行FLUSHALL命令
FLUSHALL会清空内存中的数据,并触发一次持久化

4.执行复制的时候
当设置了主从模式,Redis会在复制的时候自动进行快照

快照的原理
Redis会通过fork()函数复制一个当前进程的子进程,然后子进程进行持久化操作,而父进程继续响应客户端的请求,当子进程持久化操作完成后会将生成的快照文件替换之前的快照文件,这样Redis就完成了一次持久化。ps(执行fork函数的时候,操作系统会使用一种写时复制的技术,也就是刚执行fork函数时父进程与子进程共响内存空间,只有在父进程要修改内存中的某一片数据时操作系统才会复制这一片内存给子进程使用避免对子进程造成影响。写时复制的技术保证了虽然从逻辑上是复制了一份内存空间,但是实际上内存的使用空间不会增大一倍,但是如果在执行持久化的过程中父进程进行频繁的内存修改操作可能会导致内存快速的增长)

二.AOF
默认情况下Redis是没有开启AOF方式的持久化,可以通过appendonly参数启用:appendonly yes

持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小

同步硬盘数据
虽然在AOF模式下每次写命令都会被写入AOF文件中,但是由于操作系统的缓存机制的限制,文件并没有真正的 写入硬盘中,而是进入了操作系统的缓存,操作系统默认毎30秒会将缓存中的数据刷入硬盘,但如果服务器崩溃这30秒所有的数据库写操作就会丢失,这在某些对数据完整性要求比较高的场景下是无法容忍的,我们可以通过以下配置参数来主动的让操作系统刷新缓存

appendfsync always     #每次有数据修改发生时都会写入AOF文件。

appendfsync everysec  #每秒钟同步一次,该策略为AOF的缺省策略。

appendfsync no          #从不同步。高效但是数据不会被持久化

两种方式的比较
RDB 是一个非常紧凑(compact)的文件,它保存了 Redis 在某个时间点上的数据集。这种文件非常适合用于进行备份:比如说,你可以在最近的 24 小时内,每小时备份一次 RDB 文件,并且在每个月的每一天,也备份一个 RDB 文件。这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。
RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。
RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
如果你需要尽量避免在服务器故障时丢失数据,那么 RDB 不适合你。虽然 Redis 允许你设置不同的保存点(save point)来控制保存 RDB 文件的频率,但是,因为RDB 文件需要保存整个数据集的状态,所以它并不是一个轻松的操作。因此你可能会至少 5 分钟才保存一次 RDB 文件。在这种情况下,一旦发生故障停机,你就可能会丢失好几分钟的数据。
Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写:重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
AOF 文件有序地保存了对数据库执行的所有写入操作,这些写入操作以 Redis 协议的格式保存,因此 AOF 文件的内容非常容易被人读懂,对文件进行分析(parse)也很轻松。导出(export) AOF 文件也非常简单:举个例子,如果你不小心执行了 FLUSHALL 命令,但只要 AOF 文件未被重写,那么只要停止服务器,移除 AOF 文件末尾的 FLUSHALL 命令,并重启 Redis ,就可以将数据集恢复到 FLUSHALL 执行之前的状态。
对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。在一般情况下,每秒 fsync 的性能依然非常高,而关闭 fsync 可以让 AOF 的速度和 RDB 一样快,即使在高负荷之下也是如此。不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。
————————————————

原文链接:https://blog.csdn.net/z956281507/article/details/80288669

你可能感兴趣的:(Redis)