Redis持久化方式RDB和AOF
Redis 持久化
- RDB(快照)
优点
-
- rdb是可进行压缩的二进制文件,表示Redis在某一个时间点的数据快照。非常使用与备份,灾难恢复等场景.比如使用定时任务执行bgsave并备份rdb到server或其他文件系统中,用于恢复数据.
- rdb加载速度快于AOF方式
- rdb是可进行压缩的二进制文件,表示Redis在某一个时间点的数据快照。非常使用与备份,灾难恢复等场景.比如使用定时任务执行bgsave并备份rdb到server或其他文件系统中,用于恢复数据.
缺点
- 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
- root@e7576f2fbb11:/# redis-cli bgsave;redis-cli bgsave
- 父进程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工作流程:
- 所有的写入命令追加到缓冲区中(redis是单线程响应方式,如果实时追加到硬盘,会影响性能.同时也是fsync策略起作用的前提)
- AOF缓冲区根据对应的fsync策略向硬盘做同步操作
- 随着AOF文件越来越大,需要定期AOF文件进行重写,达到"压缩"文件的目的
- 重启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文件变小原因:
- 过期的数据不会写入
- 多余的命令不会写入
- 多条命令的合并(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文件大小的比值.
重写运作流程
- 执行bgrewriteaof请求如果当前正字执行aof,直接返回,如果在执行bgsave则推迟到bgsave完成后再执行
- redis调用fork产生一个子进程(开销同RDB)
- 主进程持续把新的变动写到aof_buf并仍然沿用appendfsync策略同步到磁盘,即旧的aof文件,由于fork使用写时复制技术,子进程只能共享fork操作时的内存数据,所以新的变动同时也要在aof_rewrite_buf存一份,防止新的aof文件生成期间丢失这部分数据
- 根据规则重写aof文件(新)
- 新aof文件写入完成后,子进程通知父进程,父进程更新信息.
- 父进程把aof_rewrite_buf写入新的aof文件
- 新aof文件替换老的aof文件
重启加载
1. AOF持久化开启且存在AOF文件时,优先加载AOF文件
2. AOF关闭或AOF文件不存在时,加载RDB文件(前提是RDB存在,不存在也会启动)
3.加载AOF/RDB文件成功后,rdis启动成功
4. AOF/RDB存在错误时,启动失败