目录
两种持久化
RDB
简介
持久化策略
手动触发命令
自动触发
执行流程
Fork操作
图示执行流程
RDB配置
AOF
简介
AOF开启
持久化策略
持久化流程
文件损坏修复
文件重写压缩
重写原理
重写流程
图示执行流程
AOF配置
两者相比
优
缺
官方推荐
启用推荐
储存方式
只做缓存
同时开启两种持久化方式
那要不要只使用AOF呢?
性能建议
Redis的数据都是储存在内存中,如果遇到进程关闭,服务器宕机等意外操作,就需要持久化操作把我们的数据持久化存储成文件到磁盘,当服务器恢复我们重启Redis时,就可以通过这些文件进行数据恢复。
在Redis中提供两种持久化方式:
1.RDB(Redis DataBase)(默认):将数据以快照的方式存储到磁盘,生成的文件名默认为dump.rdb
2.AOF(Append Of File):以日志形式把每次操作数据的命令记录下来储存到磁盘,生成为文件名默认为appendonly.aof
将数据以快照的方式存储到磁盘,生成的文件名默认为dump.rdb
,恢复时将dump.rdb
文件读到内存中。
RDB可以通过命令手动触发,也可以自动触发。
save:该命令会开始持久化操作,但是save会使Redis服务阻塞,直到持久化完成。当数据量较大,会造成长时间阻塞,不建议使用
bgsave:该命令会执行fork创建一条子进程,由子进程进行持久化操作,Redis服务一般只会在创建子进程时阻塞,后续持久化操作由子进程完成,Redis服务不会阻塞。
在配置文件中可以看到以下配置,如果被注释掉需要取消注释
save 3600 1
save 300 100
save 60 10000
它表示在3600/300/60秒内数据被修改过1/100/10000次时,自动触发bgsave
操作。我们可以通过修改或添加来改变机制。
1.执行bgsave
时,Redis进程会先检查当前进程下是否存在正在执行其他子进程,如果存在就是直接结束本次持久化。
2.通过fork操作创建子线程,创建期间Redis进程阻塞。
3.创建完毕,Redis进程恢复,可以继续处理其他命令。
4.创建的子进程先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。
5.持久化完成,子进程通知Redis
整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。
如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失(有新的数据写入但并没有触发bgsave时发生服务器意外),导致数据完整性不高。
这里为什么要用临时文件?因为如果直接写入文件的话如果写入的过程出现服务器宕机等操作,可能会出现数据大规模丢失情况。
Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等) 数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑。
在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,Linux中引入了“写时复制技术”。
一般情况父进程和子进程会共用同一段物理内存,只有进程空间的各段的内容要发生变化时,才会将父进程的改变的内容页复制一份给子进程。
在配置文件中修改。
对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用LZF算法进行压缩。推荐开启。
rdbcompression yes
在存储快照后,还可以让redis使用CRC64算法来进行数据校验。推荐开启。
rdbchecksum yes
当Redis无法写入磁盘的话,直接关掉Redis的写操作。推荐开启。
stop-writes-on-bgsave-error yes
rdb文件的保存路径,默认为Redis启动时命令行所在的目录下,可以修改。
dir ./
修改生成的rdb
文件名
dbfilename dump.rdb
以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(读操作不记录), 只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
AOF默认不开启,需要修改配置文件开启,改为yes开启
appendonly no
可以设置配置文件中的appendfsync属性:
always:始终同步,每次redis的写入都会立刻记入日志,性能较差但数据完整性比较好。
everysec:每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失。
no:redis不主动进行同步,把同步时机交给操作系统。
appendfsync everysec
所有写命令会被append追加到AOF缓冲区内,AOF缓冲区根据AOF持久化策略将操作sync同步到磁盘的AOF文件中,AOF文件大小超过重写策略或手动重写时,会对AOF文件rewrite重写,压缩AOF文件容量。
通过/usr/local/bin/redis-check-aof 进行修复
redis-check-aof --fix appendonly.aof
AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制, 当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩, 只保留可以恢复数据的最小指令集。可以使用命令bgrewriteaof
进行重写。
AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再替换)。redis4.0版本后的重写,就是把rdb 的快照,以二级制的形式附在新的aof头部,作为已有的历史数据,替换掉原来的流水账操作。
1.bgrewriteaof
触发重写,判断是否当前有bgsave
或bgrewriteaof
在运行,如果有,则等待该命令结束后再继续执行。
2.主进程fork出子进程执行重写操作,保证主进程不会阻塞。
3.子进程遍历redis内存中数据到临时文件,客户端的写请求同时写入aof_buf缓冲区和aof_rewrite_buf重写缓冲区保证原AOF文件完整以及新AOF文件生成期间的新的数据修改动作不会丢失。
4.子进程写完新的AOF文件后,向主进程发信号,父进程更新统计信息。主进程把aof_rewrite_buf中的数据写入到新的AOF文件,期间主进程阻塞。
5.使用新的AOF文件覆盖旧的AOF文件,完成AOF文件重写。
在配置文件中修改。
yes:客户端的写操作不写入aof文件只写入缓存,用户请求不会阻塞,但是在这段时间如果宕机会丢失这段时间的缓存数据。(降低数据安全性,提高性能)
no:会把数据往磁盘里刷,但是遇到重写操作,可能会发生阻塞。(数据安全,但是性能降低)
no-appendfsync-on-rewrite=no
Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次重写后大小的一倍且文件大于64M时触发重写。虽然可以节约大量磁盘空间,减少恢复时间,但是每次重写还是有一定的负担的,因此设定Redis要满足一定条件才会进行重写。
设置重写的基准值,文件达到100%时开始重写(文件是原来重写后文件的2倍时触发);
auto-aof-rewrite-percentage:100
设置重写的基准值,最小文件64MB。达到这个值开始重写。
auto-aof-rewrite-min-size:64mb
系统载入时或者上次重写下次什么时候开始重写?完毕时,Redis会记录此时AOF大小,设为base_size,
如果Redis的AOF当前大小>= base_size +base_size*100% (默认)且当前大小>=64mb(默认)的情况下,Redis会对AOF进行重写。
RDB
适合大规模的数据恢复。
重新启动时,数据直接加载到内存中,恢复速度快。
备份时,主进程没有任何IO操作,极大提升了性能。
AOF
备份更加全面,丢失数据概率更低,极端情况也不会丢失超过2s的数据。
日志文件可读,可以处理误操作。
RDB
fork时内存数据被克隆。
最后一次快照备份后的操作会在宕机时丢失。
AOF
比起RDB占用更多的磁盘空间。
恢复备份速度要慢,因为是将所有指令重新执行一遍。
每次读写都同步的话,有一定的性能压力。
官方推荐两个都启用。
如果对数据不敏感,可以选单独用RDB。
不建议单独用 AOF,因为可能会出现Bug。
如果只是做纯内存缓存,可以都不用。
RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储。
AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾。
Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。
如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式。
在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件。
建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份), 快速重启,而且不会有AOF可能潜在的bug,留着作为一个万一的手段。
因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够了,只保留save 900 1这条规则。
如果使用AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只load自己的AOF文件就可以了。
代价,一是带来了持续的IO,二是AOF rewrite的最后将rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。
只要硬盘许可,应该尽量减少AOF rewrite的频率,AOF重写的基础大小默认值64M太小了,可以设到5G以上,默认超过原大小100%大小时重写可以改到适当的数值。