什么是持久化?也就是数据持久化,当系统重启后仍能恢复保存的数据特性。
这个特性在mysql中最有体现,因为其把数据都保存在磁盘中,其实,redis也具有持久化的特性,
虽然其把数据都保存在内存中(一旦重启,内存中的数据都将清除),但其有自己的持久化策略,在向内存存数据时,同时也像磁盘中存,当重启时,就会从磁盘中获取数据到内存(为什么不向mysql一样直接与磁盘交互?虽然听着确实是麻烦,但因其自有的策略使得整体还是比mysql快的,两边的写是不同策略,理论上两边数据相同,但持久化导致数据不一定一致)
Redis如何实现持久化?
策略:RDB和AOF
RDB
redis database :它会定期地将我们的redis中内存所有数据写入硬盘中,形成一个快照,一旦redis重启了,就会根据快照把内存中的数据恢复。
定期分为两种:手动和自动触发
手动触发:通过redis客户端执行特定命令触发形成快照 :save(如果redis数据过多可能会阻塞其他redis客户端,不建议使用) bgsave(不会影响其他redis客户端,在后台处理,并发编程(实际并非多进程)
自动触发:在redis的配置文件设置,每隔一段时间就触发一次
bgsave的执行流程
首先输入bgsave命令输入,redis进程(父进程)识别命令并判断,当前是否有其他redis客户端工作的子进程,如果有一个子进程正在执行bgsave,则直接返回当前的bgsave,如果没有,父进程会fork出子进程,子进程来处理bgsave命令并生成rdb文件,父进程继续处理其他请求。子进程完成整个持久化过程后,通知父进程,收集退出信息并退出。
redis生成的rdb文件,是存放在redis的工作目录中,在配置文件中设置。(默认在/var/lib/redis)

rdb的持久化操作可以触发多次,当执行rdb镜像操作时,先把生成的快照的数据保存临时文件中,当生成结束后,删除原来的rdb,把新保存的文件改名为dump
除此之外,服务器通过shutdown关闭命令时,会自动触发rdb快照(主从复制也可以)
如果是kill命令(异常重启)退出服务器则不会触发
如果Redis启动时加载到损坏的RDB⽂件会拒绝启动。这时可以使⽤Redis提供的redis check-dump⼯具检测RDB⽂件并获取对应的错误报告。
RDB最大的问题就是,不能实时的持久化保存数据,比如我在两次持久化之间存数据,但在下次持久化之前,服务器因某种原因重启/退出了,那么存的这些数据就会丢失。
AOF很好地解决了这个我问题,接下来我们看看AOF的执行
RDB是⼀个紧凑压缩的⼆进制⽂件,代表Redis在某个时间点上的数据快照。⾮常适⽤于备份,全量复制等场景。⽐如每6⼩时执⾏bgsave备份,并把RDB⽂件复制到远程机器或者⽂件系统中 (如hdfs)用于灾备。
Redis加载RDB恢复数据远远快于AOF的⽅式。
RDB⽅式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运⾏都要执⾏fork创建⼦进程,属于重量级操作,频繁执⾏成本过⾼。
RDB⽂件使⽤特定⼆进制格式保存,Redis版本演进过程中有多个RDB版本,兼容性可能有风险
AOF
其存的并不是数据,而是用户的每一个操作,当redis重启时,就会读取AOF的操作恢复数据,(以AOF为准,AOF启动时,就不会读RDB了,默认关闭)
在配置文件中修改
这就意味着,AOF机制是即写内存又写硬盘,涉及到硬盘,影响redis的性能?不会,其实没有影响。AOF机制先写入内存的缓冲区,积累一定量再写入硬盘。
同样的,如果在缓冲区内的数据未到磁盘中服务器崩溃了也会丢失,尽量避免这种问题,缓冲区有三种刷新机制;
缓冲区的刷新机制
always 一旦存数据到缓冲区立即刷新
everysec:每秒刷新一次
no:由OS控制刷新频率
依然是在配置文件中修改

刷新频率过高必然会导致效率降低,因此要平衡(懂得取舍)
AOF的重写机制
随着redis服务器运行时间逐渐变长,AOF文件记录的操作也会越来越多,一旦文件过大,redis重启时一定会影响效率,因此redis会对AOF文件进行重写,
也并不是都会删除,而是类似整理的操作,删除那些冗余,重复的操作,只保留操作最后的结果,比如AOF有连续的set del set del,那么重写后就是空,因为最后的结果就是不对redis有任何数据操作,这就是重写机制。
重写机制的触发时机
同样分为手动和自动触发
手动:bgrewriteaof 命令
自动触发:根据autoaofrewriteminsize(触发时AOF最小文件大小,默认64mb)和autoaofrewritepercentage(当前aof占用大小相较于上次重写时增加的比例)参数触发
触发流程
和RDB高度相似,创建子进程去完成触发工作,重写时,不关心aof原来的内容,只关心内存最终数据状态,子进程只需要把状态获取并写入新的aof文件即可。(区别于rdb的方式,rdb是二进制存储,aof是文本存储)
在重写过程中,父进程仍能记录内存的变化并写入缓冲区(此时子进程并不知道)这个缓冲区专门存专门存父进程fork后的数据变化并写入新aof文件(子进程退出后)(aof-rewrite-buf)
如果执行重写命令时,发现redis正在生成rdb快照,此时就会等待其执行完毕后再重写
混合持久化
由于aof以文本形式存数据的开销比较大,现在大部分采用混合持久化的模式,即以rdb二进制的方式把数据存aof中。
实际redis启动时都是以aof为主,只有判断aof关闭时才会启动rdb
