Redis持久化方式RDB和AOF

Redis 持久化


 

  1. RDB(快照)

    优点 

    • rdb是可进行压缩的二进制文件,表示Redis在某一个时间点的数据快照。非常使用与备份,灾难恢复等场景.比如使用定时任务执行bgsave并备份rdb到server或其他文件系统中,用于恢复数据.
    • rdb加载速度快于AOF方式

    缺点

    • RDB不可以做到实时持久化,容易造成数据丢失,假如频繁使用bgsave强行实时持久化,会非常影响性能,因为创建fork子进程也是有阻塞产生的
    • RDB使用特定的二进制保存,随着redis的不断更新,会有多个格式的RDB版本,会产生兼容问题

 

  2. AOF(追加)

    优点

    • 比RDB要可靠,可以定制不同的fsync策略(appendfsync everysec/no/always),默认是appendfsync everysec,每秒fsync一次,意味着最多丢失1s的数据
    • AOF是一个纯追加的文件,遇到宕机基本也不会影响磁盘上的aof日志文件
    • 档aof太大时,redis会自动进行重写(重写在一个新的文件,与此同时reids会继续往旧的aof文件追加日志信息,当新文件写完时会用新文件覆盖旧文件,之后日志信息开始往新文件追加)

    缺点

    • 相同数据集,aof文件要大于rdb文件
    • AOF速度稍慢与RDB

 

 

RDB 


 

 RDB持久化是把当前进程数据生成的快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发

 

  1.手动触发,使用save和bgsave命令

 

    • save:阻塞当前redis服务器,直到持久化完成为止,对于内存较大的实例会造成长时间的阻塞,线上环境禁止使用,已经被废弃.
root@e7576f2fbb11:/# redis-cli save
OK
root@e7576f2fbb11:/# redis-cli info|grep save        #查看持久化相关信息
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1497083505
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
root@e7576f2fbb11:/# tail -n 4 /var/log/redis/redis-server.log
61:C 10 Jun 08:20:46.257 * DB saved on disk
61:C 10 Jun 08:20:46.258 * RDB: 0 MB of memory used by copy-on-write
29:M 10 Jun 08:20:46.316 * Background saving terminated with success
29:M 10 Jun 08:31:45.676 * DB saved on disk            ###运行redis-cli save对应的redis服务日志
    • bgsave: redis进程执行fork操作创建子进程,RDB持久化由这个子进程负责,完成后自动结束.阻塞仅仅会发生在fork阶段,时间非常非常的短,bgsave是对save的优化.
root@e7576f2fbb11:/# redis-cli bgsave
Background saving started
root@e7576f2fbb11:/# redis-cli info|grep fork
latest_fork_usec:771                  #####最近一次fork子进程阻塞用的时间us
root@e7576f2fbb11:/# redis-cli info|grep save     #####获取持久化相关信息
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1497084106             ####最后一个RDB时间
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
root@e7576f2fbb11:/# tail -n 4 /var/log/redis/redis-server.log    ####使用bgsave持久化redis服务产生的日志
29:M 10 Jun 08:41:46.346 * Background saving started by pid 77
77:C 10 Jun 08:41:46.380 * DB saved on disk
77:C 10 Jun 08:41:46.381 * RDB: 0 MB of memory used by copy-on-write
29:M 10 Jun 08:41:46.385 * Background saving terminated with success

  2.自动触发

    2.1 通过reids.conf配置动触发bgsave

    2.2 当从节点执行全量复制操作时,主节点自动执行bgsave生成bgsave RDB文件并发送给从节点.

    2.3 当使用redis-cli  shutdown关闭redis服务时,如果没有开启AOF持久化功能则也会自动执行bgsave

root@e7576f2fbb11:/# grep 'save' /etc/redis/redis.conf
#   save <seconds> <changes>
#   Will save the DB if both the given number of seconds and the given
#   In the example below the behaviour will be to save:
#   Note: you can disable saving completely by commenting out all "save" lines.
#   It is also possible to remove all the previously configured save
#   points by adding a save directive with a single empty string argument
#   save ""
save 900 1        ###900s内至少一次改动,自动触发bgsave
save 300 10        ###300s内至少10次改动,自动触发bgsave
save 60 10000      ###60s内至少10000次改动,自动触发bgsave
# save ""        ###如果最后一行是save ""则上面自动触发bgsave规则会失效

  3.bgsave运作流程

  • 执行bgsave命令后,redis主进程判断当前是否存在正在执行的(AOF或者RDB)子进程,如果存在则直接返回bgsave命令.
    • root@e7576f2fbb11:/# redis-cli bgsave;redis-cli bgsave
      Background saving started
      (error) ERR Background save already in progress
  • 父进程fork子进程过程中,父进程会短暂的阻塞,通过redis-cli info|grep fork可以获得最近一个fork的操作耗时,单位为us,微秒.
  • 父进程fork子进程成功后,返回Background saving started,并停止阻塞主进程,可以继续响应其它指令.
  • 子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。执行lastsave命令可以获取最后一次RDB生成的时间.
  • 子进程发送信号给父进程表示完成,父进程更新统计信息.redis-cli  info可以查看redis状态.

  4.RDB文件相关信息

  

root@e7576f2fbb11:/# egrep -i "filename|dir" /etc/redis/redis.conf
# line as value of a configuration directive, you'd better put includes
# interfaces using the "bind" configuration directive, followed by one or
#   points by adding a save directive with a single empty string argument
# The filename where to dump the DB
dbfilename dump.rdb          #RDB文件保存的文件名,默认采取压缩
# The working directory.
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
# The Append Only File will also be created inside this directory.
# Note that you must specify a directory here, not a file name.
dir /var/lib/redis          ###RDB文件保存目录

 在redis正常运行过程中如果默认的RDB存储路径磁盘写满或不能正常写时,可以使用config set dbfilename newfilename和config set dir newdir动态改变默认的存储路径.

root@e7576f2fbb11:/# redis-cli -h 127.0.0.1 -p 6379  config set dir /var/lib/
OK
root@e7576f2fbb11:/# redis-cli -h 127.0.0.1 -p 6379  config set filename newfilename.rdb
(error) ERR Unsupported CONFIG parameter: filename
root@e7576f2fbb11:/# redis-cli -h 127.0.0.1 -p 6379  config set dbfilename newfilename.rdb
OK
root@e7576f2fbb11:/# redis-cli bgsave
Background saving started
root@e7576f2fbb11:/# ls -l /var/lib/newfilename.rdb
-rw-r--r-- 1 root root 34 Jun 10 09:28 /var/lib/newfilename.rdb
root@e7576f2fbb11:/# date
Sat Jun 10 09:29:14 UTC 2017
root@e7576f2fbb11:/#
root@e7576f2fbb11:/# redis-check-dump /var/lib/newfilename.rdb        #####使用redis-check-dump 工具检测RDB文件是否有问题.
==== Processed 3 valid opcodes (in 17 bytes) ===================================
CRC64 checksum is OK

 

AOF

 


 

AOF(append only file)持久化:使用独立的日志的方式记录每次写的命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的.AOF的主要作用是解决了数据持久化的实时性.

如果要开启AOF需要修改redis.conf配置:appendonly  yes(默认不开启:appendonly no)

通过定义appendfilename和dir修改aof文件名和保存路径.

AOF工作流程:

  1. 所有的写入命令追加到缓冲区中(redis是单线程响应方式,如果实时追加到硬盘,会影响性能.同时也是fsync策略起作用的前提)
  2. AOF缓冲区根据对应的fsync策略向硬盘做同步操作
  3. 随着AOF文件越来越大,需要定期AOF文件进行重写,达到"压缩"文件的目的
  4. 重启redis时,可以加载AOF文件进行数据恢复.

 

文件同步

  redis提供多种缓冲区同步文件策略,由参数appendfsync控制,不同值含义如下:

可配置值说明
always 命令写入aof_buf后调用fsync同步操作同步到aof文件,fsync同步完成后线程返回
everysec 命令写入aof_buf后调用系统write操作,write完成后线程返回,fsync操作由专门线程每秒调用一次 (建议配置)
no 命令写入aof_buf后调用系统write操作,不对aof文件做fsync同步,同步硬盘由操作系统负责,通常最长同步周期30秒

系统调用write和fsync说明

  • write 操作会触发延迟写机制.Linux在内核提供页缓冲区用来提高IO性能.write操作在写入系统缓冲区后直接返回.同步硬盘操作依赖于系统调度的机制,比如当缓冲区页空间写满或达到特定时间周期时触发.同步文件之前,如果此时系统宕机,缓冲区数据会丢失.
  • fsync这对单个文件操作,做强制磁盘同步,fsync将阻塞知道写入硬盘完成后返回,保证数据持久化.

 

重写机制

  随着不断的追加写入,aof文件越来越大,此时重写机制会压缩文件大小.重写指的是:把redis进程内的数据转化为写命令同步到新AOF文件的过程.

  重写使aof文件变小原因:

    1. 过期的数据不会写入
    2. 多余的命令不会写入
    3. 多条命令的合并(lpush list a lpush list b lpush c====>lpush list a b c)  

  重写的触发

    • 手动调用  bgrewriteaof命令
    • 自动触发  根据配置文件中auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机
      • auto-aof-rewrite-min-size: 表示重写aof时,文件的最小体积,default64MB(重写优先条件,必须满足)
      • auto-aof-rewrite-min-percentage: 表示当前aof文件大小和上次重写后aof文件大小的比值.

         

         

  重写运作流程

    1. 执行bgrewriteaof请求如果当前正字执行aof,直接返回,如果在执行bgsave则推迟到bgsave完成后再执行
    2. redis调用fork产生一个子进程(开销同RDB)
    3. 主进程持续把新的变动写到aof_buf并仍然沿用appendfsync策略同步到磁盘,即旧的aof文件,由于fork使用写时复制技术,子进程只能共享fork操作时的内存数据,所以新的变动同时也要在aof_rewrite_buf存一份,防止新的aof文件生成期间丢失这部分数据
    4. 根据规则重写aof文件(新)
    5. 新aof文件写入完成后,子进程通知父进程,父进程更新信息.
    6. 父进程把aof_rewrite_buf写入新的aof文件 
    7. 新aof文件替换老的aof文件

 

 

 

重启加载


 

1. AOF持久化开启且存在AOF文件时,优先加载AOF文件

 

2. AOF关闭或AOF文件不存在时,加载RDB文件(前提是RDB存在,不存在也会启动)

 

3.加载AOF/RDB文件成功后,rdis启动成功

 

4. AOF/RDB存在错误时,启动失败

 

posted @ 2017-06-10 20:20  weelin_area  阅读(970)  评论(0编辑  收藏  举报