如果面试的时候有面试过问:“Redis有哪些持久化方式,区别是什么呢?”,想必聪明的各位小伙伴心中已有自己的答案了。
一、为什么要持久化
Redis作为缓存中间件,其数据均是操作系统内存的,有时候我们为了避免其宕机导致数据丢失,故而引入其持久化功能。
二、如何实现持久化
Redis提供了不同级别的持久化方式:
RDB
AOF
不持久化
RDB + AOF
2.1 RDB
这种持久化方式,是能够在指定时间间隔对Redis数据进行快照存储。
优点:
1.生成的文件是一个紧凑的文件,可以保存某个时间点Redis中的整个数据集
2.可以用于主从复制
3.RDB可以保证Redis的性能,利用bgsave (参见2.1.1)
4.与AOF相比,它文件大小会更小,恢复速度会更快
缺点:
1.数据安全性不高(RDB方式一般会把保存间隔时间设置的较长(相对AOF而言,参见2.1.2),这样就会导致可能会丢失一部分数据)
2.fork子线程时,如果数据量过大,则会影响Redis客户端响应
2.1.1 save和bgsave的区别
RDB保存文件时有两种方式,save和bgsave,对于bgsave而言,它是从Redis主线程中fork出来一个子线程,来执行整个文件生成,这样对于Redis来说,它就不会影响主线程Redis命令的执行,能最大化保证Redis性能;但是对于save而言,它会直接里用主线程来操作,会阻塞其他Redis命令的执行,一般不建议。
2.1.2 为什么需要将RDB时间跨度设大
save 60 1000 #代表60秒内,至少1000个数据发生变化,就进行RDB持久化
假设将RDB时间设置的过短,那么当数据量过大时,上一次RDB还没有完成,又来了一次RDB,这样就会导致频繁的fork子线程,增加Redis服务压力,影响客户端响应。
2.1.3 RDB工作方式
当Redis要生成快照dump.rdb文件时,服务器会执行下述操作:
1. Redis调用forks.同事拥有父进程和子进程
2. 子进程会将数据写入到临时的RDB文件中
3. 当子进程完成文件写入后,会用生成的临时的RDB文件覆盖原有的RDB文件,在覆盖完成时会删除久RDB文件
2.2 AOF(Append-only file)
这种持久化方式,会记录每次Redis执行的写操作的命令,在Redis服务重启时通过回放这些命令来实现数据恢复。
优点:
1.AOF会使你的数据更加可靠 (2.2.1)
2.AOF文件在体积过大的时候可以执行重写
3.AOF文件可读性更强
缺点:
1.AOF文件体积一般比RDB要大
2.根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB
2.2.1 AOF的写入策略
1.无fsync(不同步)将数据交给操作系统来处理。更快,也更不安全的选择。
2.每秒同步
3.每次执行写操作命令时同步
这就是为什么AOF相对RDB来说数据更可靠,AOF时及时配置1s写入一次,最多也只会丢失1s的数据
2.2.2 工作原理
AOF 重写和 RDB 创建快照一样,都巧妙地利用了写时复制机制:
* Redis 执行 fork() ,现在同时拥有父进程和子进程。
* 子进程开始将新 AOF 文件的内容写入到临时文件。
* 对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾,这样样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。
* 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。
* 搞定!现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。
2.2.3 文件重写
BGEWRITEAOF #可以在不打断客户端的情况下,对AOF进行重写
RDB & AOF
总的来说,选择哪种方式,主要看场景是什么样的情况,根据不同需求选择。
特别的知识点:
1.BGSAVE 和 BGREWRITEAOF命令不可以同时执行,避免对磁盘造成大量IO操作
2.当AOF和RDB同时开启时,一般优先执行AOF,因为AOF数据相对更完整