Redis——持久化

Redis 的 2 种持久化方式 Snapshot(RDB) 和 Append-only file(AOF) 的配置和对比

1.Snapshot

1.1 配置参数

save <seconds> <changes>  
stop-writes-on-bgsave-error yes  
rdbcompression yes  
dbfilename dump.rdb  
dir ./  
  • save :在X秒内如果key有至少X次改变就触发持久化,例如save 900 1的话就是在900秒如果key有至少1次改变就触发持久化。如果想关闭此功能的话,可以把全部save行都注释或删除或者使用save ""。
  • stop-writes-on-bgsave-error:在bgsave遇到error的时候是否停止持久化,默认是yes代表是,no代表不是
  • rdbcompression:是否压缩,默认是yes代表是,no代表不是,如果想节省CPU的话就设为no,但是rdb文件会比较大
  • dbfilename:持久化的文件名字,默认是dump.rdb
  • dir:持久化的目录名字,默认是redis.conf所在的目录./

1.2 redis有5种触发snapshot持久化的方式

  • 1)客户端执行BGSAVE命令初始化一个会占用一定内存的background进程
  • 2)客户端执行SAVE命令,这个时候redis会阻塞所有命令直到snapshot保存完毕,一般很少使用,除非你可以接受redis暂时阻塞或者没有足够内存执行BGSAVE
  • 3)redis.conf文件配置了save ,当满足条件的时候自动触发BGSAVE操作
  • 4)服务器接收到SHUTDOWN命令或者TERM signal会执行SAVE,redis会阻塞所有命令直到snapshot保存完毕,然后关闭redis
  • 5)1台redis连接到另外1台redis并且执行SYNC命令,由于某种原因如果SYNC没有执行,主redis会先执行BGSAVE

需要注意的是如果服务器crash的话会导致自从上次snapshot完成之后的数据丢失

2. Append-only file(AOF)

2.1 配置参数

appendonly no  
appendfilename "appendonly.aof"  
appendfsync everysec  
dir ./  
  • appendonly:是否启动aof,默认是no代表不启用,yes代表启用
  • appendfilename:aof的文件名,默认是appendonly.aof
  • appendfsync:触发的间隔,默认是everysec代表每秒,另外还有always代表有改变都触发,性能最差但数据最安全,no代表让OS自己决定什么时候执行,性能最好但数据不安全
  • dir:和上述是同一个参数(共用),持久化的目录名字,默认是redis.conf所在的目录./

需要注意的是如果你使用了SSD的话,appendfsync设置always会可能导致write amplification从而很大影响SSD的寿命;另外就是aof一般是比rdb文件较大,恢复时间较长,因为要重新执行所有的写操作

3. Rewriting/compacting AOF

3.1 配置参数

no-appendfsync-on-rewrite no  
auto-aof-rewrite-percentage 100  
auto-aof-rewrite-min-size 64mb  

  • no-appendfsync-on-rewrite:在aof rewrite的时候上述appendfsync是否暂时停止,默认是no代表不停止,yes代表停止,不会造成I/O资源竞争,性能较前者好。在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。
  • auto-aof-rewrite-percentage:自动触发aof rewrite的百分比,默认是100%,就是比上次rewrite的1倍
  • auto-aof-rewrite-min-size:自动触发aof rewrite的最小size,默认是64mb,就是如果size超过64mb,而且是上次执行的1倍,就会自动触发

    因为AOF会以追加的方式记录所有写操作的命令到磁盘文件里面,所以文件会越来越大,导致redis重启的时候恢复时间较长。为了缓解这种问题,redis使用了BGREWRITEAOF,用于删除重复多余的写命令,类似BGSAVE,是一个占用一定系统资源的background进程。因为rewrite的时候会删除旧的AOF文件,如果AOF文件比较大的话,会消耗更多的系统资源

4.Snapshot VS AOF

  • snapshot在下一次触发前如果服务器crash了,在上次snapshot之后修改的数据会丢失,而AOF是记录所有的写操作,在数据完整性来说,AOF比snapshot要好
  • snapshot持久化的文件rdb一般比aof要小,所以在恢复的时候snapshot会快一点,而且节省硬件资源
  • 如果服务器在写aof的时候故障导致aof文件损坏,可以使用自带的工具redis-check-aof --fix修复,而snapshot文件rdb损坏是无法修复的

    所以如果你可以容忍数据丢失的话,可以使用snapshot方式,而且也是比AOF要节省资源,否则的话就使用AOF方式,或者同时使用2种方式(重启的时候会优先使用AOF)。

5.网友翻译的AOF配置部分

原文

############################## APPEND ONLY MODE ###############################  

# By default Redis asynchronously dumps the dataset on disk. This mode is  
# good enough in many applications, but an issue with the Redis process or  
# a power outage may result into a few minutes of writes lost (depending on  
# the configured save points).  
#  
# The Append Only File is an alternative persistence mode that provides  
# much better durability. For instance using the default data fsync policy  
# (see later in the config file) Redis can lose just one second of writes in a  
# dramatic event like a server power outage, or a single write if something  
# wrong with the Redis process itself happens, but the operating system is  
# still running correctly.  
#  
# AOF and RDB persistence can be enabled at the same time without problems.  
# If the AOF is enabled on startup Redis will load the AOF, that is the file  
# with the better durability guarantees.  
#  
# Please check http://redis.io/topics/persistence for more information.  

appendonly no  

# The name of the append only file (default: "appendonly.aof")  
# appendfilename appendonly.aof  

# The fsync() call tells the Operating System to actually write data on disk  
# instead to wait for more data in the output buffer. Some OS will really flush   
# data on disk, some other OS will just try to do it ASAP.  
#  
# Redis supports three different modes:  
#  
# no: don't fsync, just let the OS flush the data when it wants. Faster.  
# always: fsync after every write to the append only log . Slow, Safest.  
# everysec: fsync only one time every second. Compromise.  
#  
# The default is "everysec", as that's usually the right compromise between  
# speed and data safety. It's up to you to understand if you can relax this to  
# "no" that will let the operating system flush the output buffer when  
# it wants, for better performances (but if you can live with the idea of  
# some data loss consider the default persistence mode that's snapshotting),  
# or on the contrary, use "always" that's very slow but a bit safer than  
# everysec.  
#  
# More details please check the following article:  
# http://antirez.com/post/redis-persistence-demystified.html  
#  
# If unsure, use "everysec".  

# appendfsync always  
appendfsync always  

# appendfsync no  

# When the AOF fsync policy is set to always or everysec, and a background  
# saving process (a background save or AOF log background rewriting) is  
# performing a lot of I/O against the disk, in some Linux configurations  
# Redis may block too long on the fsync() call. Note that there is no fix for  
# this currently, as even performing fsync in a different thread will block  
# our synchronous write(2) call.  
#  
# In order to mitigate this problem it's possible to use the following option  
# that will prevent fsync() from being called in the main process while a  
# BGSAVE or BGREWRITEAOF is in progress.  
#  
# This means that while another child is saving, the durability of Redis is  
# the same as "appendfsync none". In practical terms, this means that it is  
# possible to lose up to 30 seconds of log in the worst scenario (with the  
# default Linux settings).  
#   
# If you have latency problems turn this to "yes". Otherwise leave it as  
# "no" that is the safest pick from the point of view of durability.  
no-appendfsync-on-rewrite no  


# Automatic rewrite of the append only file.  
# Redis is able to automatically rewrite the log file implicitly calling  
# BGREWRITEAOF when the AOF log size grows by the specified percentage.  
#   
# This is how it works: Redis remembers the size of the AOF file after the  
# latest rewrite (if no rewrite has happened since the restart, the size of  
# the AOF at startup is used).  
#  
# This base size is compared to the current size. If the current size is  
# bigger than the specified percentage, the rewrite is triggered. Also  
# you need to specify a minimal size for the AOF file to be rewritten, this  
# is useful to avoid rewriting the AOF file even if the percentage increase  
# is reached but it is still pretty small.  
#  
# Specify a percentage of zero in order to disable the automatic AOF  
# rewrite feature.  

auto-aof-rewrite-percentage 100  
auto-aof-rewrite-min-size 64mb  

译文

############################## 仅追加方式 ###############################  

#默认情况下Redis会异步的将数据导出到磁盘上。这种模式对许多应用程序已经足够了,  
#但是如果断电或者redis进程出问题就会导致一段时间内的更新数据丢失(取决与配置项)  
#  
#这种只增文件是可选的能够提供更好的体验的数据持久化策略。  
#举个例子,如果使用默认的配置数据fsync策略,在服务器意外断电的情况下redis只会丢失一秒中内的更新数据,  
#或者当redis进程出问题但操作系统运转正常时,redis只会丢失一个数据更新操作。  
#  
#AOF 和 RDB 持久化方式可以同时启动并且无冲突。  
#如果AOF开启,启动redis时会加载aof文件,这些文件能够提供更好的保证。  
#请在 http://redis.io/topics/persistence 获取更多数据持久化信息。  

appendonly no  

# 只增文件的文件名称。(默认是appendonly.aof)  
# appendfilename appendonly.aof  

#调用fsync()函数会通知操作系统真正将数据写入磁盘,而不是等待缓冲区中有更多数据。  
#有些操作系统会将数据输出到磁盘,有些操作系统只是ASAP。  
#  
#redis支持三种不同的方式:  
#  
#no:不调用,之等待操作系统来清空缓冲区当操作系统要输出数据时。很快。  
# always: 每次更新数据都写入仅增日志文件。慢,但是最安全。  
# everysec: 每秒调用一次。折中。  
#  
#默认是每秒中一次,因为它往往是在速度和数据安全两者之间的折中选择。  
#如果你可以接受让操作系统去自动清空缓存,你可以将这项配置降低到'no'(如果你可以接受一段时间的数据丢失,默认的rdb就足够了),  
#这完全取决与你。如果你想要一个更好的体验或者从相反的角度,使用'always',这样会很慢,但是比'everysec'安全些。  
#  
#请在下面的文章中获取更多细节知识:  
#  http://antirez.com/post/redis-persistence-demystified.html  
#  
#如果你不是很清楚这三项之间的区别,或者不知道哪种适合你的机器,就是用默认吧。  

# appendfsync always  
appendfsync always  
# appendfsync no  

#当AOF策略设置为'always'或者'everysec'的时候,后台的保存进程会进行很多磁盘I/O操作,  
#在某些linux结构中redis会在调用sync()方法时阻塞很长时间。记住,现在还没办法解决这个问题,即使在不同进程中进行调用也会block。  
#  
#使用如下配置可能会缓解这个问题,这样会在存储大数据或者BIGREWRITEAOF的时候不会在主进程中调用fsync()方法。  
#  
# 这表示,如果另外一个子进程在进行保存操作,redis的表现如同配置为‘appendfsync no’。  
#在实际应用中,这表示在最坏的情景下(使用linux默认配置)可能会丢失30秒日志。  
#   
#如果你有特殊的情况可以配置为'yes'。但是配置为'no'是最为安全的选择。  
no-appendfsync-on-rewrite no  


#自动重写只增文件。  
#redis可以自动盲从的调用‘BGREWRITEAOF’来重写日志文件,如果日志文件增长了指定的百分比。  
#   
#它是这样工作的:每次rewrite后redis会记录日志文件的大小。(如果重启后没有重写后的大小,就默认用日志文件大小)  
#  
# 这个基准日志大小和当前日志大小做比较。如果当前大小比指定的百分比,重写机制就会被触发。  
#同时,你也要制定一个重写下线,用来避免增长百分比够了,但是日志文件还很小的情况。  
#  
#指定百分比为0可以注掉自动重写日志文件功能。  

auto-aof-rewrite-percentage 100  
auto-aof-rewrite-min-size 64mb  

参考:redis 配置文件 append only file(aof)部分---数据持久化