Redis如何实现数据不丢失
Redis的读写操作都是在内存中,所以Redis性能才会高,但是当Redis重启后,内存中的数据就会丢失,那为了保存内存中的数据不会丢失,Redis实现了数据持久化机制,会把数据保存到磁盘,这样Redis重启就能够从磁盘恢复原有的数据
Redis提供了三种数据持久化方式
AOF
AOF步骤
Redis在执行完一条命令后就会把该命令以追加的方式写到一个文件,然后Redis重启时,会读取该命令然后逐一执行命令的方式来进行数据恢复
避免额外的检查开销:因为如果先将写操作记录到AOF日志中,再执行该命令的话,如果当前命令有问题如果不检查的话,Redis使用该命令进行恢复的时候就可能会出错
不会阻塞当前写操作命令的执行:因为是在当前线程的写操作之后
- 数据可能会丢失:当前线程执行完命令而还没有写入磁盘时就宕机了
- 可能阻塞其它操作:因为记录AOF日志也是在主线程中执行,所以当Redis把日志写入磁盘时会阻塞后续的命令
AOF的写回策略
AOF日志文件过大怎么办?
AOF日志是一个文件,随着写命令的执行,文件会越来越大,如果文件过大就会带来性能问题,比如AOF恢复中执行的命令就会很多就会导致恢复过程很慢
所以Redis提供了AOF重写机制,当AOF文件大小超过设定的阈值时AOF就会启用重写机制来压缩AOF文件,比如set name lixiaobo 与set name lidabo 就会设置为一条指令set name lidabo
重写AOF日志过程
Redis的重写AOF过程是由后台子进程bgwriteaof来完成的,这么做的好处:
触发重写机制后,主进程会创建重写AOF的子进程,此时子进程只会对这个内存进行只读,重写AOF子进程会读取所有指令,并逐一把内存数据的键值对转换成另一条命令,再将命令记录到重写日志(新的AOF文件)
但是重写过程中,主进程依然可以正常处理命令,所以就出现了问题,如果主进程修改了已经存在的key-value,那么就会发生写时复制,此时这个key-value数据在子进程的内存数据就与主进程的内存数据不一样了
为了解决这种数据不一致,Redis设置了一个AOF重写缓冲区,这个缓冲区在创建bgwriteaof子进程之后开始使用
在重写AOF期间,当Redis执行完一个写命令之后,它会同时把这个写命令放入AOF缓冲区与AOF重写缓冲区
也就是说在bgwriteaof期间,主进程需要执行三个工作
当子进程重写完成之后会向主进程发送一条信号,信号是进程间通信的一种方式
主进程收到该信号后,会调用一个信号处理函数
RDB
RDB记录的是某一个瞬间的内存数据,记录的是实际数据,因此在数据恢复时,RDB恢复数据的效率比AOF高些
如何进行RDB
redis提供了两个命令来执行RDB
Redis的快照是全量快照,也就是每次执行快照都会把内存中的数据都记录到磁盘,所以这是一个比较重的操作
RDB执行快照时候数据能修改?
可以修改,在执行bgsave过程,Redis依旧可以继续处理操作命令,也就是数据是能被修改,关键技术还是写时复制
混合持久化
混合持久化步骤
AOF的优点是丢失数据少,但是数据恢复慢,而RDB是优点是恢复速度快而快照的频率不好把握,如果频率过低,数据丢失的量就比较多,如果频率高就会影响性能
所以退出了混合持久化集成两者优点,在AOF重写日志时,fork出来的子进程会把当前主线程共享的内存数据以RDB方式写入到AOF文件,然后主线程处理的命令被记录到重写缓冲区中,重写缓冲区中的命令会以追加AOF的形式存在AOF日志中
混合持久化的优缺点
优点
集成了AOF与RDB的优点
缺点
文件可读性变差