何为持久化
- 所谓持久化就是将数据用内存保存到磁盘的工程, 其目的就是防止数据的丢失
因为内存中的数据 在服务器重启之后就会丢失,⽽磁盘的数据则不会,因此为了系统的稳定起⻅,我们需要将数据进⾏持久 化。同时持久化功能⼜是 Redis 和 Memcached 最主要的区别之⼀,因为 Redis ⽀持持久化⽽ Memcached 不⽀持
快照方式(RDB, Redis Database)
- 将某一时刻的内存中的数据以二进制的方式压缩后写入到磁盘中
- 对于一个Redis服务器来说,它的所有非空数据库以及数据库中的所有键值对就是当前数据库的状态。所以只需要将数据库的状态保存在硬盘当中,即使服务器停机或者断电,只要硬盘中存储的状态还在,就可以通过它来还原数据库原来的状态。
- 为了保证文件的安全以及容量更小,RDB持续化所生成的RDB文件是一个经过压缩的二进制文件,通过这个文件就可以还原数据库的状态。 好比mysql中的undo log
SAVA与BGSAVA
RDB持久化根据执行持久化的对象不同又分为SAVA和BGSAVA两种方式
SAVA即让Redis服务进程来执行持久化,所以直到RDB持久化结束之前,Redis服务进程会一直处于阻塞状态,无法处理任何命令。
BGSAVE则会通过fork()来创建一个子进程,然后让子进程来接管RDB持久化,而父进程继续处理命令请求
由于SAVA的会导致主进程的阻塞,所以使用时基本不会考虑,所以通常我们都会默认使用BGSAVA来进行,下面我指的也都是BGSAVA
优点
- RDB的内容为二进制形式, 占用的内存小, 更适合做为备份文件
- RDB对灾难恢复很有用, 因为其的小巧紧凑, 可以很快的传输到远程的服务器上进行Redis服务恢复
- 可以很大程度提高Redis的运行速度, 因为每次持久化时, 主进程都会fork一个子进程来进行数据持久化到磁盘, 这样就减少了主进程的任务负担, 从而提高了主进程的效率
- 与AOF格式的文件相比, RDB文件重启更快
- RDB可以提高Redis的运行速度,因为使用BGSAVA持久化时会fork出子进程进行持久化的I/O操作. == 主进程不会受到干扰==。
缺点
- RDB只能保存某个时间段间隔的数据(也就是快照与快照之间有时间 间隔), 如果在一个间隔中途Redis服务器突然挂了, 就有丢失数据的风险
- 上面说到RDB进行持久化操作的时候会创建一个子进程来完成, 但是如果某时间段数据集非常大, fork()很多的子进程很耗时, 并且如果CPU处理能力不行的话, 可能会导致Redis停止位客户端服务一段时间(因为Redis操作很重要一个特性就是其内存是原子操作)
文件追加方式(AOF, Append Only File)
-
记录所有操作的命令, 并以文本的形式追加到文件中
-
AOF持久化其实就是保存Redis服务器所执行的命令来保存数据库的状态,将命令追加到AOF文件的末尾(Append Only File),AOF的核心其实就是将所有执行过的命令重新执行,来恢复状态, 好比mysql中的redo log
-
当服务器启动时,就会读取AOF文件中的所有命令,将其在服务器上重新执行一次,来恢复服务器的状态。
-
随着服务器存储的数据越来越多,此时AOF保存的命令也越来越多,文件的体积就会变得非常大,这样就可能导致对Redis服务器以及宿主机造成影响,并且随着文件的增大,使用AOF来进行数据还原需要的时间也就更多。
-
所以AOF引入了重写的机制,即只保存能够获取最终结果的命令, 重写的流程很简单,就是去直接读取当前数据库中的键值状态,然后构造出对应的命令来进行保存
例如插入1,2,3,4,5 然后删除4,5,记录是就直接进行一次记录lpush 1 2 3,就可以直接省去了中间的操作。(实现原理是重写缓冲区) -
并且和RDB的BGSAVA一样,为了不阻塞主进程,所有的重写操作都会通过创建子进程来进行,并且由于子进程创建时会通过写时拷贝机制带有服务器数据的副本,所以也不需要对数据进行加锁就可以保证安全,提高了效率
-
但是这时又引入了一个问题,如果父进程接受了新的命令,这些命令可能就会对数据库的状态进行修改,这样就会导致重写后的AOF文件所保存的状态和当前的数据库状态不一致。
-
为了解决这个问题,服务器新增了一个AOF重写缓冲区,将两个AOF的过程给分割开
服务器流程
- 执行客户端发送来的新命令
- 将执行后的写命令追加到AOF缓冲区中
- 将执行后的写命令追加到AOF重写缓冲区中
优点
- AOF 保存的数据更加完整, 数据不易丢失, AOF 提供了三种保存策略:每次操作保存、每秒钟保存⼀次、跟随 系统的持久化策略保存,其中每秒保存⼀次,从数据的安全性和性能两⽅⾯考虑是⼀个不错的选择,也 是 AOF 默认的策略,即使发⽣了意外情况,最多只会丢失 1s 钟的数据
- AOF使用的是命令追加的写入方式, 所以不会出现文件损坏的问题, 即使意外损坏也较易恢复
- AOF 持久化⽂件,⾮常容易理解和解析,它是把所有 Redis 键值操作命令,以⽂件的⽅式存⼊了磁 盘。即使不⼩⼼使⽤ flushall 命令删除了所有键值信息,只要使⽤ AOF ⽂件,删除最后的 flushall 命令,重启 Redis 即可恢复之前误删的数据.
缺点
- 对比RDB保存相同的数据 使用AOF资源消耗更大
- Redis 负载较高的时候, 使用RDB更好
- RDB 使⽤快照的形式来持久化整个 Redis 数据,⽽ AOF 只是将每次执⾏的命令追加到 AOF ⽂件 中,因此从理论上说,RDB ⽐ AOF 更健壮。
混合持久化方式
- 混合顾名思义就是结合了RDB和AOF的优点, 在写入的时候, 先把数据以RDB的形式写入文件的开头, 再将后续的操作命令以AOF的格式保存到文件中去, 这样就保证Redis重启时的速度, 又能减轻数据丢失的风险
- 也就是mysql中的redo log和undo log一起使用, 但是这里是将俩个文件合并为一个文件, 文件开头记录压缩后的二进制数据, 尾巴记录操作命令
优点
- 结合RDB的特点和AOF的特点, 开头以RDB的格式, 可以快启动, 同时结合AOF的特点, 可以减少数据丢失的风险
缺点
- 结合俩者的特性, 导致AOF文件的可读性下降
- 兼容性差, 如果开启混合持久化AOF文件, 不能使用Redis4.0之前的版本
- 可以在 redis-cli 命令⾏中执⾏
config set aof-use-rdb-preamble yes
来开启混合持久化,当 开启混合持久化时 Redis 就以混合持久化⽅式来作为持久化策略;当没有开启混合持久化的情况下,使⽤config set appendonly yes
来开启 AOF 持久化的策略,当 AOF 和混合持久化都没开启的情况 下默认会是 RDB 持久化的⽅式。
其优点级: 混合持久化 > 文件追加持久化 > 快照持久化