Redis_持久化机制
redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到磁盘来保证持久化,持久化可以避免因进程退出而造成数据丢失;
一、一种是RDB持久化
在指定的时间间隔内,将内存当中的数据集快照写入磁盘,也就是行话将的Snapshot快照,它恢复时是将快照文件直接读到内存
redis提供两种方式进行持久化
1.RDB
1.1 原理是redis 会单独创建(fork)一个与当前线程一模一样的子进程进行持久化,会先将数据写入到一个临时文件中,待持久化结束了,在用这个临时文件替换上次持久化好的文件,整个过程中,主进程不进行任何的IO操作,这确保了极高的性能。
如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效,RDB的缺点是最后一次持久化后的数据可能丢失。
1.2 Fork 的作用是复制一个与当前一样的进程,新进程的所有数据(变量,环境变量,程序计数器等)数值都和原进程一致,但是一个全新的进程,并作为原进程的子进程
1.3 保存的是dump.rdb文件
1.4 配置位置/usr/local/bin/dump.rdb
1.5 如何触发RDB快照
1.配置文件中默认快照配置 也就是冷拷贝后重新使用 (也就是重启服务)
可以cp dump.rdb dump_new.rdb
2.命令save或者是bgsave
save:save时只管保存,其他不管,全部阻塞
set k10 v10
如果想立即保存M,可以不等到设置的单位时间内保存dump.rdb文件
save 立即将改动的命令保存起来
命令save或者是bgsave
save :时只管保存,其他的不管,全部阻塞
bgsave:Redis 会在后台异步进行快照操作,快照的同时还可以相应客户端请求,可以通过lastsave
命令获取最后一次成功执行快照的时间
save命令:阻塞当前redis,直到RDB持久化过程完成为止,若内存实例比较大会
造成时间阻塞(线上环境不建议使用它)
bgsage命令:redis进程执行fork操作创建子进程,由子进程完成持久化,阻塞
时间很短(微妙级),是save的优化,在执行redis-cli shutdown关闭
redis服务时,如果没有开启AOF持久化,自动执行bgsave;
stop-writes-on-bgsave-error
stop-write-on-bgsave-error yes Redis 执行save命令的时候,将禁止写入
bgsave命令,它是一个异步保存命令,也就是系统将启动另一条进程,
把Redis 的数据保存到对应的数据文件中,它和save命令最大的不同是它不会阻塞客户端的写入,
也就是执行bgsave的时候,允许客户端继续读/写redis.
在默认情况下,如果redis执行bgsave失败后,Redis将停止接受写操作,这样一种强硬的方式让用户数据
不能正确的持久化到磁盘,否则就会没人注意到灾难的发生,如果后台保存进程重新启动工作了,Redis
也将自动允许写操作,然而如果安装了靠谱的监控,可能不希望redis这样做,那么可以将其修改为no
rdbcompression:
默认是yes。压缩,对于存储到磁盘中的快照,可以设置是否进行压缩存储,
如果是的话,redis会采用LZF算法进行压缩,如果不想消耗CPU进行压缩
可以设置为关闭功能
rdbchecksum:
在存储快照后,还可以让redis使用CRC64算法来进行数据校验,但是这样做会增大
约10%性能消耗,如果希望获取到最大的性能提升,可以关闭此功能
dbfilename
dump.rdb
dir
3.执行flushall命令,也会产生dump.rdb文件,但是里面是空的,无意义
1.6 如何恢复
将备份文件(dump.rdb)移动到redis安装目录并启动服务即可
config get dir 获取目录
1.7 优势
适合大规模的数据恢复,适合于备份,全量复制,快于AOF方式
对数据完整性和一致性要求不高
1.8 劣势
1.在一定间隔时间做一次备份,所以如果redis意外down,就会丢失最后一次快照后的所有修改
2.Fork时,内存中的数据被克隆了一份,大致2倍的膨胀需要考虑
3.无法做到实时持久化,每次都咬创建子进程,频繁操作成本过高
1.9 如何停止
动态所有停止RDB保存规则的方法:redis-cli config set save ""
1.11 这个命令是否对rdb文件进行检验,如果是将对db文件检验,从dbfilename的配置可以知道,
rdb文件实际是Redis持久化的数据文件
RDB小总结
1.RDB 是一个非常紧凑的文件
2.RDB 在保存RDB文件时父进程唯一需要做的就是fork出一个子进程来做,
所以RDB持久化方式可以最大化redis的性能
3.与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些
1.数据丢失风险大
2.RDB 需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候
fork的过程非常耗时,可能会导致Redis在一些毫秒级不能响应客户端请求
二、另外一种是AOF(append only file)持久化
2.1是什么:以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录)只许追加文件但不可 以改写文件,redis启动之初会读取该文件重新构建数据,换而言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
流程说明:
1.所有的写入命令(set hget)会append追加到aof_buf缓冲区中
2.AOF缓冲区向硬盘做sync同步-->为了减轻压力
3.随着AOF文件越来越大,需要定期对AOF文件rewrite重写,达到压缩
4.当redis服务重启,可load加载AOF文件进行回复
AOF 和RDB 可以同时共存的,先加载AOF 文件
2.2 /usr/local/bin 目录下 修复aof文件
redis-check-aof --fix appendonly.aof
2.3 appendonly no(默认值) yes是打开aof持久化
2.4 APPEND ONLY MODE追加
only 模式的设置,默认情况下redis采用异步方式dump数据到磁盘上,极端情况下可能导致丢失部分数据
(比如服务器宕机),如果数据比较重要,不希望丢失,可以启动直写的模式,这种模式redis会将所有接收
的写操作同步到appendonly.aof文件中,该文件会在redis服务器启动时在内存中重建所有得数据。注意这种模式
对系统的性能影响非常大
1.appendonly yes //启用aof持久化方式 --默认 no 指定是否启用直写模式
2.appendfilename --appendonly.aof 直写模式默认文件名
3.appendfsync 调用fsync()方式让操作系统写数据到磁盘上,数据同步方式有一下几种
1.Always :同步持久化每次发生数据变更会立即记录到磁盘,性能较差,但数据完整性比较好 -->(不推荐使用)
2.Everysec:出厂默认推荐,异步操作,每秒记录,如果一秒内宕机,有数据丢失 -->(推荐)
3.No 不调用fsync,由操作系统决定何时同步,比如快的模式; --> (操作系统自身的同步)
Rewrite 重写参数
4.No-appendfsync-on-rewrite,重写时是否可以运用Appendfsync,用默认no即可,保证数据安全性
当AOF fsync策略为always或everysec,后台保存进程会执行大量的I/O操作,
某些linux配置下redis可能会阻塞过多fsync()调用
正在导出rdb快照过程中,要不要停止同步aof
5.Auto-aof-rewrite-min-size 设置重写的基准值 64M 默认值 (生产一般3G起)
6.Auto-aof-rewrite-percentage 设置重写的基准值 100 默认值
2.5 AOF 启动/修复/恢复
正常恢复
启动:设置yes
将有数据的aof文件复制一份保存到对应目录(config get dir)
恢复:重启redis然后重新加载
异常恢复
启动:设置yes
备份被写坏的AOF文件
修复:Redis-check-aof --fix 进行修复
恢复:重启redis然后重新加载
2.6 Rewrite
1.是什么:AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制
当AOF文件的大小超过设定的阙值时,Redis就会启动AOF文件的内容压缩
只保留可以恢复数据的最小指令集,可以使用命令bgrewriteaof
2.重写原理:AOF文件持续增长而过大时,会fork出一条新进程来讲文件重写(也就是先写临时文件最后在rename)
遍历新进程的内存中数据,每条记录有一条的set语句,重写aof文件的操作,并没有读取旧的aof文件
而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照类似
3.触发机制:redis会记录上次重写时的AOF文件大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件
大于64M时触发
2.7 优势
1.每秒同步:appendfsync always(总是写入aof文件,并完成磁盘同步)
2.每修改同步:appendfsync everysec (每一秒写入aof文件,并完成磁盘同步)
3.不同步:appendfsync no (写入aof文件,从不同步磁盘)
从持久化的角度讲,always最安全,从效率上, no 最快,而redis默认设置进行了折中,选择了everysec,合情合理
2.7.1 no-appendfsync-on-rewrite-no
它指定是否在后台AOFrewrite(重写)期间调用fsync,默认是no,表示要调用fsycn(无论后台是否有子进程在刷盘)
bgwriteaof机制 在一个子进程进行aof重写,从而不阻塞主进程对其余命令的处理,同时解决了aof 文件过大问题
现在问题出现了,同时在执行bgwriteaof操作和主进程写aof文件的操作,两者都会操纵磁盘,而bgwriteaof往往会
涉及大量磁盘操作,这样会造成主进程在写aof文件的时候出现阻塞的情形,现在no-appendsync-on-rewrite参数出现
如果该参数设置为no,这说明并没有执行磁盘操纵,只是写入了缓存区,因为这样并不会造成阻塞(因为没有竞争磁盘)
但是如果这个时候redis挂掉,丢失多少数据?在linux的操作系统的默认设置下,最多会丢失30秒数据
因此,如果应用系统无法忍受延迟,而可以容忍少量的数据丢失,则设置为yes。如果应用系统无法忍受数据丢失,则设置为no。
2.7.2 auto-aof-rewrite-precent 100
他指定Redis重写AOF文件的条件,默认100,表示与上次rewrite的AOF文件大小相比,当前AOF文件增长量超过上次
AOF文件大小的100%,就会触发backgroundrewrite ,若配置为0,则会禁用自动rewrite
2.7.3 auto-aof-write-min-size 64mb
他指定rewrite的AOF文件大小,若AOF文件小于该值,即使当前文件的增量比例达到auto-aof-rewrite-percentage的配置
的值,也不会触发自动rewrite,即这连个配置同时满足时,才会触发rewrite
2.7.4 aof-load-truncated yes
redis 恢复是会忽略最后一条可能存在问题的指令,默认yes,即AOF写入时,可能存在指令写错的问题(突然断电,写了一半)
这种情况下yes会log并继续,而no会直接恢复失败。
2.8 劣势
1.相同数据集的数据而言aof文件要远大于rdb文件,恢复速度慢于rdb
2.Aof运行效率要慢于rdb,每秒同步策略效率较好,不同步效率和rbd相同
AOF总结
1.AOF文件是一个只进行追加的日志文件
2.Redis 可以在AOF文件体积变得过大时,自动地在后台进行重写
3.AOF 文件有序的保存了对数据库执行的所有写入操作,这些写入操作以Redis协议的格式保存
因此AOF文件的内容非常容易被人读懂,对文件进行分析也很轻松
1.对于相同的数据集来说,AOF文件的体积通常大于RDB文件的体积
2.根据所使用的fsync策略,AOF的速度可能会慢于RDB
redis重启时加载AOF与RDB的顺序?
1.当AOF和RDB文件同时存在,优先加载AOF
2.若关闭了AOF,加载RDB文件
3.加载AOF/RDB成功,redis重启成功
4.AOF/RDB存在错误,启动失败打印错误信息
官网建议
1. RDB持久化方式能够在指定的时间间隔能对你的数据进行对照存储
2.AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候回重新
执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作
到文件末尾
redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大,
只做缓存:如果你值希望你的数据在服务器运行的时候存在,也可不使用任何持久化方式
同时开启两种持久化方式
在这种情况下,当redis重启时候会优先载入AOF文件来恢复原始的数据
因为在通常情况下,AOF文件保存的数据要比RDB文件保存的数据要完整
RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件,那要不要只
使用aof呢,作者建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份)
快速重启,而且不会有AOF可能潜在的BUG,留着作为一个万一的手段
性能建议
因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,
只保留save 900 1 这条规则
如果Enable AOF ,好处是在最恶劣情况下也只会对视不超过两秒数据,启动脚本较简单只load自己
的AOF文件就可以了,代价
一 是带来了持久的IO
二 是AOF rewrite的最后将rewrite过程中生产的新数据写到新文件早成的阻塞几乎是不可避免的,
只要硬盘许可,应尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到
5G以上,默认超过原大小100%大小时重写可以改到适当的数值
如果不Enable AOF ,紧靠Master-Slave Replication 实现高可用性也可以,能省掉以大笔IO也减少了
rewrite时带来的系统波动,代价是如果Master/Slave 同时倒掉,会丢失实际分钟的数据,启动脚本也要比
将两个Master/Slave的RDB文件,载入较新的那个,新浪微博就选用这种架构