redis持久化
作者:互联网
redis如何实现数据不丢失:为了保证Redis数据不丢失,要把数据从内存存储到磁盘上,这就是Redis的数据持久化。Redis 数据持久化有三种方式:
1)AOF日志(Append Only File,文件追加方式):
先执行命令把数据写入内存,然后再记录命令日志到文件中,重启时重新执行AOF文件中的命令以恢复数据,是目前redis持久化的主流方式。工作流程如下:所有命令追加到aof_buf缓冲区,缓冲区根据策略向硬盘aof文件做同步操作,redis服务器重启时,加载aof文件恢复数据。
Redis为什么要先执行命令,再把数据写入日志?
由于Redis在写入日志之前,不对命令进行语法检查,所以只记录执行成功的命令,避免出现记录错误命令的情况,而且在命令执行后再写日志不会阻塞当前的写操作。
Redis先执行命令,再把数据写入日志,有什么风险?
如果Redis刚执行完命令,此时发生故障宕机,会导致这条命令存在丢失的风险。AOF日志其实也是在主线程中执行,所以当Redis把日志文件写入磁盘的时候,还是会阻塞后续的操作无法执行。redis如果直接追加到硬盘,由于Redis是单线程,性能完全取决于硬盘负载,先写入缓冲区还可以提供多种同步到硬盘的策略。
redis的系统调用,write和fsync
write触发延迟写,写入系统缓冲区后返回,通过系统调度完成同步磁盘的操作
fsync强制磁盘同步,阻塞直到写入硬盘完成后返回
缓冲区向硬盘aof的同步操作:通过appendfsync控制,取值有三种always、everysec、no
always:命令写入aof_buf后调用系统fsync操作同步到AOF文件,fsync完成后线程返回
everysec:命令写入aof_buf后调用系统write操作,write完成后线程返回,fsync同步文件操作由专门线程每秒调用一次
no:命令写入aof_buf后调用系统write操作,不对AOF文件做fsync同步,同步硬盘操作有操作系统负责,通常同步周期最长30s
2)RDB快照(Redis DataBase):将某一个时刻的内存数据,以二进制的方式写入磁盘。
RDB记录的是某一时刻的数据而不是操作,所以采用RDB方法做故障恢复时只需要直接把RDB文件读入内存即可,实现快速恢复
RDB做快照时会阻塞线程吗?
Redis提供了三个命令生成RDB快照文件,分别是save,bgsave和bgrewriteaof。
save 命令在主线程中执行,会导致阻塞,直到RDB操作完成。bgsave命令会创建一个子进程,该子进程用于RDB持久化过程,避免了对主线程的阻塞,这也是Redis RDB的默认配置。子进程会根据父进程的内存生成快照文档,对原有文件进行原子替换。bgsave创建子进程的时候对主进程会有略微阻塞,时间很短,微秒级别。bgsave期间服务器拒绝执行save、bgsave、bgrewriteaof这三个命令,主要是防止线程间竞争产生问题。子进程创建RDB文件(dump.rdb)是一个压缩的二进制文件,压缩后的文件远远小于内存中的大小,保存在dir配置指定的目录下,通过它可以恢复Redis内存中的数据
RDB生成快照文件时,数据还能被增删改吗?
可以的,如果生成快照文件期间数据不能被修改,是会有潜在问题的。假如生成快照的20s时间里,如果数据不能被修改,Redis就不能处理对这些数据的写操作,那无疑会给业务服务造成巨大影响。如果主线程执行写操作,则被修改的数据会复制一份副本,然后bgsave子进程会把该副本数据写入RDB文件,在这个过程中,主线程仍然可以直接修改原来的数据。
可以每秒做一次快照么?
如果频繁地执行全量快照,会带来两方面开销:一是频繁将全量数据写入磁盘,会给磁盘带来很大压力。二是bgsave子进程需要从主线程fork出来,fork创建过程本身会阻塞主线程,而且主线程的内存越大,阻塞时间越长。
既然频繁执行全量快照不行,那还有什么其他好方法吗?
第一个方法是做增量快照。在第一次做完全量快照后,T1和T2时刻如果再做快照,只需要将被修改的数据写入快照文件就行了。
第二个方法是Redis4.0提出一个混合使用AOF日志和RDB快照的方法:RDB快照以一定的频率执行,在两次快照之间,使用AOF日志记录这期间的所有命令操作。假如两次RDB之间有T1和T2两次修改,用AOF日志记录,等到第二次做全量快照时,就可以清空AOF日志,因为此时的修改都已经记录到快照中了。
3) 混合使用AOF日志和RDB快照
如上简介
标签:AOF,redis,持久,写入,Redis,RDB,快照,日志 来源: https://www.cnblogs.com/MarkLeeBYR/p/16615549.html