什么是持久化?
持久化的方式:
1.RDB——快照持久化
Redis可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。在创建快照之后,用户可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本,还可以将快照留在原地以便重启服务器时使用。
1.1触发机制-创建快照的主要三种方式
注意:在使用快照持久化来保存数据时,一定要记住:如果系统真的发生崩溃,用户将丢失最近一次生成快照之后更改的所有数据。因此,快照持久化只适用于那些即使丢失一部分数据也不会造成问题的应用程序。
-
save(同步)
客户端可以通过向Redis发送SAVE命令来创建一个快照,接到SAVE命令的Redis服务器在快照创建完毕之前将不再响应任何其他命令。SAVE命令并不常用,我们通常只会在没有足够内存去执行BGSAVE命令的情况下,又或者即使等待持久化操作执行完毕也无所谓的情况下,才会使用这个命令。
SAVE命令会阻塞Redis服务器响应其他命令:
文件策略和复杂度: -
bgsave(异步)
客户端可以通过向Redis发送BGSAVE命令来创建一个快照。对于支持BGSAVE命令的平台来说(除Windows基本都支持),Redis会调用fork来创建一个子进程,然后子进程负责将快照写入硬盘,而父进程则继续处理命令请求。
fork:当一个进程创建子进程的时候,底层的操作系统会创建改进程的一个副本,在Unix系统上面创建子进程的操作会进行如下优化:在刚开始的时候,父子进程共享相同的内存,直到父进程或者子进程对内存进行了写入之后,对被写入内存的共享才会结束。
文件策略和复杂度:
save与bgsave
- 自动生成RDB
如果用户设置了save配置选项,如 save 60 10000,那么从Redis最近一次创建快照之后开始算起,当“60秒之内10000次写入” 这个条件被满足时,Redis就会自动触发BGSAVE命令。如果用户设置了多个save配置选项,那么当任意一个save配置选项所设置的条件被满足时,Redis就会触发一次BGSAVE命令。
1.2触发机制-不容忽略方式
-
shutdown命令接收到关闭服务器的请求时,或者接收到标准TERM信号时。Redi会执行一个SAVE命令,阻塞所有客户端,不再执行客户端发送的任何命令,并在SAVE命令执行完毕之后关闭服务器。
-
当一个Redis服务器连接另一个Redis服务器,并向对方发送SYNC命令来开始一次复制操作的时候,如果主服务器目前没有在执行BGSAVE操作,或者主服务器并非刚刚执行完BGSAVE操作,那么主服务器就会执行BGSAVE命令。
1.3相关的配置参数
-
save: 里是用来配置触发 Redis的 RDB 持久化条件,也就是什么时候将内存中的数据保存到硬盘。比如“save m n”。表示m秒内数据集存在n次修改时,自动触发bgsave(这个命令下面会介绍,手动触发RDB持久化的命令)
save 900 1:表示900 秒内如果至少有 1 个 key 的值变化,则保存
save 300 10:表示300 秒内如果至少有 10 个 key 的值变化,则保存
save 60 10000:表示60 秒内如果至少有 10000 个 key 的值变化,则保存
当然如果你只是用Redis的缓存功能,不需要持久化,那么你可以注释掉所有的 save 行来停用保存功能。可以直接一个空字符串来实现停用:save ""
-
stop-writes-on-bgsave-error:默认值为yes。当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据。这会让用户意识到数据没有正确持久化到磁盘上,否则没有人会注意到灾难(disaster)发生了。如果Redis重启了,那么又可以重新开始接收数据了。
-
rdbcompression:默认值是yes。对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用LZF算法进行压缩。如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能,但是存储在磁盘上的快照会比较大。
-
rdbchecksum:默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。
-
dbfilename:设置快照的文件名,默认是 dump.rdb,建议dump-${port}.rdb 。
-
dir:设置快照文件的存放路径,这个配置项一定是个目录,而不能是文件名。默认是和当前配置文件保存在同一目录。
也就是说通过在配置文件中配置的 save 方式,当实际操作满足该配置形式时就会进行 RDB 持久化,将当前的内存快照保存在 dir 配置的目录中,文件名由配置的 dbfilename 决定。
1.4恢复数据
将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可,redis就会自动加载文件数据至内存了。Redis 服务器在载入 RDB 文件期间,会一直处于阻塞状态,直到载入工作完成为止。
获取 redis 的安装目录可以使用 config get dir 命令
载入的标识是如下命令:
1.5停止 RDB 持久化
有些情况下,我们只想利用Redis的缓存功能,并不像使用 Redis 的持久化功能,那么这时候我们最好停掉 RDB 持久化。可以通过上面讲的在配置文件 redis.conf 中,可以注释掉所有的 save 行来停用保存功能或者直接一个空字符串来实现停用:save ""
也可以通过命令:
redis-cli config set save " "
1.6RDB的优势和劣势
优势:
-
RDB是一个非常紧凑(compact)的文件,它保存了redis 在某个时间点上的数据集。这种文件非常适合用于进行备份和灾难恢复。
-
生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
-
RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
劣势:
-
RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作,如果不采用压缩算法(内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑),频繁执行成本过高(影响性能)
-
RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本Redis服务无法兼容新版RDB格式的问题(版本不兼容)
-
在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改(数据有丢失)
2.AOF
简单来说,AOF持久化会将被执行的命令写道AOF文件的末尾,以此来记录数据发生的变化。因此。Redis只要从头到尾重新执行依次AOF文件包含的所有写命令,就可以恢复AOF文件所记录的数据集。
2.1AOF的三种策略(appendfsync always|everysec|no)
-
always
每个Redis写命令都会被写入硬盘,从而将发生系统崩溃时出现的数据丢失减到最少。不过因为这种同步策略需要对硬盘进行大量写入,所以Redis处理命令的速度会受到硬盘性能的限制:转盘式硬盘(spinning disk)在这种同步频率下每秒只能处理大约200个写命令,而固态硬盘(SSD)每秒大概也只能处理几万个命令。(因为这个选项让Redis每次只写入一个命令,这种不断地写入少量数据的做法有可能会引发严重的写入放大(write amplification)问题,在某些情况下甚至会将固态硬盘的寿命从原来的几年降为几个月) -
everysec
为了兼顾数据安全和写入性能,用户可以考虑使用 everysec 选项,让Redis以每秒一次的频率对AOF文件进行同步。Redis每秒同步一次AOF文件时的性能和不使用任何持久化特性时的性能相差无几,而通过每秒同步一次AOF文件,Redis可以保证,即使出现系统崩溃,用户也最多只会丢失一秒之内产生的数据。当硬盘忙于执行写入操作的时候,Redis还会优雅地放慢自己的速度以便适应硬盘的最大写入速度。 -
no
若使用 no 选项,那么Redis将不对AOF文件执行任何显式的同步操作,而是由操作系统来决定应该在何时对AOF文件进行同步。这个选项在一般情况下不会对Redis的性能带来影响,但系统崩溃将导致使用这种选项的Redis服务器丢失不定数量的数据,另外,如果用户的硬盘处理写入操作的速度不够快的话,那么当缓冲区被等待写入硬盘的数据等填满时,Redis的写入操作将被阻塞,并导致Redis处理命令请求的速度变慢,因为这个原因一般来说并不推荐使用 no 选项。
三种策略对比:
2.2重写/压缩AOF文件
AOF持久化既可以将丢失数据的时间降低至1秒(甚至不丢失任何数据),又可以在极短时间内完成定期的持久化操作,但是也会出现两个问题:
- 因为Redis会不断地将被执行的写命令记录到AOF文件里面,所以随着Redis不断运行,AOF文件的体积也会不断增长,在极端情况下,体积不断增大的AOF文件甚至可能会使用完硬盘的所有可用空间。
- Redis在重启之后需要通过重新执行AOF文件记录的所有写命令来还原数据集,所以如果AOF文件的体积非常大,那么还原操作执行的时间就可能会非常长。
AOF重写:
AOF重写作用:
- 减少硬盘占用量
- 加快恢复速度
AOF重写实现两种方式:
-
bgrewriteaof命令
可以向Redis发送bgrewriteaof命令,这个命令会通过移除AOF文件种的冗余命令来重写(rewrite)AOF文件,使用AOF文件的体积变得尽可能地小。bgrewriteaof的工作原理和bgsave创建快照的工作原理非常相似:Redis会创建一个子进程,然后由子进程负责对AOF文件进行重写。因为AOF文件重写也需要用到子进程,所以快照持久化因为创建子进程而导致的性能问题和内存占用问题,在AOF持久化中也同样存在。更糟糕的是,如果不加以控制的话,AOF文件的体积可能会比快照文件的体积大好几倍,在进行AOF重写并删除旧AOF文件的时候,删除一个体积达到数十GB大的旧AOF文件可能会导致操作系统挂起数秒。 -
AOF重写配置
AOF持久化也可以通过设置配置选项来自动执行bgrewriteaof
- auto-aof-rewrite-percentage:AOF文件重写需要的尺寸
-
auto-aof-rewrite-min-size:AOF文件增长率
例子:
若auto-aof-rewrite-percentage=100 auto-aof-rewrite-min-size=64mb 并且启用了AOF持久化,那么当AOF文件体积大于64mb,并且AOF文件的体积比上一次重写之后的体积大了至少一倍(100%)的时候,Redis将执行bgrewriteaof命令。
如果AOF重写执行得过于频繁得话,可将auto-aof-rewrite-percentage选项得值设置为100以上。这种做法可以让Redis在AOF文件得体积变得更大之后才执行重写操作,不过也会让Redis在启动时还原数据集所需的时间变得更长。
- AOF其他配置
- appendonly yes(默认no,关闭):表示是否开启AOF持久化
- appendfilename “appendonly.aof”:AOF持久化配置文件的名称