redis持久化
Redis 提供了两种不同的持久化方法来将数据存储到硬盘里面。一种方法叫快照(snapshotting,RDB),它可以将存在于某一时刻的所有数据都写入硬盘里面。另一种方法叫只追加文件(append-only file,AOF),它会在执行写命令时,将被执行的写命令复制到硬盘里面。
RDB(redis database)
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是Snapshot快照,它恢复时是将快照文件直接读到内存里。
redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。
如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
Fork:Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。
要启用RDB,需要修改Redis的配置文件redis.conf
#save: 多久执行一次自动快照操作
save 900 1
save 300 10
save 60 1000
save 60 5 #自行测试使用,表示60秒类写入5次的话,redis就会自动触发BGSAVE命令
#stop-writes-on-bgsave-error: 在创建快照失败后是否仍然继续执行写命令
stop-writes-on-bgsave-error no
#rdbcompression: 是否对快照文件进行压缩
* yes: 开启,这种情况下,Redis会采用LZF算法对rdb文件进行压缩 * no: 关闭
rdbcompression no
#快照文件名
dbfilename dump.rdb
#快照文件存放目录
dir /data/
RDB的触发条件会比AOF麻烦,大致可以分为以下几种:
① 通过redis-cli等客户端直接发送 BGSAVE 或 SAVE 指令:BGSAVE 会让Redis调用fork创建一个子进程在后台运行,子进程将会负责创建快照到磁盘中,可以通过lastsave命令获取最后一次成功执行快照的时间。;SAVE(与配置文件中的save毫无关系)会让Redis主进程直接开始创建快照,但在创建快照的过程中,Redis不会响应其他命令请求。在docker中启动redis容器后,在redis-cli中输入 “BGSAVE” 或 “SAVE” 后,能够在挂载的data目录下生成一个dump.rdb文件;
③ 通过配置项```save```进行触发(具体请参照上文的参数说明);
④ 通过SHUTDOWN命令关闭Redis服务器时,Redis会自动触发一个SAVE指令;
⑤ 通过标准TERM信号kill掉Redis服务时,Redis也会自动触发一个SAVE指令;
⑥ 通过Redis主从服务器的复制请求时,会触发一次BGSAVE指令(当且仅当主服务器没有子进程在执行BGSAVE)。
⑦ 执行flushall命令,也会产生dump.rdb文件,但里面是空的,无意义。
【恢复数据:将备份文件(dump.rbd)移动到redis的启动目录(你在哪个目录下启动的redis,哪个目录就是你的启动目录)下并启动服务即可。config get dir 获取目录】
① 关闭rdb的命令:redis-cli config set save " "
② 进入配置文件redis.conf将:
Save 900 1
Save 300 10
Save 60 10000
注释掉,并打开save "" 的注释,使得 save " " 生效,即可关闭rdb;
AOF(append-only file)
AOF:以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作 。
AOF的启用配置与RDB一样在redis.conf文件中
#appendonly: 是否启用AOF
* yes: 启用AOF
* no: 关闭AOF,默认
appendonly no
【注意:在docker中启动redis,所挂载的配置文件中appendonly必须设置为no,否则redis启用后会出现闪退的现象。
所以docker中要想使用AOF,可以在运行启动redis时加上 --appendonly yes】
#appendfsync: 启用AOF后的数据同步频率
* alaways: 同步持久化 每次发生数据变更会立即记录到磁盘 性能较差但数据完整性比较好(不建议)
* everysec: 每秒执行一次同步,异步操作,如果一秒内宕机有数据丢失(默认的,对性能没有太大影响)
* no: 让操作系统来决定应该何时进行同步。(不建议)
appendfsync everysec
#no-appendfsync-on-rewrite:在对AOF进行压缩(也被称为重写机制)的时候能否执行同步操作
*yes 不允许 *no 允许(默认,保证数据安全性)
no-appendfsync-on-rewrite no
# Auto-aof-rewrite-min-size:设置重写的基准值
Auto-aof-rewrite-percentage:设置重写的基准值
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
(如果觉得AOF重写执行得过于频繁,我们可以把auto-aof-rewrite-percentage设置100以上,可以适当降低重写频率)
rewrite:AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集,可以使用命令bgrewriteaof
rewrite(重写)原理:AOF文件秩序增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename),遍历新进程的内存中数据,每条记录有一条的Set语句。重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点相似。
重写触发条件:系统载入时或者上次重写完毕时,Redis会记录此时AOF大小,设为base_size,如果Redis的AOF当前大小>= base_size +base_size*100% (默认)且当前大小>=64mb(默认)的情况下,Redis会对AOF进行重写。
(redis会记录上次重写时的aof大小,默认配置是当aof文件大小时上次rewrite后大小的一倍且文件大于64M时触发)
直接根据appendfsync的设置进行触发
关闭AOF的命令:redis-cli config set appendfsync no
总结
RDB跟AOF都可以确保Redis的数据持久化,但各有特点:
RDB因为有默认的指令SAVE跟BGSAVE支持,所以适合对数据库做全量备份,比如每天凌晨3点开始执行一次BGSAVE。
AOF因为是保存的写命令,因而更适合实时备份,备份机制更稳健,丢失数据概率更低;可读的日志文本,通过操作AOF稳健,可以处理误操作。事实上现在企业应用也基本都是采用的AOF
AOF比起RDB占用更多的磁盘空间;恢复备份速度要慢;每次读写都同步的话,有一定的性能压力;存在个别Bug,造成不能恢复。
但光是使用了RDB或AOF、甚至两个一起用,也还是不够的,对于一个需要支持可扩展的分布式平台而言,我们还需要提供一套复制备份机制,允许在一个周期内,自动将AOF或者RDB的文件备份到不同的服务器下,这种情况下,我们就需要使用Redis的复制并生成数据副本功能 。
若同时开启 RDB 和 AOF:
AOF优先,RDB与AOF同时开启 默认无脑加载AOF的配置文件
相同数据集,AOF文件要远大于RDB文件,恢复速度慢于RDB
AOF运行效率慢于RDB,但是同步策略效率好,不同步效率和RDB相同