关于Redis持久化

前言

好记性不如烂笔头,最近看了些关于redis持久化的文章,记一下笔记。

redis持久化方式

redis持久化有两种方式,分别为RDB快照和AOF。

快照

就是定时将内存中的数据集快照写入磁盘,实际操作是fork一个子进程将文件写入到一个临时文件,写入成功后,再替换掉原先的文件,用二进制压缩存储。

AOF

将redis执行过的所有数据操作指令(读操作不记录),记录到一个aof日志文件中,只可追加不可修改文件,当启动redis时候,redis会读取该aof配置文件,进行数据操作。

redis持久化方式对应优缺点

快照

优点

1、如果数据集较大,rdb的启动效率会更高,因为我们可以很快把单纯的一个数据文件压缩转移到其他存储介质上,而aof只是保存了指令,要从头开始执行一遍,数据是不断变化的,所以aof比rdb恢复数据的速度要慢得多
2、适合备份数据
3、性能最大化,fork出一个子进程,再由子进程去进行持久化的工作,这样就可以极大的避免服务进程执行IO操作

缺点

1、定时存储的原理,在宕机情况下,会丢失还没有来得及存储的数据,而丢失的多少和备份策略有关,例如:5分钟备份一次,但是第8分时宕机了,那么就丢失了后面的3分钟数据。
2、fork子进程的时候,如果数据量过大,那么可能会导致整个服务器停止服务。

AOF

优点:

1、就算宕机了,启动脚本时只需要加载对应的AOF文件进行数据重建
2、aof对于日志文件的写入执行的是append操作,所以如果发生中断,也不会修改文件中已经存在的记录,如果是写了一半数据中断了,也可以在Redis下一次启动之前,通过redis-check-aof工具来帮助我们解决数据一致性的问题。

缺点

1、加载aof文件时,带来持续IO,redis可能会开很久
2、AOF 在过去曾经发生过这样的 bug : 因为个别命令的原因,导致 AOF 文件在重新载入时,无法将数据集恢复成保存时的原样。
3、相同数据集的情况下,aof文件要比rdb大得多,,因为rdb是直接保存了数据,而aof只是保存了指令,要从头开始执行一遍,数据是不断变化的,所以aof比rdb恢复数据的速度要慢得多

选用哪种持久化方式?

如果对于数据一致性有比较高的要求,则启用aof,如果可以允许数据的少量丢失,并且对于备份要求比较多,可以采用rdb。
rdb可定时备份数据,并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快,还可以避免aof带来的潜在bug。也可同时使用两种方法。

优化

1、 因为rdb文件只是用作后备用途,所以只建议在slave上持久化rdb文件,而且只要15分钟备份一次,只保留save 900 1 规则
2、如果启用aof,aof 文件rewrite时,将产生的新数据写到新文件造成的阻塞几乎是不可避免的,只要硬盘许可,应该尽量减少AOF rewrite频率,可将auto-aof-rewrite-min-size即aof重写的阈值从默认的64M改为5G,超过原大小100%这一比率auto-aof-rewrite-percentage 也可调整。
3、如果不启用AOF ,仅靠Master-Slave Replication 实现高可用性也可以。能省掉一大笔IO也减少了rewrite时带来的系统波动。代价是如果Master/Slave同时倒掉,会丢失十几分钟的数据,启动脚本也要比较两个Master/Slave中的RDB文件,载入较新的那个。新浪微博就选用了这种架构

持久化相关配置(Redis默认为RDB模式,可以通过修改配置文件来打开 AOF 功能:appendonly yes)

RDB配置(可在配置文件中设置,也可直接执行命令)

1、直接执行命令进行数据回写分同步和异步两种机制,分别对应SAVE命令和BGSAVE命令

同步回写即SAVE命令,主进程直接向磁盘回写数据。在数据大的情况下会导致系统假死很长时间,所以一般不是推荐的。

异步回写即BGSAVE命令,主进程fork后,复制自身并通过这个新的进程回写磁盘,回写结束后新进程自行关闭。由于这样做不需要主进程阻塞,系统不会假死,一般默认会采用这个方法。

注意:在小内存的进程上做一个fork,不需要太多资源,但当这个进程的内存空间以G为单位时,fork就成为一件很恐怖的操作。假设在16G内存的主机上fork 14G内存的进程,肯定会报内存无法分配的。并且越是改动频繁的主机上fork也越频繁,所以可以通过设置vm.overcommit_memory。
Linux内核会根据参数vm.overcommit_memory参数的设置决定是否放行。
如果 vm.overcommit_memory = 1,直接放行
vm.overcommit_memory = 0:则比较 此次请求分配的虚拟内存大小和系统当前空闲的物理内存加上swap,决定是否放行。
vm.overcommit_memory = 2:则会比较 进程所有已分配的虚拟内存加上此次请求分配的虚拟内存和系统当前的空闲物理内存加上swap,决定是否放行。

2、在Redis的配置文件中设置了多个save的选项配置

只要其中任一条满足,Redis都会触发一次BGSAVE操作,比如:900秒之内至少一次写操作、300秒之内至少发生10次写操作、60秒之内发生至少10000次写操作都会触发发生快照操作
语法:save
解释:当在规定的时间内,Redis发生了写操作的个数满足条件,会触发发生BGSAVE命令
save 900 1
save 300 10
save 60 10000

AOF配置

在Redis的配置文件中存在三种同步方式,它们分别是:
appendfsync always     #每次有数据修改发生时都会写入AOF文件。
appendfsync everysec  #每秒钟同步一次,该策略为AOF的缺省策略。
appendfsync no          #从不同步。高效但是数据不会被持久化。

AOF的Rewrite(重写)

定义:AOF采用文件追加的方式持久化数据,所以文件会越来越大,为了避免这种情况发生,增加了重写机制。

原理: 当AOF文件的大小超过了配置所设置的阙值时,Redis就会启动AOF文件压缩,只保留可以恢复数据的最小指令集,执行 BGREWRITEAOF 命令, Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令。

具体解释:当AOF增长过大时,会fork出一条新的进程将文件重写(也是先写临时文件最后rename),遍历新进程的内存数据,每条记录有一条set语句。重写AOF文件并没有操作旧的AOF文件,而是将整个内存中的数据内容用命令的方式重写了一个新的aof文件(有点类似快照)

触发机制:Redis会记录上次重写时的AOF文件大小,默认配置时当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。

数据恢复具体操作

1、获取备份目录

redis 127.0.0.1:6379> CONFIG GET dir
1) "dir"
2) "/usr/local/redis/bin"   
以上命令 CONFIG GET dir 输出的 redis 备份目录为 /usr/local/redis/bin。

2、停止redis服务

3、拷贝备份文件到 /usr/local/redis/bin目录下

4、重新启动redis服务

注意事项

1、当Redis服务器重启的时候,会自动恢复数据,RDB与AOF同时开启时,优先从AOF中恢复,其次才从RDB中恢复,因为 AOF 文件所保存的数据通常是最完整的。
2、AOF运行效率慢于RDB,但是同步策略效率(每秒同步一次)好,不同步效率和RDB相同
3、配置文件中,对于rdb持久化的策略,遵循从下往上匹配条件
4、开启rdb情况下, 当Redis通过shutdown命令关闭服务器请求时,会执行SAVE命令创建一个快照,如果使用kill -9 PID将不会创建快照。
5、开启rdb情况下,由于redis使用fork来复制一份当前进程,那么子进程就会占有和主进程一样的内存资源,比如说主进程8G内存,那么在备份的时候必须保证有16G内存,要不然会启用虚拟内存,性能非常差。

参考文章

从Redis的数据丢失说起
redis的持久化方式RDB和AOF的区别
Redis教程(十):持久化详解
redis的 rdb 和 aof 持久化的区别
Redis实战总结-配置、持久化、复制
持久化-RDB

你可能感兴趣的:(关于Redis持久化)