Redis系列四:redis持久化

redis支持RDB和AOF两种持久化机制,持久化可以避免因进程退出而造成数据丢失。

两种持久化可以单独使用其中一种,但更多情况下是将二者结合使用。

一、RDB持久化

RDB持久化把当前进程数据生成快照(.rdb)文件保存到硬盘的过程,有手动触发和自动触发。

redis会在以下几种情况下对数据进行快照。
a)根据配置规则进行自动快照;
b)用户执行save或bgsave命令;
c)执行flushall命令;
d)执行复制(replication)时;
 

1、根据配置规则进行自动快照

允许用户自定义快照条件,当符合快照条件时,redis会自动执行快照操作。进行快照的题哦啊键可以由用户在配置文件中自定义,由两个参数构成:时间窗口M和改动的键的个数N。每当时间M内被更改的键的个数大于N时,即符合自动快照条件。
如redis安装目录中包含的样例配置文件中预置的3个条件:
save 900 1
save 300 10
save 60 10000
每条快照条件占一行,并且以save参数开头,同时可以存在多个条件,条件之间是“或”的关系。上例中,save 900 1的意思是在15分钟(900秒)内有一个或一个以上的键被更改则进行快照,同理,save 300 10表示子啊300秒内至少有10键被修改进行快照。


2、手动触发有save和bgsave两命令 

除redis自动进行快照外,服务重启、手动迁移以及备份时我们也会需要手动执行快照操作。redis提供两个命令来完成这一操作。


save命令:阻塞当前Redis,直到RDB持久化过程完成为止,若内存实例比较大会造成长时间阻塞,线上环境不建议用它
bgsave命令:redis进程执行fork操作创建子线程,由子线程完成持久化,阻塞时间很短(微秒级),是save的优化,在执行redis-cli shutdown关闭redis服务时,如果没有开启AOF持久化,自动执行bgsave;
显然bgsave是对save的优化。

bgsave运行流程

 

3、执行flushall命令

执行flushall命令时,redis会清除数据库中所有的数据,要注意,不论清空数据库的过程是否触发了自动快照条件,只要自动快照条件不为空,redis就会执行一次快照操作。
如当定义的快照条件为当1秒内修改10000个键时进行自动快照,而当数据库里只有一个键时,执行flushall命令也会触发快照,即使这一过程实际上只有一个键被修改了。
当没有定义自动快照条件时,执行flushall则不会进行快照。

 4、执行复制(replication)时

当设置了主从模式时,redis会在复制初始化时进行自动快照。

5、快照原理

redis默认会将快照文件存储在redis当前进程的工作目录中的dump.rdb文件中,可以通过配置dir和dbfilename两个参数分别指定快照文件的存储路径和文件名。快照过程如下:
a、redis使用fork函数复制一份当前进程(父进程)的副本(子进程);
b、父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件;
c、当子进程写入完所有数据后会用到该临时文件替换旧的rdb文件,至此一次快照操作完成。
 
注意:
在执行fork的时候操作系统会使用写时复制(copy-on-write)策略,即fork函数发生的一刻父子进程共享同一内存数据,当父进程要更改其中某片数据时(如执行写命令),操作系统会将该片数据复制一份以保证子进程的数据不受影响,所以新的rdb文件存储的时执行fork一刻的内存数据。
写时复制策略也保证了在fork的时刻虽然看上去生成了两份内存副本,但实际上内存的占用量并不会增加一倍。
当进行快照的过程中,若写入操作较多,造成fork前后数据差异较大,是会使得内存使用量显著超过实际数据大小的,因为内存中不仅保存了当前的数据库数据,而且还保存着fork时刻的内存数据。进行内存用量估算很容易忽略该问题,造成内存用量超限。
 
通过上述发现redis在进行快照的过程中不会修改rdb文件,只有快照结束后才会将旧的文件替换成新的,也就是手任何时候rdb文件都是完整的,使得我们可以通过定时备份rdb文件来实现redis数据库备份。rdb文件是经过压缩(可以配置rdbccompression参数以禁用压缩节省CPU占用)的二进制格式,所以占用的空间会小于内存中的数据大小,更加利于传输。
 
redis启动后会读取rdb快照文件,将数据从硬盘载入到内存,根据数量大小与结构和服务器性能不同,这个时间也不同,通常将一个记录1000万字符串类型键、大小为1GB的快照文件载入内存中需要花费20~30秒。
通过rdb方式实现持久化,一旦redis异常退出,就会丢失最后一次快照以后更改的所有数据,这就需要通过组合设置自动快照条件的方式来将可能发生的数据损失控制在能够接受的范围。
 

RDB文件的操作

   命令:config set dir /usr/local  //设置rdb文件保存路径

   备份:bgsave  //将dump.rdb保存到usr/local下

   恢复:将dump.rdb放到redis安装目录与redis.conf同级目录,重启redis即可

   优点:1,压缩后的二进制文文件适用于备份、全量复制,用于灾难恢复

              2,加载RDB恢复数据远快于AOF方式

   缺点:1,无法做到实时持久化,每次都要创建子进程,频繁操作成本过高

              2,保存后的二进制文件,存在老版本不兼容新版本rdb文件的问题  

二、AOF持久化

针对RDB不适合实时持久化,redis提供了AOF持久化方式来解决。

开启:redis.conf设置:appendonly yes  (默认不开启,为no)

默认文件名:appendfilename "appendonly.aof"   

1、流程说明

  • 所有的写入命令(set hset)会append追加到aof_buf缓冲区中
  • AOF缓冲区向硬盘做sync同步
  • 随着AOF文件越来越大,需定期对AOF文件rewrite重写,达到压缩
  • 当redis服务重启,可load加载AOF文件进行恢复

AOF持久化流程:命令写入(append),文件同步(sync),文件重写(rewrite),重启加载(load)

2、AOF配置详解

appendonly yes     //启用aof持久化方式

# appendfsync always //每收到写命令就立即强制写入磁盘,最慢的,但是保证完全的持久化,不推荐使用

appendfsync everysec //每秒强制写入磁盘一次,性能和持久化方面做了折中,推荐

# appendfsync no    //完全依赖os,性能最好,持久化没保证(操作系统自身的同步)

no-appendfsync-on-rewrite  yes  //正在导出rdb快照的过程中,要不要停止同步aof

auto-aof-rewrite-percentage 100  //aof文件大小比起上次重写时的大小,增长率100%时,重写

auto-aof-rewrite-min-size 64mb   //aof文件,至少超过64M时,重写

3、如何从AOF恢复?

  • 设置appendonly yes;
  • 将appendonly.aof放到dir参数指定的目录;
  • 启动Redis,Redis会自动加载appendonly.aof文件。

 

注意:
同步硬盘数据:
虽然每次执行更改数据库内容的操作时,AOF都会将命令记录在AOF文件中,但是事实上,由于操作系统的缓存机制,数据并没有真正地写入硬盘,而是进入了操作系统的硬盘缓存。在某人情况下系统每30秒会执行一次同步操作,以便将硬盘缓存中的内容真正地写入硬盘,在这30秒的过程中若系统异常退出则会导致硬盘缓存中的数据丢失。为了解决该问题需要redis在写入AOF文件后主动要求系统将缓存内容同步到硬盘中。在redis中可以通过appendfsync参数设置同步的时机:
#appendfsync always
appendfsync everysec
#appendfsync no
 
默认情况采用everysec规则,即每秒执行一次同步操作,always表示每次执行写入都会执行同步,这是最安全也是最慢的方式。no表示不主动进行同步操作,而是完全交由操作系统来做(即每30秒一次),这个最快最不安全。一般everysec足够了,既兼顾了性能又保证了安全。

三、redis重启时恢复加载AOF与RDB顺序及流程:

1,当AOF和RDB文件同时存在时,优先加载AOF

2,若关闭了AOF,加载RDB文件

3,加载AOF/RDB成功,redis重启成功

4,AOF/RDB存在错误,redis启动失败并打印错误信息

 

posted @ 2019-08-18 15:45  工作中的点点滴滴  阅读(200)  评论(0编辑  收藏  举报