本章节我们来看看Redis时如何就爱那个数据存储到硬盘里面,是的数据在Redis重启之后仍然存在的。Redis提供了两种不同的持久化方法来将数据存储到硬盘里面。一种方法叫快照(snapshotting),它可以将存在于某一时刻的所有数据都写入硬盘里;另一种方法教只追加文件(append-only file, AOF),它会在执行的写命令复制到硬盘里。这两种方法可以自由搭配使用,具体如何选择,需要根据用书的数据以及应用来决定。下面在Redis安装目录的redis.conf文件中查看下Redis默认的持久化配置:
//SNAPSHOTTING save 900 1 save 300 10 save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump.rdb dir ./ //APPEND ONLY MODE appendonly no appendfilename "appendonly.aof" appendfsync everysec no-appendfsync-on-rewrite no auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb aof-load-truncated yes
可以看出默认开启的时快照模式,AOF模式是关闭的,具体的配置项是什么意思后面再看,这里先了解下哪里可以修改配置以及Redis默认行为。
用户可以将快照复制到其他服务器已达到备份的效果,也可以就将快照留在原地以便重启服务器时使用,快照文件存在dbfilename选项指定的文件中,并存储在dir指定的路径,根据默认配置即./dump.rdb,如果在新的快照文件创建之前,Redis、操作系统或者硬件三者任意一个崩溃了,Redis会丢失最近一次创建快照之后写入的所有数据。创建快照有以下几种方式:
由于快照持久化会会在系统发生崩溃时丢失数据,因此只适用于那些即使丢失一部分数据叶不会造成问题的应用程序,如果不能接受这样的损失,可以参考后面AOF持久化。下面列举一些使用于快照持久化的场景:
个人开发服务器上,考虑到降低快照持久化带来的资源消耗,可以只设置sava 900 1,意思是距离上一次成功生成快照已经超过900秒,并且在此期间至少执行了一次写入操作,Redis就会自动开始一次新的BGSAVE操作。
在处理日志的同时,记录被处理日志的文件以及偏移量,如果Redis奔溃了而未能生成新的快照,可以从最后一次生成快照开始重新处理日志文件即可。
当Redis存储数据量只有几个GB的时候,使用快照来保存数据是没有问题的,生成快照的时间叶非常短。但随着Redis占用的内存越来越多时,BGSAVE在创建子进程时耗费的时间也越来越多,所以选择合适的创建快照方式以及妥善地处理可能出现的数据丢失,对快照持久化数据来说相当重要。
简单来说,AOF持久化会将被执行的写命令写到AOF文件的末尾,以此来记录数据的变化。因此,Redis只要从头到位重新执行一次AOF文件包含的所有命令,就可以恢复AOF文件所记录的数据集。下面列举appendfsync配置选项对AOF文件的同步频率的影响:
命令 | 描述 |
---|---|
always | 每个Reids写命令都要同步写入硬盘,这样做会严重降低Redis的速度 |
everysec | 每秒执行一次同步,显示地将多个写命令同步到硬盘 |
no | 让操作系统来决定应该何时进行同步 |
注:这里稍微解释下文件同步,在向硬盘写入文件时,写入内容首先会被存储到缓冲区,然后由操作系统决定何时将缓冲区内容写入到硬盘,这样才算真正的写入数据了。sync操作就是命令操作系统将文件同步到硬盘,同步操作会一直阻塞直到指定的文件被写入硬盘为止。当同步操作执行完毕之后,即使系统出现故障,只要硬盘不坏,就不会对被同步的文件造成任何影响。
appendfsync always选项是最安全同时也是最慢的,某些情况下还可能会影响固态硬盘的使用寿命,所以慎用!为了兼顾数据安全和写入性能,可以考虑使用appendfsync everysec,也是Redis默认行为。Redis每秒同步一次AOF文件的性能和不适用任何持久化特性时的性能相差无几,而每秒一次的同步,当系统出现故障时,也最多只会丢失一秒内产生的数据。appendfsync no选项是将写入硬盘的决定权交给操作系统,如果硬盘的写入速度不够快,缓冲区被填满时,Redis的写入操作将被阻塞,从而导致Redis处理命令请求的速度变慢,所以appendfsync no也不推荐使用。
AOF持久化看似很美好,有什么理由不使用呢?实际上并没那么简单,因为Redis会不断地将被执行的写命令记录到AOF文件中,AOF文件的体积会越来越大,极端情况下可能会撑满硬盘;另外一个问题是,Redis在重启之后需要通过重新执行AOF文件记录的所有写命令来还原数据集,所以如果AOF文件的体积非常大,那么还原操作执行的时间就可能非常长。
为了解决上述问题,可以向Redis发送BGREWRITEAOF命令,BGREWRITEAOF命令会通过移除AOF文件中的冗余命令来重写AOF文件,使得AOF文件的体积变得尽可能的小。也可以设置auto-aof-rewrite-percentage和auto-aof-rewrite-min-size来自动触发BGREWRITEAOF命令。Redis默认行为的意思是当AOF的体积大于64M,并且比上一次重写之后的体积大了至少一倍(100%)的时候,Redis将执行BGREWRITEAOF命令。如果AOF重写执行的国语频繁的话,可以调整auto-aof-rewrite-percentage选项的值设置为100以上,让Redis在AOF文件的体积变得更大之后才执行重写操作。