Redis持久化
Redis的持久化机制有两种,一种是RDB快照,另一种是AOF日志。RDB时一次全量备份,AOF日志时连续性的增量备份。RDB快照时内存数据的二进制序列化形式,在存储上十分紧凑。而AOF日志记录时内存数据修改修改的指令记录文本。
一、RDB(Redis Database)快照
RDB快照持久化时Redis默认开启的,他会根据配置策略将内存数据保存在一个名为dmp.rdb的二进制文件中。
在redis.conf配置文件中,可以配置RDB的持久化策略,系统默认是三个保存策略(同时生效),如下:
- save 900 1 900秒内有1个键发生改变
- save 300 10 30秒内有10个键发生改变
- save 60 10000 60秒内有10000个键发生改变
我们可以根据自己生产环境的具体情况进行配置。如果我们要关闭RDB快照,直接将配置文件中上述三个save注释即可。
写时复制机制(COW)
Redis提供了save命令进行快照生成,但是save命令要阻塞主进程(执行客户端命令的线程),当需要生产快照的内存特别大时(几百G),那么需要的时间会很长,甚至十几秒,所以这时候如果阻塞主进程,会导致整个服务器不可用,就得不偿失了。
针对这个情况。Redis借助操作系统提供的写时复制技术,提供了bgsave命令,bgsave命令可以在主进程的基础上,fork一个子进程,子进程会共享主进程的代码和数据段,相当时在后台生产快照。
在bgsave子进程写入RDB数据时,如果主进程对这些数据也都是读操作,那么主进程bgsave子进程相互不影响。但是
如果主进程要修改一块数据,这一块数据就会被复制一份,生产该数据的副本,然后,bgsave至机场会把这个副本数据写入RDB,而在这个过程中,主进程仍然可以直接修改原来的数据。
优点
- Redis宕机后数据恢复块
- 二进制文件体积小
缺点
- 持久化策略(数据时周期性进行备份)可能会导致在宕机时数据丢失较多
AOF(append-only file)持久化
执行流程
- 命令追加append:将Redis的写命令追加到存从区AOF_buf
- 文件写入(write)和文件同步(sync):根据不同的同步策略将aof_buf中的内容同步到硬盘
- 文件重写(rewrite):定期重写AOF文件,达到压缩的目的
AOF持久化可以通过Redis.conf文件中的appendonly参数控制时候开启。
appendponly 默认情况夏是no,开启之后,Redis会将修改的每一条指令先记录到系统缓存,默认每隔一秒钟就把
珲春刷新到appendonly.aof磁盘文件中,当Redis重新启动时,程序就可以通过执行AOF文件中的命令来达到重建数据的目的。
*2
$6
SELECT
$1
0
*3
$3
SET
$1
1
$1
2
*3
$3
SET
$4
key1
$4
val1
*3
$3
SET
$4
3124
$3
124
*3
$3
SET
$5
key14
$4
key2
这是一种resp协议数据格式,星号后面的数值代表命令有多少个参数,$号后面的数值代表这个参数有几个字符。
AOF持久化策略
- appendfsync always:每次有新命令追加到AOF文件时就执行一次fsync(文件同步)(file synchronization),非常慢。也不安全。不建议使用,硬盘的IO称为性能的瓶颈
- appendfsync everysec:美妙fsync一次。足够快,并且在故障时只会丢失1秒的饿数据,AOF会默认这个配置
- appendfsync no:从不sync,将数据交给操作系统来处理,更快,也是不安全的选择,发生宕机时,数据丢失的最多
AOF重写
假设我们执行了两个命令 set key1 1
与set key2 2
,在开启AOF持久化的情况下,这两个命令都会被记录到AOF文件中,但是我们在宕机后重启恢复数据的时候是不是就只需要执行set key2 2
就可以了,所以无效的命令不再写入文件。随着时间的推移,体积会越来越大,推荐每天定时重写AOF。
手动出发后台重写,redis客户端执行命令:bgrewriteaof
Redis提供两个配置参数控制AOF自动重写频率(redis.conf)
- auto-aof-rewrite-min-size-64mb :aof文件至少要达到64MB才会自动重写,文件太小恢复速度很快
- auto-aof-rewrite-percentage 100: aof文件自上一次从写后文件大小增长了100%则再次触发重写
触发重写时Redis会通过fork主进程,生成一个子进程去做,这么做的原因是因为而重写一般以为这进行大量I/O操作,非常耗时,如果用主进程区重写会导致主进程长时间的阻塞。印象Redis执行客户端命令。甚至导致服务长时间不可用。但是子进程进行重写就意味着主进程仍然可以接收、处理客户端指令,就会导致重写后的AOF文件和服务器当前的数据库状态不一致。
例如:子进程fork主进程时,内存中只有key1这个键。但是开始重写后,客户端同时又多set了key2、key3,这就导致了重写的AOF文件和数据库不一致。
所以Redis在AOF重写时加了一个AOF重写缓冲区,当有新命令执行的时候,Redis会将命令发送到AOF缓冲区和AOF重写缓冲区。
AOF重写流程
执行完重写任务后,子进程会想主进程发送一个信号,主进程收到信号会执行下面两个操作:
注意:两个操作会阻塞主进程
- 将AOF重写缓冲区中的所有内容写入到新的AOF文件中,保证AOF文件保存的数据库状态和服务器当前状态一致
- 对新的AOF文件进行改名,原子的覆盖现有AOF文件,完成新旧文件的替换
优点
- 数据完整性要求高于RDB,默认情况下,最多丢失1秒中的数据
缺点
- Redis宕机后数据恢复慢
- 文件体积大
混合持久化(sence redis4.0)
混合持久化顾名思义就是结合RDB和AOF两种持久化话方式的优势。
混合模式后,AOF在重写时会将AOF文件中的数据以RDB文件的二进制格式写入当前AOF文件中,之后的新的写操作继续以AOF文件的格式进行追加,当Redis宕机重启的时候,加载AOF文件进行恢复数据时,现加载RDB的部分再加载剩余的AOF内容,因此重启效率大幅度得到提升。
通过修改Redis.conf文件中的以下配置开启混合持久化:
- aof-use-rdb-preamble yes
总结
RDB持久化
- RDB文件会保存Redis中所有的键值对数据
- save生成RDB文件会阻塞主进程
- bgsave命令会开启子进程生成RDB,不会阻塞主进程
- RDB文件体积小,保存的格式是二进制数据
- RDB通过写时复制周期性机制,可会丢失部分数据
- RDB文件在Redis宕机恢复快
RDB是以二进制存储数据,所以体积小,宕机恢复块。
RDB通过写时复制周期性机制,可能会导致部分数据丢失。
开启RDB指令有两种,一种save,另一种bgsave,对于save来说,生成的RDB文件会阻塞主进程
对于bgsave来说,会开启子线程生成RDB,不会阻塞主进程。
AOF持久化
- AOF文件保存的是客户端执行的命令
- AOF文件体积大,恢复慢,但是默认配置下的数据比RDB要全很多
- Redis宕机重启后默认是用AOF方式进行恢复
- AOF文件中的命令是以Resp协议格式保存的
- 命令会先保存到缓冲区(AOF缓冲区和AOF重写缓冲区),在定期同步到AOF文件
- AOF会根据配置策略自动的对AOF文件进行重写,以降低文件体积
- AOF重写时会fork一个子进程区执行,同时是会有一个重写缓冲区,用来保存重写时主进程修改的键
- AOF重写时,最后会生成一个新的AOF文件,覆盖原有的文件
- 将重写缓冲区的内容写入到AOF于替换新旧AOF文件时会阻塞主进程
因为AOF保存的是客户端的命令(Resp协议格式),所以体积大,恢复慢,在默认的配置下的数据比RDB要全,并且宕机重启后是用AOF方式恢复。
AOF开启之后,命令会先保存到缓冲区(AOF缓冲区和AOF重写缓冲区),定期同步到AOF文件中。
对于AOF的重写,目的是降低文件体积,优化不必要的命令(例如对统一数据多次就该,只需要最新的一次修改足以)
AOF的重写时会Fork一个子进程区执行,同时会有一个重写缓冲区,用来保存重写时主线程修改的键。生成一个新的AOF文件,之后会覆盖到旧的AOF文件,会阻塞主线程。
混合持久化
- 混合持久化时RDB于AOF的优势结合所产生的
- 混合持久化本质还是用的AOF文件
- 混合持久化使用的前提时开启AOF持久化
- 混合持久化在重写AOF文件时将数据直接写成RDB的二进制格式,之后新的命令还是以AOF文件Resp协议格式进行保存
混合持久化就是AOF重写时将AOF文件中的数据是以RDB的二进制形式写入AOF中,之后的新的写操作继续以AOF文件的格式进行追加,当redis宕机重启时,先加载RDB的部分在加载剩余的AOF内容,提高重启的效率。