很是感谢《redis实战》真本书,本文大多内容也参考了书中的内容。很是推荐你们看一下《redis实战》这本书,感受书中的不少理论性东西仍是很不错的。html
为何本文的名字要加上春夏秋冬又一春,哈哈 ,这是一部韩国的电影,我感受电影不错,因此就用在文章名字上了,没有什么特别的含义,而后下面的有些配图也是电影相关镜头。git
不少时候咱们须要持久化数据也就是将内存中的数据写入到硬盘里面,大部分缘由是为了以后重用数据(好比重启机器、机器故障以后回复数据),或者是为了防止系统故障而将数据备份到一个远程位置。github
Redis不一样于Memcached的很重一点就是,Redis支持持久化,并且支持两种不一样的持久化操做。Redis的一种持久化方式叫快照(snapshotting,RDB),另外一种方式是只追加文件(append-only file,AOF).这两种方法各有千秋,下面我会详细这两种持久化方法是什么,怎么用,如何选择适合本身的持久化方法。redis
快照(snapshotting)持久化
Redis能够经过建立快照来得到存储在内存里面的数据在某个时间点上的副本。Redis建立快照以后,能够对快照进行备份,能够将快照复制到其余服务器从而建立具备相同数据的服务器副本(Redis主从结构,主要用来提升Redis性能),还能够将快照留在原地以便重启服务器的时候使用。安全
快照持久化是Redis默认采用的持久化方式,在redis.conf配置文件中默认有此下配置:服务器
save 900 1 #在900秒(15分钟)以后,若是至少有1个key发生变化,Redis就会自动触发BGSAVE命令建立快照。 save 300 10 #在300秒(5分钟)以后,若是至少有10个key发生变化,Redis就会自动触发BGSAVE命令建立快照。 save 60 10000 #在60秒(1分钟)以后,若是至少有10000个key发生变化,Redis就会自动触发BGSAVE命令建立快照。
根据配置,快照将被写入dbfilename选项指定的文件里面,并存储在dir选项指定的路径上面。若是在新的快照文件建立完毕以前,Redis、系统或者硬件这三者中的任意一个崩溃了,那么Redis将丢失最近一次建立快照写入的全部数据。markdown
举个例子:假设Redis的上一个快照是2:35开始建立的,而且已经建立成功。下午3:06时,Redis又开始建立新的快照,而且在下午3:08快照建立完毕以前,有35个键进行了更新。若是在下午3:06到3:08期间,系统发生了崩溃,致使Redis没法完成新快照的建立工做,那么Redis将丢失下午2:35以后写入的全部数据。另外一方面,若是系统刚好在新的快照文件建立完毕以后崩溃,那么Redis将丢失35个键的更新数据。app
建立快照的办法有以下几种:svg
- BGSAVE命令: 客户端向Redis发送 BGSAVE命令 来建立一个快照。对于支持BGSAVE命令的平台来讲(基本上全部平台支持,除了Windows平台),Redis会调用fork来建立一个子进程,而后子进程负责将快照写入硬盘,而父进程则继续处理命令请求。
- SAVE命令: 客户端还能够向Redis发送 SAVE命令 来建立一个快照,接到SAVE命令的Redis服务器在快照建立完毕以前不会再响应任何其余命令。SAVE命令不经常使用,咱们一般只会在没有足够内存去执行BGSAVE命令的状况下,又或者即便等待持久化操做执行完毕也无所谓的状况下,才会使用这个命令。
- save选项: 若是用户设置了save选项(通常会默认设置),好比 save 60 10000,那么从Redis最近一次建立快照以后开始算起,当“60秒以内有10000次写入”这个条件被知足时,Redis就会自动触发BGSAVE命令。
- SHUTDOWN命令: 当Redis经过SHUTDOWN命令接收到关闭服务器的请求时,或者接收到标准TERM信号时,会执行一个SAVE命令,阻塞全部客户端,再也不执行客户端发送的任何命令,并在SAVE命令执行完毕以后关闭服务器。
- 一个Redis服务器链接到另外一个Redis服务器: 当一个Redis服务器链接到另外一个Redis服务器,并向对方发送SYNC命令来开始一次复制操做的时候,若是主服务器目前没有执行BGSAVE操做,或者主服务器并不是刚刚执行完BGSAVE操做,那么主服务器就会执行BGSAVE命令
若是系统真的发生崩溃,用户将丢失最近一次生成快照以后更改的全部数据。所以,快照持久化只适用于即便丢失一部分数据也不会形成一些大问题的应用程序。不能接受这个缺点的话,能够考虑AOF持久化。性能
AOF(append-only file)持久化
与快照持久化相比,AOF持久化 的实时性更好,所以已成为主流的持久化方案。默认状况下Redis没有开启AOF(append only file)方式的持久化,能够经过appendonly参数开启:
appendonly yes
开启AOF持久化后每执行一条会更改Redis中的数据的命令,Redis就会将该命令写入硬盘中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是经过dir参数设置的,默认的文件名是appendonly.aof。
在Redis的配置文件中存在三种同步方式,它们分别是:
appendfsync always #每次有数据修改发生时都会写入AOF文件,这样会严重下降Redis的速度 appendfsync everysec #每秒钟同步一次,显示地将多个写命令同步到硬盘 appendfsync no #让操做系统决定什么时候进行同步
appendfsync always 能够实现将数据丢失减到最少,不过这种方式须要对硬盘进行大量的写入并且每次只写入一个命令,十分影响Redis的速度。另外使用固态硬盘的用户谨慎使用appendfsync always选项,由于这会明显下降固态硬盘的使用寿命。
为了兼顾数据和写入性能,用户能够考虑 appendfsync everysec选项 ,让Redis每秒同步一次AOF文件,Redis性能几乎没受到任何影响。并且这样即便出现系统崩溃,用户最多只会丢失一秒以内产生的数据。当硬盘忙于执行写入操做的时候,Redis还会优雅的放慢本身的速度以便适应硬盘的最大写入速度。
appendfsync no 选项通常不推荐,这种方案会使Redis丢失不定量的数据并且若是用户的硬盘处理写入操做的速度不够的话,那么当缓冲区被等待写入的数据填满时,Redis的写入操做将被阻塞,这会致使Redis的请求速度变慢。
虽然AOF持久化很是灵活地提供了多种不一样的选项来知足不一样应用程序对数据安全的不一样要求,但AOF持久化也有缺陷——AOF文件的体积太大。
重写/压缩AOF
AOF虽然在某个角度能够将数据丢失下降到最小并且对性能影响也很小,可是极端的状况下,体积不断增大的AOF文件极可能会用完硬盘空间。另外,若是AOF体积过大,那么还原操做执行时间就可能会很是长。
为了解决AOF体积过大的问题,用户能够向Redis发送 BGREWRITEAOF命令 ,这个命令会经过移除AOF文件中的冗余命令来重写(rewrite)AOF文件来减少AOF文件的体积。BGREWRITEAOF命令和BGSAVE建立快照原理十分类似,因此AOF文件重写也须要用到子进程,这样会致使性能问题和内存占用问题,和快照持久化同样。更糟糕的是,若是不加以控制的话,AOF文件的体积可能会比快照文件大好几倍。
文件重写流程:
和快照持久化能够经过设置save选项来自动执行BGSAVE同样,AOF持久化也能够经过设置
auto-aof-rewrite-percentage
选项和
auto-aof-rewrite-min-size
选项自动执行BGREWRITEAOF命令。举例:假设用户对Redis设置了以下配置选项而且启用了AOF持久化。那么当AOF文件体积大于64mb,而且AOF的体积比上一次重写以后的体积大了至少一倍(100%)的时候,Redis将执行BGREWRITEAOF命令。
auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
不管是AOF持久化仍是快照持久化,将数据持久化到硬盘上都是很是有必要的,但除了进行持久化外,用户还必须对持久化获得的文件进行备份(最好是备份到不一样的地方),这样才能尽可能避免数据丢失事故发生。若是条件容许的话,最好能将快照文件和从新重写的AOF文件备份到不一样的服务器上面。
随着负载量的上升,或者数据的完整性变得 愈来愈重要时,用户可能须要使用到复制特性。
Redis 4.0 对于持久化机制的优化
Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,能够经过配置项 aof-use-rdb-preamble
开启)。
若是把混合持久化打开,AOF 重写的时候就直接把 RDB 的内容写到 AOF 文件开头。这样作的好处是能够结合 RDB 和 AOF 的优势, 快速加载同时避免丢失过多的数据。固然缺点也是有的, AOF 里面的 RDB 部分就是压缩格式再也不是 AOF 格式,可读性较差。
参考:
《Redis实战》