Redis做为一个内存数据库,数据是之内存为载体存储的,那么一旦Redis服务器进程退出,服务器中的数据也会消失。为了解决这个问题,Redis提供了持久化机制,也就是把内存中的数据保存到磁盘当中,避免数据意外丢失redis
Redis提供了两种持久化方案:RDB持久化和AOF持久化,一个是快照的方式,一个是相似日志追加的方式数据库
RDB持久化是经过快照的方式,即在指定的时间间隔内将内存中的数据集快照写入磁盘。在建立快照以后,用户能够备份该快照,能够将快照复制到其余服务器以建立相同数据的服务器副本,或者在重启服务器后恢复数据。RDB是Redis默认的持久化方式缓存
RDB持久化会生成RDB文件,该文件是一个压缩过的二进制文件,能够经过该文件还原快照时的数据库状态,即生成该RDB文件时的服务器数据。RDB文件默认为当前工做目录下的dump.rdb
,能够根据配置文件中的dbfilename
和dir
设置RDB的文件名和文件位置安全
# 设置 dump 的文件名 dbfilename dump.rdb # 工做目录 # 例如上面的 dbfilename 只指定了文件名, # 可是它会写入到这个目录下。这个配置项必定是个目录,而不能是文件名。 dir ./
触发快照的时机bash
save
和bgsave
命令save <seconds> <changes>
规则,自动间隔性执行bgsave
命令bgsave
flushall
命令清空服务器数据shutdown
命令关闭Redis时,会执行save
命令执行save
和bgsave
命令,能够手动触发快照,生成RDB文件,二者的区别以下服务器
使用save
命令会阻塞Redis服务器进程,服务器进程在RDB文件建立完成以前是不能处理任何的命令请求app
127.0.0.1:6379> save OK
而使用bgsave
命令不一样的是,basave
命令会fork
一个子进程,而后该子进程会负责建立RDB文件,而服务器进程会继续处理命令请求async
127.0.0.1:6379> bgsave Background saving started
fork()
是由操做系统提供的函数,做用是建立当前进程的一个副本做为子进程函数
fork
一个子进程,子进程会把数据集先写入临时文件,写入成功以后,再替换以前的RDB文件,用二进制压缩存储,这样能够保证RDB文件始终存储的是完整的持久化内容性能
在配置文件中设置save <seconds> <changes>
规则,能够自动间隔性执行bgsave
命令
################################ SNAPSHOTTING ################################ # # Save the DB on disk: # # save <seconds> <changes> # # Will save the DB if both the given number of seconds and the given # number of write operations against the DB occurred. # # In the example below the behaviour will be to save: # after 900 sec (15 min) if at least 1 key changed # after 300 sec (5 min) if at least 10 keys changed # after 60 sec if at least 10000 keys changed # # 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 # like in the following example: # # save "" save 900 1 save 300 10 save 60 10000
save <seconds> <changes>
表示在seconds秒内,至少有changes次变化,就会自动触发gbsave
命令
save 900 1
当时间到900秒时,若是至少有1个key发生变化,就会自动触发bgsave
命令建立快照save 300 10
当时间到300秒时,若是至少有10个key发生变化,就会自动触发bgsave
命令建立快照save 60 10000
当时间到60秒时,若是至少有10000个key发生变化,就会自动触发bgsave
命令建立快照除了RDB持久化,Redis还提供了AOF(Append Only File)持久化功能,AOF持久化会把被执行的写命令写到AOF文件的末尾,记录数据的变化。默认状况下,Redis是没有开启AOF持久化的,开启后,每执行一条更改Redis数据的命令,都会把该命令追加到AOF文件中,这是会下降Redis的性能,但大部分状况下这个影响是可以接受的,另外使用较快的硬盘能够提升AOF的性能
能够经过配置redis.conf
文件开启AOF持久化,关于AOF的配置以下
# appendonly参数开启AOF持久化 appendonly no # AOF持久化的文件名,默认是appendonly.aof appendfilename "appendonly.aof" # AOF文件的保存位置和RDB文件的位置相同,都是经过dir参数设置的 dir ./ # 同步策略 # appendfsync always appendfsync everysec # appendfsync no # aof重写期间是否同步 no-appendfsync-on-rewrite no # 重写触发配置 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb # 加载aof出错如何处理 aof-load-truncated yes # 文件重写策略 aof-rewrite-incremental-fsync yes
AOF须要记录Redis的每一个写命令,步骤为:命令追加(append)、文件写入(write)和文件同步(sync)
开启AOF持久化功能后,服务器每执行一个写命令,都会把该命令以协议格式先追加到aof_buf
缓存区的末尾,而不是直接写入文件,避免每次有命令都直接写入硬盘,减小硬盘IO次数
对于什么时候把aof_buf
缓冲区的内容写入保存在AOF文件中,Redis提供了多种策略
appendfsync always
:将aof_buf
缓冲区的全部内容写入并同步到AOF文件,每一个写命令同步写入磁盘appendfsync everysec
:将aof_buf
缓存区的内容写入AOF文件,每秒同步一次,该操做由一个线程专门负责appendfsync no
:将aof_buf
缓存区的内容写入AOF文件,何时同步由操做系统来决定appendfsync
选项的默认配置为everysec
,即每秒执行一次同步
关于AOF的同步策略是涉及到操做系统的write
函数和fsync
函数的,在《Redis设计与实现》中是这样说明的
为了提升文件写入效率,在现代操做系统中,当用户调用
write
函数,将一些数据写入文件时,操做系统一般会将数据暂存到一个内存缓冲区里,当缓冲区的空间被填满或超过了指定时限后,才真正将缓冲区的数据写入到磁盘里。这样的操做虽然提升了效率,但也为数据写入带来了安全问题:若是计算机停机,内存缓冲区中的数据会丢失。为此,系统提供了
fsync
、fdatasync
同步函数,能够强制操做系统马上将缓冲区中的数据写入到硬盘里,从而确保写入数据的安全性。
从上面的介绍咱们知道,咱们写入的数据,操做系统并不必定会立刻同步到磁盘,因此Redis才提供了appendfsync
的选项配置。当该选项时为always
时,数据安全性是最高的,可是会对磁盘进行大量的写入,Redis处理命令的速度会受到磁盘性能的限制;appendfsync everysec
选项则兼顾了数据安全和写入性能,以每秒一次的频率同步AOF文件,即使出现系统崩溃,最多只会丢失一秒内产生的数据;若是是appendfsync no
选项,Redis不会对AOF文件执行同步操做,而是有操做系统决定什么时候同步,不会对Redis的性能带来影响,但假如系统崩溃,可能会丢失不定数量的数据
在了解AOF重写以前,咱们先来看看AOF文件中存储的内容是啥,先执行两个写操做
127.0.0.1:6379> set s1 hello OK 127.0.0.1:6379> set s2 world OK
而后咱们打开appendonly.aof
文件,能够看到以下内容
*3 $3 set $2 s1 $5 hello *3 $3 set $2 s2 $5 world
该命令格式为Redis的序列化协议(RESP)。
*3
表明这个命令有三个参数,$3
表示该参数长度为3
看了上面的AOP文件的内容,咱们应该能想象,随着时间的推移,Redis执行的写命令会愈来愈多,AOF文件也会愈来愈大,过大的AOF文件可能会对Redis服务器形成影响,若是使用AOF文件来进行数据还原所需时间也会越长
时间长了,AOF文件中一般会有一些冗余命令,好比:过时数据的命令、无效的命令(重复设置、删除)、多个命令可合并为一个命令(批处理命令)。因此AOF文件是有精简压缩的空间的
AOF重写的目的就是减少AOF文件的体积,不过值得注意的是:AOF文件重写并不须要对现有的AOF文件进行任何读取、分享和写入操做,而是经过读取服务器当前的数据库状态来实现的
文件重写可分为手动触发和自动触发,手动触发执行bgrewriteaof
命令,该命令的执行跟bgsave
触发快照时相似的,都是先fork
一个子进程作具体的工做
127.0.0.1:6379> bgrewriteaof Background append only file rewriting started
自动触发会根据auto-aof-rewrite-percentage
和auto-aof-rewrite-min-size 64mb
配置来自动执行bgrewriteaof
命令
# 表示当AOF文件的体积大于64MB,且AOF文件的体积比上一次重写后的体积大了一倍(100%)时,会执行`bgrewriteaof`命令 auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb
下面看一下执行bgrewriteaof
命令,重写的流程
fork
一个子进程来建立一个新的AOF文件aof_buf
的同时,还会追加到aof_rewrite_buf
AOF重写缓冲区Redis4.0开始支持RDB和AOF的混合持久化(能够经过配置项 aof-use-rdb-preamble
开启)
redis-check-aof fix
命令修复上面介绍了RDB持久化和AOF持久化,那么来看一下他们各自的优缺点以及该如何选择持久化方案
关于RDB和AOF的优缺点,官网上面也给了比较详细的说明https://redis.io/topics/persistence
RDB
优势:
缺点:
AOF
优势:
缺点:
若是是数据不那么敏感,且能够从其余地方从新生成补回的,那么能够关闭持久化
若是是数据比较重要,不想再从其余地方获取,且能够承受数分钟的数据丢失,好比缓存等,那么能够只使用RDB
若是是用作内存数据库,要使用Redis的持久化,建议是RDB和AOF都开启,或者按期执行bgsave
作快照备份,RDB方式更适合作数据的备份,AOF能够保证数据的不丢失