client Redis[内存] --> 内存数据、磁盘数据----> 磁盘,Redis官方提供了两种不同的持久化方案将内存中的数据存储在硬盘中:
快照(Snapshot)
AOF只追加日志文件。
1、快照(Snapshot)
1、快照的特点:
快照的方式是将某一时刻的数据全部写入到磁盘中,也是Redus中默认的开启持久化的方式。保存的文件是以.rdb结尾的文件。
需要注意的是:redis在哪个目录下启动,哪一个就是redis的工作目录,后面的rdb持久化或者AOF持久化,产生的文件都存在于redis的当前工作目录下。在哪里启动就会读取哪里的快照文件
2、快照的生成的方式:
1、客户端的方式:通过bigsave、save指令
1、bigsave指令
当主进程接收到客户端的写命令的请求,主进程会调用fork函数来创建一个子进程,子进程负责进行快照,并将快照写入到磁盘中。此时的父类会继续的接受客户端的写数据的请求。
2、save指令
当主进程接收到客户端的写数据的请求,主进程会调用fork函数来创建一个子进程来进行快照并将数据存入磁盘中,此时子进程会拒绝外界客户端写数据的请求一直到子进程结束。
fork :当一个进程创建子线程的时候,底层的操作系统会创建进程的一个副本,在类似于unix系统中创建子线程的操作会进行优化,在刚开始的时候,父子进程共享相同的内存,知道父类进程或者子类进程对内存进行了写之后,对被写入的内存的共享才会结束服务
2、配置器配置自动触发
1、修改配置文件redis.conf文件,用户在redis.conf配置文件中设置了save配置选项,redis会在save选项条件满足之后自动的触发一次bgsave命令,如果设置多个save配置选项,当任意一个save配置文件条件满足,redis也会触发一次bgsave命令
3、服务器接收客户端shutdown指令
当redis通过shutdown指令接收到关闭服务器的请求时,会执行一个save命令,阻塞所有的客户端,不再执行客户端执行发送的任何命令,并且在save命令执行完毕之后关闭服务器。
修改快照的位置和名称: redis.conf 配置文件中:#1.修改生成快照名称
- dbfilename dump.rdb# 2.修改生成位置
- dir ./
2、AOF只追加日志文件
1、特点:
将客户端的所有的写的命令都记录在日志文件中,AOF持久化会将被执行的写命令写到AOF的文件中。以此来记录数据发生的变化。因此只要Redis从头执行一下这个日志文件就可以恢复到原先的数据集。
2、开启AOF:
在redis中是默认不开启AOF持久化的,需要在配置文件中开启:
1、开启AOF持久化:修改 appendonly yes
修改 appendfilename "appendonly.aof" 指定生成文件名称
3、日志追加的频率:
# 1.always 【谨慎使用】
- 说明: 每个redis写命令都要同步写入硬盘,严重降低redis速度
- 解释: 如果用户使用了always选项,那么每个redis写命令都会被写入硬盘,从而将发生系统崩溃时出现的数据丢失减到最少;遗憾的是,因为这种同步策略需要对硬盘进行大量的写入操作,所以redis处理命令的速度会受到硬盘性能的限制;
- 注意: 转盘式硬盘在这种频率下200左右个命令/s ; 固态硬盘(SSD) 几百万个命令/s;
- 警告: 使用SSD用户请谨慎使用always选项,这种模式不断写入少量数据的做法有可能会引发严重的`写入放大`问题,导致将固态硬盘的寿命从原来的几年降低为几个月。# 2.everysec 【推荐默认】
- 说明: 每秒执行一次同步显式的将多个写命令同步到磁盘
- 解释: 为了兼顾数据安全和写入性能,用户可以考虑使用everysec选项,让redis每秒一次的频率对AOF文件进行同步;redis每秒同步一次AOF文件时性能和不使用任何持久化特性时的性能相差无几,而通过每秒同步一次AOF文件,redis可以保证,即使系统崩溃,用户最多丢失一秒之内产生的数据。 # 3.no 【不推荐】
- 说明: 由操作系统决定何时同步
- 解释:最后使用no选项,将完全由操作系统决定什么时候同步AOF日志文件,这个选项不会对redis性能带来影响但是系统崩溃时,会丢失不定数量的数据,甚至丢失全部数据,另外如果用户硬盘处理写入操作不够快的话,当缓冲区被等待写入硬盘数据填满时,redis会处于阻塞状态,并导致redis的处理命令请求的速度变慢。
4、修改同步的频率:
# 1.修改日志同步频率
- 修改appendfsync everysec|always|no 指定
3、AOF重写:
1、AOF带来的问题:
AOF会将所有写数据的命令都写入到日志文件中,假设连续的一百次操作都是相同,此时AOF会记录这一百次的记录,就会导致文件过大,因为要恢复数据库的状态其实文件中保存一条数据就够了,为了压缩aof的持久化文件Redis提供了AOF重写(ReWriter)机制。
2、AOF重写:
在一定的程度上可以减少AOF文件的体积,并且能够保证数据不丢失。
3、AOF触发的方式:
1、客户端触发的方式:
bgrewriteaof
2、服务器配置方式自动的触发:
- 配置redis.conf中的auto-aof-rewrite-percentage选项
- 如果设置auto-aof-rewrite-percentage值为100和auto-aof-rewrite-min-size 64mb,
并且启用的AOF持久化时,那么当AOF文件体积大于64M,并且AOF文件的体积比上一次重写之后体积大了至少一倍(100%)时,会自动触发,
如果重写过于频繁,用户可以考虑将auto-aof-rewrite-percentage设置为更大
4、AOF的重写机制的原理
1、7.0.0版本之前:
1、首先,当主进程触发AOF重写机制的时候,主进程会调用fork函数创建一个子进程进行快照,并将生成的dump文件用指令的方式写入临时文件中,子进程会将完成写入临时文件通知给主进程。
2、此时主进程还会继续接受客户端的写数据的命令,主进程会继续向原先的aof文件中记录命令,同时也会将命令缓存到内存中,当主进程接受到子进程写入完成这个命令的时候,会将缓存在内存中的写数据指令同步到临时文件中。
3、当内存中的指令写入后,临时文件就会替换掉原先的aof文件。
2、7.0.0版本之后:
1、首先,当主进程触发AOF重写机制的时候,主进程会调用fork函数创建一个子进程进行快照,并将生成的dump文件用指令的方式写入临时文件中,和原先快照文件一起以命令的方式写入到临时文件中。
2、此时主进程还会继续接收客户端的写数据的命令,此时将命令写入新的增量文件中,同时也会将命令写入到就的增量文件中(aof文件)。
3、然后将旧的增量文件和临时文件合并生成一个临时清单
4、底层通过读取这个临时清单去重写生成一个新的rdb文件去替换原先旧的基本文件。
与之前的最大的改变就是将原先的单个AOF文件拆分成一个基本文件和多个增来文件,基本文件负责的是重写AOF之前已经存在的数据和一些快照的数据。增量文件负责的是一些增量的修改。都会存在在一个单独的文件中,并由清单文件所管理。
5、总结:
两种持久化方案既可以同时使用(aof),又可以单独使用,在某种情况下也可以都不使用,具体使用那种持久化方案取决于用户的数据和应用决定。
无论使用AOF还是快照机制持久化,将数据持久化到硬盘都是有必要的,除了持久化外,用户还应该对持久化的文件进行备份(最好备份在多个不同地方)。