redis的内容是存储在内存中的,高效,但是停电则消失。
Redis官方提供了两种不同的持久化方法来将数据存储到硬盘:
- 快照(Snapshot)
- AOF(Append Only File)只追加日志文件
一、快照
1. 特点:
这种方式可以将某一时刻所有的数据都写入磁盘,当然这也是redis的默认kaiq持久化方式,保存的文件是以.rdb形式结尾。因此这种方式也称之为RDB方式。
2. 快照生成方式
- 客户端方式:BGSAVE和SAVE指令
- 服务器配置自动触发
BGSAVE
客户端可以使用BGSAVE命令来创建一个快照,当接收到客户端的BGSAVE命令时,redis会调用fork1来创建一个子线程,然后子线程负责将快照写入磁盘中,而父进程则继续处理命令请求。
SAVE
客户端可以使用SAVE命令来创建一个快照,接收到save命令的redis服务器在快照创建完毕之前将不再响应任何其它的命令。
3. 服务器配置方式满足配置自动触发
-
用户在redis.conf中设置了save配置选项,redis会在save选项条件满足之后自动触发一次BGSAVE命令,如果设置多个save配置选项,当任意一个save配置选项条件满足,redis也会触发一次BGSAVE命令
-
如果在刚刚生成快照以后,新添加了数据,却还不能满足下一次生成快照,突然断电,或者系统宕机,那么数据也会丢失,所以redis提供了AOF的方式,甚至可以做到不丢失任何数据。
二、AOF只追加日志文件
- 特点
这种方式可以将所有客户端的写命令记录到日志文件中,该文件一秒同步一次,AOF持久化会将被执行的写命令写到AOF的文件末尾,以此来记录数据发生的变化,因此只要redis从头到尾执行一次AOF文件所包含的所有写命令,就可以恢复AOF文件的记录的数据集。 - 开启AOF持久化
在redis中,默认是没有开启AOF持久化机制的,需要在配置中开启。
vim redis.conf
appendonly no
改为appendonly yes
- 修改完之后重启,你会发现redis子目录多出appendonly.aof文件
之后对库的数据进行操作,再执行vim appendonly.aof
查看 appendonly.aof 文件,该文件的确存放的都是写命令。
- 日志追加频率
- always【谨慎使用】
每个命令都要被同步写入磁盘,严重降低redis速度。
SSD硬盘用户注意:大量的写会影响ssd硬盘使用寿命。 - everysec【推荐】
每秒执行一次同步显式的将多个写命令同步到磁盘(最多丢失一秒钟数据) - no 【不推荐】
由操作系统决定何时同步,可能会丢失不定量甚至全部。
- 修改同步频率
-修改appendfsync 指定everysec/always/no
三、AOF文件的重写
- AOF带来的问题
AOF的方式1也同时带来了另一个问题。持久化的文件会越来越大。例如,我们调用incr test命令100次,文件中必须保存全部的100条命令,其实由99条是多余的。因为要恢复数据库的状态其实文件中保存一条set test 100就够了。为了压缩aof的持久化文件,Redis提供了AOF重写(ReWriter)机制。 - AOF重写
用来在一定程度上减少AOF文件的体积 - 触发重写方式
a.客户端方式触发重写命令:
执行BGREWRITEAOF
命令,不会阻塞redis的服务
测试:
- 先查看appendonly.aof文件大小
- 再往库里重复写入命令,
- 然后再查看appendonly.aof文件大小(1560kb)
- 重写AOF(appendonly.aof)文件
- redis-server窗口查看重写状态(重写成功)
- 再去查看appendonly.aof文件大小(134kb)
结论:重写AOF文件能一定程度上减轻文件体积,提高了系统效率。
b. 服务器配置方式自动触发
- 配置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
设置为更大。
c. AOF文件重写原理(个人感觉很像MySQL转储sql文件及数据)
重写AOF文件是将这个内存中的数据库内容用命令的方式重写了一个新的aof文件,替换原有的文件这点和快照有点类似。
- 重写流程
1.redis调用fork,现有父子两个进程 子进程根据内存中的数据快照,往临时文件中写入重建数据库状态的命令
2.父进程继续处理client请求,除了把命令写入到原来的aof文件中,同时把收到的写命令缓存起来这样就能保证如果子进程重写失败的话并不会出现问题。
3.当子进程把快照内容写入以命令方式写道临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件。
4.现在父进程可以使用临时文件替换旧的AOF文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。
持久化的总结
- 两种持久化方案既可以同时使用(aof),又可以单独使用,在某种情况下也可以都不使用,具体使用哪种持久化方案取决于用户的数据和应用决定。
当一个进程创建子进程的时候,底层的操作系统会创建该进程的副本,在类unix系统中创建子线程的操作会进行优化:在刚开始的时候,父子进程共享相同内存,直到父进程或子进程对内存进行了写之后,对被写入的内存的共享才会结束服务。 ↩︎