redis快照与AOF

我们知道,redis的数据是保存在内存里,而内存一断电就没了,所以为了数据持久化,我们得想办法把内存中的数据持久化到硬盘或者另一台机子上。


先说本地持久化到硬盘,这就有两种方式,一是快照(snapshotting),二是只追加文件(append-only file AOF)

快照

快照的核心原理就是把redis在某个时间内存内的所有数据都写入硬盘,那么什么时候写入呢?快照的配置都有哪些呢?
出现下面的情况redis会快照内存里的数据
1 用户发送bgsave命令(此时redis会fork一个子进程,子进程负责生成硬盘文件,父进程负责继续接受命令)
2 用户发送save命令(和bgsave命令不同,发送save命令后,到系统创建快照完成之前系统不会再接收新的命令,换句话说save命令会阻塞后面的命令,而bgsave不会)
3 用户在配置文件了配置了类似这样的命令 
  save 60 1000
  这个的意思是说,自从上次快照成功算起,如果满足"60秒内有1000次写入"这个条件,系统就自动调用bgsave,如果配置文件里有多个save命令,只有满足一个就调用bgsave命令
4 用户发送shutdown,系统会先导员save命令阻塞客户端,然后关闭服务器
5 当有主从架构时,从服务器向主服务器发送sync命令来执行复制操作时,只有主服务器当时没有进行bgsave操作,那么主服务器就会执行bgsave操作。更多的关于主从复制的信息,见下文

快照的配置信息

save 60 1000           
stop-writes-on-bgsave-error no
rdbcompression yes
dbfilename dump.rdb
dir ./
第一个配置不用解释了,第二个看英文就是失败后是否暂停写命令,第三个写的时候是否压缩,第五和第四合起来构成了数据文件的全地址


加入下午3:12分完成了一次快照,一切OK,在4:25开始进行第二次快照,持续了2分钟,一直到4:27次成功生成快照文件。在这2分钟内,系统又更新了35个键。如果在这2分钟内系统发生了崩溃,那么我们就丢失了自3:12以后的所有数据。如果系统在刚完成快照且那35个键还没有写入硬盘时就崩溃了,那我们就丢失了35个键。

快照的优势

快照的文件适合备份
我们建立下面的文件,让他每天凌晨3点执行,就能获得每天redis的版本了

[plain] view plain copy
 
  1. #! /bin/bash  
  2.    
  3. PATH=/usr/local/bin:$PATH  
  4. redis-cli SAVE  
  5.    
  6. date=$(date +"%Y%m%d")  
  7. cp /var/lib/redis/6379/dump.rdb /data01/cache_backup/$date.rdb  
  8.    
  9. echo "done!"  

快照的劣势

可能会丢失数据
save 60 1000,如果我在60秒内只更新了800条数据,然后系统崩溃了,那么这800条数据就没了
第二:
大数据量的时候,做RDB,redis服务会暂停近1分钟(20g的物理内存,redis里面有13g的数据)!这个就是redis持久化的时候的服务暂停现象(为啥?创建子进程,子进程的工作不需要资源么?)。
一种方式就是,我关闭自动快照的设置,就是不要写save 10 1000这样的命令,而是在系统不忙的时候发送bgsave,至少我能控制什么时候系统发生停顿么。再或者我发送save,这个虽然会停顿,但是因为不用创建子进程有时候也比较快。

AOF

还有一种就是aof
这是什么呀?就是系统会把所有的redis数据进行的写操作的命令记录到硬盘上,这样一来恢复的时候,再执行一次命令就OK了
它有下面几个设置属性
appendonly no    #是否开启aof 
appendfsync everysec  
no-appendfsync-on-rewrite no
这个配置项是设置在rewrite的时候是否对新的写操作进行fsync(将缓存中的命令写入硬盘)。no表示进行fsync,yes表示不进行默认是设置为no
rewrite是将写操作合并,比如set aa 1; set aa 2; 两个操作应该写成一个操作set aa 2;而什么时候进行rewrite呢?就是aof文件太大的时候
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
appendfsync有三种选择分别是always,everysec,no
always就是每次有一个写命令,就把命令存的硬盘文件里
everysec就是每秒写入硬盘一次
no就是由操作系统来确认什么时候写
我们一般都使用everysec,每秒把写命令写入到硬盘与不进行任何持久化操作在性能上没有什么区别。
aof优势在于:就算出问题了,最多丢失1秒内的更新数据
aof的劣势:
aof文件的体积可能会很大(可能比快照文件还大),另一方面,系统重启的时候回从aof里读命令,如果aof文件太大,读命令也就要还很久

怎么办?系统可以重写aof文件,尽量把文件体积缩小
不过重写的操作也是系统fork一个进程做的,那么在快照里存在的内存占用与性能问题,也会存在。
no-appendfsync-on-rewrite
这个配置项是设置在rewrite的时候是否对新的写操作进行fsync。no表示进行fsync,yes表示不进行
默认是设置为no
重写的时候,get操作是没有问题的,但是如果no-appendfsync-on-rewrite为no,那么写数据就会出现延迟。
我们把no-appendfsync-on-rewrite改成yes,写就没有延迟了

也就是说,aof也是由问题的
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
上面这个两个命令的意思是当现在的aof文件大于64mb,且现在的文件比上一次重写后的文件体积增加了至少100%,那么就立刻重写aof文件。



RDB 和 AOF ,我应该用哪一个?
一般来说,如果想达到足以媲美 PostgreSQL 的数据安全性, 你应该同时使用两种持久化功能。如果你非常关心你的数据,但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。有很多用户都只使用 AOF 持久化, 但我们并不推荐这种方式: 因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快, 除此之外, 使用 RDB 还可以避免之前提到的 AOF 程序的 bug 。因为以上提到的种种原因, 未来我们可能会将 AOF 和 RDB 整合成单个持久化模型。 (这是一个长期计划。)
(上面两段,复制自:https://my.oschina.net/davehe/blog/174662)

同时使用快照与aof时,当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。

posted @ 2018-08-22 15:02  阿拉神苗  阅读(2062)  评论(0编辑  收藏  举报