目录
介绍
RDB(redis database)
是什么
备份如何执行
配置
优势
劣势
备份恢复
AOF(Append Only File)
是什么
数据恢复
正常恢复
异常恢复
同步频率设置
重写(压缩)
持久化流程
优势
劣势
总结
介绍
redis持久化操作方式有两种:RDB和AOF。
RDB(redis database)
是什么
在指定的时间间隔内将内存中的数据集快照写入磁盘,快照为保存时间点的所有数据。它恢复时是将快照文件中的数据直接读到内存中。
备份如何执行
redis使用RDB进行备份时,会单独创建一个子进程进行持久化,会先将数据写到一个临时文件中,待持久化过程结束了,在用这个临时文件替换上次持久化好的文件。整个过程中主进程时不进行任何IO操作的。这就确保了极高的性能,如果需要进行大规模的数据恢复,且对于数据恢复的完整性不是很敏感,那RDB的方式比AOF方式更加高效。RDB的缺点是最后一次持久化后的数据可能丢失(因为RDB备份时通过一定周期来进行备份的)。
- fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量,环境变量,程序计数器等)数值和原进程一致。但是是一个全新的进程,并作为原进程的子进程。
- 在linux程序中,fork产生一个子进程后,通常会调用exec类的函数进行进程替换。出于效率考虑,linux引入了写时拷贝技术。下面博客中有谈到,子进程和父进程实际公用进程地址空间。只有当子进程或者父进程对数据进程写操作时,才会在新开辟空间,将值赋值进去。进程的操作(创建,终止,等待,替换)_两片空白的博客-CSDN博客
为什么要将数据先保存到临时文件:
为了保证数据的一致性和完整性。防止在持久化时redis服务器挂了,数据没有持久化完成。
配置
默认生成持久化文件名。
生成dump.rdb文件的默认位置在redis服务器启动时所在的目录。
当redis无法写入磁盘时,直接关掉redis的写操作。推荐yes。
持久化文件是否进行压缩。如果时yes,redis会采用LZF算法进行压缩。如果不想消耗CPU来进行压缩,可以关闭此功能。
检测完整性。
在存储快照时,还可以让redis使用CRC64算法来进行数据校验。
但是这样做会增加大约10%的性能消耗。推荐yes
save 多少秒 有多少key发生变化
下面框住的表示,默认当3600秒内有一个key发送变化,会进行持久化。当300秒至少有100个key发送变化,才会进行持久化,60秒内至少有10000个key发生变化才会进行持久化。
这样说明,想持久化的时间越短,数据的变化需要越多。
禁止使用
注意:需要过完时间才进行持久化。
演示:
1. 修改配置
2. 重启redis服务器
3. 查看dump.rdb文件
当前启动redis的目录下没有dump.rdb文件
4. 在20秒内修改3个key
5. 再次查看dump.rdb文件
优势
- 适合大规模数据的恢复。
- 更适合对数据完整性和一致性要求不高中使用。
- 节省磁盘空间。
- 恢复速度快。
劣势
- Fork的时候(建立临时文件),内存中的数据拷贝了一份,大致2倍的膨胀率需要考虑。
- 虽然redis再fork的时候使用了写时拷贝技术,但是如果数据量庞大时还是比较消耗性能。
- 周期一定时间间隔做一次备份,如果再周期时间内,redis意外down掉,就丢失了最后一次快照的所有修改。
备份恢复
1. redis会通过redis.conf文件中save字段的规则会持久化数据到dump.rdb中。
AOF(Append Only File)
是什么
以日志的形式来记录每一个写操作(增量保存),写操作包括插入,删除和修改,不包括查询。并且是将redis执行过的写指令记录下来。只允许追加文件,但是不允许改写文件。
redis启动的时候会读取该日志文件来进行重构数据,也就是redis启动的时候会根据日志文件中的内容将写操作指令从前到后执行一次来完成数据的恢复工作,与RDB类似。
AOF默认不开启。可以在redis.conf配置文件来配置日志文件的名称,默认是appendonly.aof。日志文件生成的位置也是在redis服务器启动时所在的目录下。
RDB时默认开启的,当AOF和RDB都开启了,redis会使用哪一个做来进行数据恢复呢?
答案是AOF。
演示:
将AOF开启,重启服务器。
查看生成的日志文件
重新连接redis客户端,查看数据。redis中没有数据,说明使用的时AOF来恢复数据。
插入数据后,查看日志文件,大小不为0。
查看dump.rdb文件,大小也变化了。说明数据持久化不仅使用了AOF,也使用了RDB。
总结:
当RDB和AOF都开启时,数据恢复使用的是AOF,持久化RDB和AOF都会使用。因为数据不会存在丢失的情况。
数据恢复
正常恢复
AOF的数据持久化的机制虽然和RDB不同,但是数据恢复的操作同RDB一样。同样是备份日志文件,需要时恢复到redis的启动目录下,redis启动时系统会自动加载。
演示:
之前有向redis中插入数据。
将日志文件备份,后关闭redis服务,删除日志文件(模拟redis服务宕机,误删日志文件),在恢复日志文件重启redis服务。
数据恢复了
异常恢复
日志文件中记录的时在redis中写操作数据的指令,有特定的格式、当日志文件发生损坏,比如:被修改,格式被破坏。可以通过redis-check-aof --fix 文件名对日志文件进行修复。不知道redis-check-aof在哪,可以通过命令whereis redis-check-aof,查找。
演示:
将日志文件备份,然后模拟误操作修改日志文件
删除日志文件,关闭redis服务,重启服务。
连接redis客户端
在redis7版本之前使用客户端连接redis服务器时,连接会被拒绝。但是redis7版本后,演示不出来了。
同步频率设置
在配置文件中可以通过appendfsync字段来设置redis的同步频率。
- always:始终同步,每次redis的写入都会被记入日志,性能较差,但是数据完整性比较好。
- everysec:每秒同步,每秒有写操作指令记入日志,如果宕机,当前秒可能丢失数据。
- no:redis不主动进行同步,把同步时机交给操作系统。
重写(压缩)
- 是什么
AOF采用的是文件追加的方式,文件会越来越大,为了避免这种情况,新增了重写机制。
当文件大小超过设定的阈值时,Redis会启用AOF文件的内容压缩,只保留可以恢复数据的最小指令集。可以使用命令bgrewriteaof。
比如:我在redis中插入了三条数据set k1 11,set k2 22,set k3 33 在日志文件中会记录三条这样的指令。当文件大小超过阈值进行重写时,会将着三条命令压缩成一条命令set k1 11 k2 22 k3 33。
- 重写原理
AOF日志文件持续增长超过阈值时,会fork出一个新进程来将文件重写,和RDB一样,也是先写临时文件最后再替换日志文件。
redis4.0 版本后的重写,是指把RDB的快照,以二进制的形式,附在新的AOF头部,作为已有的历史数据,替换掉原来的流水账操作。在配置中如果no-appendfsync-on-rewrite=yes,不写入AOF文件只写入缓存,用户请求不会阻塞,但是如果在这段时间内如果宕机会丢失这段时间的缓存数据。(降低数据的安全性,提高性能)。如果no-appendfsync-on-rewrite=no,还是会把数据往磁盘里刷,但是遇到重写操作,可能会发生阻塞。(数据安全,但是性能降低)
- 触发重写条件
Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上一次重写后大小的一倍且文件大小大于64M时触发。
重写虽然可以节约大量磁盘空间,减少恢复时间。但是每一次重写有一定的负担,因此需要redis满足一定条件才会重写。
文件重写基准值配置:
例如:当前AOF日志文件大小文件70M,重写后大小文件50M,下一次会在100M开始重写。
redis启动或者重写完毕时,Redis会记录此时AOF日志文件的大小,设为base_size,当AOF日志文件大小大于等于base_size+base_size*auto-aof-rewrite-percentage%,并且大于等于auto-aof-rewrite-min-size时进行重写。
- 重写流程
- 输入bgrewriteaof触发重写,判断是否当前有bgsave或bgrewriteaof运行,如果有,则等待该命令结束后再继续执行。
- 主进程fork出子进程执行重写操作,保证主进程不会被阻塞。
- 子进程遍历redis内存中的数据到临时文件,客户端的写请求同时写入aof_buf缓冲区和aof_rewrite_buf重写缓冲区保证原AOF文件完整以及新AOF文件生成期间的新数据修改动作不会丢失。
- 子进程完成新的AOF文件后,向主进程发信号,父进程更新统计信息,主进程把aof_rewrite_buf中的数据写到新的AOF文件中。
- 使用心得AOF文件替换旧的AOF文件,完成AOF重写。
持久化流程
- 客户端的写操作指令会被追加到AOF缓冲区中。
- AOF缓冲区根据AOF持久化策略(always,everysec,no)将操作同步到磁盘的AOF日志文件中。
- AOF日志文件的大小超过重写策略或者手动重写时,会对AOF日志文件进行重写,压缩AOF文件容量。
- redis服务重启时,会重新加载AOF日志文件中的写操作达到数据恢复的目的。
优势
- 备份机制更加稳定,丢失数据概率更低。
- 可读的日志文件,通过操作AOF稳健,可以处理误操作。可以恢复日志文件。
劣势
- 比RDB占用更多磁盘空间,需要保存指令。
- 恢复备份数据慢。需要重新执行指令。
- 每次读写都同步的话,有一定的性能压力。同步策略设置为aways。
- 存在个别的Bug,导致不能恢复。
总结
- 用那个好
官方推荐两个都用,如果对数据不敏感,允许数据部分丢失,可以单独使用RDB,不建议单独使用AOF,因为可能会出现Bug,如果只是做纯内存缓存,两个都可以不用。
- RDB和AOF比较
- RDB持久化方式能够在指定的时间间隔对数据的快照进行存储。
- AOF的持久化方式记录每次对服务器的写操作,当服务器重启的时候会重新执行这些命令恢复原来的数据,AOF命令以redis协议追加每次写操作到文件末尾。
- AOF当日志文件超过一定阈值,可以对日志文件进行重写,达到压缩功能,以至于日志文件体积不会过大。
- 制作缓存,可以不适用任何持久化方式。
- 同时开启两种持久化方式时:
- 当redis重启时会优先加载AOF日志文件,因为在RDB文件可能存在数据丢失的情况。
- 建议不要只是用AOF,因为RDB更适用于备份数据库(AOF不断变化不好用于备份),快速重启不会有AOF可能潜在的Bug,留着做万一的手段。
- 性能建议
- 因为RDB时作为数据库的备份,建议只在slave上持久化RDB文件,并且只要15分支备份一次就够了,只需要保留save 900 1这条规则。
- 如果使用AOF,好处是在最恶劣的情况下也只会丢失不超过两秒的数据,启动脚本简单,只要加载自己的AOF文件就可以了。
- 缺点是1. 带来了持续的IO,需要不断追加写操作。2. AOF重写时产生的新数据写到日志文件时造成的阻塞是不可避免的。
- 只要硬盘许可,AOF应该尽量减少重写操作,AOF重写文件基础大小为64M,太小了,可以设置到5G以上。默认超过重写后日志文件大小的两倍时重写也可以改到适当值。