Redis持久化有两种方式:RDB和AOF
一般是两种方式搭配使用,同时开启,这时候Redis重新启动会使用AOF文件来恢复内存中的数据,然后如果我们需要备份Redis数据的话则将dump.rdb文件备份即可。
RDB快照方式持久化
dump.rdb是二进制的压缩文件,里边是全量快照数据,用来做备份恢复比较方便。Redis进行RDB持久化的时候会先生成临时文件,生成完成之后一次性替换dump.rdb
文件,所以dump.rdb文件都是完整的。
RDB快照生成时机:
(1)、SAVE和BGSAVE 一般是用后者异步的做快照,不阻塞其他命令,使用LASTSAVE可以看最近一次成功执行快照的时间。(返回的是一个UNIX时间戳 ,1641258757 -> 2022-01-04 09:12:37)
127.0.0.1:7001> lastsave
(integer) 1638239440
127.0.0.1:7001> bgsave
Background saving started
127.0.0.1:7001> lastsave
(integer) 1641258757
(2)、根据配置定时进行快照,redis.conf
文件里有默认配置
#900秒内如果有1个key发生了修改,则执行一次快照
save 900 1
#300秒内如果有10个key发生了修改,则执行一次快照
save 300 10
#60秒内如果有10000个key发生了修改,则执行一次快照
save 60 10000
(3)、FLUSHALL时,执行这个命令会清除内存数据库中的所有数据,需要注意。
(4)、主从复制时 ,以RDB快照的方式将数据同步到从库。
rdbcompression参数可以用来控制是否压缩二进制dump.rdb文件,压缩的话文件小,传输和写盘快,不压缩则节省CPU资源,可以根据需求自己取舍。在redis.conf文件里配置,默认是压缩的:
rdbcompression yes
RDB快照的时候,Redis会从主进程fork出来子进程来负责快照持久化,fork是内核操作、使用了所谓CopyOnWrite技术:
1、 fork开始时,内存就是readonly的了,子进程复制读的是fork时刻的快照数据。
2、 主进程如果有写入会复制一份该修改到的内存页、新内存页是可读写的、原内存页仍然readonly给子进程用、然后将指针指向新的这个内存页。这样主进程只修改的这一部分后面读写会到新内存页、其他还是会到原内存页的,而子进程持久化一直是用的原内存页,两者同时进行互相不阻塞。且内存使用上也不会是把主进程的内存复制了一模一样大小的两份,写操作少的话,复制的内存页只占很少一部分。
但如果RDB快照期间写操作比较多、剩余可用内存又比较少,可能会出现Redis数据库内存 + 写复制使用的内存大于系统内存的情况,需要修改Linux系统参数使应用程序可以申请超过可用内存大小的空间:
修改/etc/sysctl.conf:
vm.overcommit_memory = 1
然后执行sysctl vm.overcommit_memory = 1
确保马上生效。
overcommit_memory这个参数是应用程序可以向系统申请超过实际可用大小的内存空间,注意只是申请或系统承诺,但并不是马上就真的分配了这么多内存页。一般来说保守的策略是不开启这个参数的。
AOF命令追加方式持久化
RDB方式会丢失最后一次快照之后的数据,如果用Redis做临时热点数据的缓存,那问题不大,如果是不能容忍丢失的交易数据,那要配合AOF方式使用。
开启AOF方式:
appendonly yes
1、AOF——增量命令appendonly和命令重写
AOF方式会每秒将使得Redis数据修改的命令(更准确说是发送给Redis Server的通信协议内容)写入到appendonly.aof
文件里,Redis会定期对写入命令进行重写,重写后的aof文件逻辑上来说跟之前一样但命令更少,比如执行了3个SET key value
,那其实只保留最后一个就可以了。
#aof文件超过上一次重写时的百分之多少则进行重写
auto-aof-rewrite-percentage 100
#最小要达到多少大小才重写
auto-aof-rewrite-min-size 64mb
也可以手工触发aof重写,BGREWRITEAOF
命令。
2、aof刷盘时机
Redis写aof文件的时候实际上也是先写系统磁盘缓冲的,可以根据情况来指定刷盘的时机。
#appendfsync always
appendfsync everysec
#appendfsync no
always是每次写都同步刷盘,everysec是异步写磁盘缓冲、1秒刷盘一次,no的话就是Redis自己不主动刷盘、把刷盘控制权交给操作系统,Linux默认是30秒一次。所以综合性能和数据安全性,用everysec就可以了。
参考:
《Redis入门指南(第2版)》
Redis-关于RDB的几点顿悟-COW(Copy On Write)_Muscleape的博客-CSDN博客_redis的cow