Redis持久化
持久化就是把内存中的数据写进硬盘里面,获得持久的保存。
为了防止断电,服务器宕机导致内存中的数据丢失
持久化的实现方式:
-
RDB(Redis Database)
-
AOF(Append Only File)
-
RDB+AOF
一、RDB
RDB:在指定的时间间隔,执行数据集的时间点快照。类似照片记录效果的方式,把某一时刻的数据和状态以文件的形式写到磁盘上,也就是快照。这样一来即使故障宕机,快照文件也不会丢失,数据的可靠性也就得到了保证。
这个快照文件就成为RDB文件(dump.rdb)恢复时将硬盘快照文件直接读回到内存里。保存备份时是全量快照,把内存中的所有数据都记录到磁盘中。
rdb配置修改
在redis的配置文件中指定 时间间隔
redis6之前
在Redis.conf 配置文件中的 SNAPSHOTTING 下配置save参数,来触发Redis的RDB 持久化条件
比如 “save m n ”表示 m 秒内数据存在 n 次修改时,自动触发bgsave
save 900 1:每隔900秒,如果有1个key发生变化,就写一份新的RDB文件
save 300 10:每隔300秒,如果有10个key发生变化,就写一份新的RDB文件
save 60 10000:每隔60秒,如果有10000个key发生变化,就写一份新的RDB文件
Redis7的配置文件将配置项修改为:
自定义修改:
-
修改触发频率 通过修改save后的值 save 5 2
-
也就是5秒之后,并且修改次数达到2次,就会保存到dump
-
-
修改dump文件保存路径 ----修改 dir
-
修改dump文件名 -----修改dbfilename
恢复数据
如果想要恢复数据,只需要将备份文件(dump.rdb) 移动到redis的安装目录(如果指定了dump文件的存放路径,那么把dump文件放到该路径即可恢复)并启动服务即可。
如何测试?
先创建三个set集合,保证5秒后修改了2次,会生成一个 dump.rdb,我们把这个dump.rdb改个名字,然后把库清空。(执行flushall或 flushdb 命令也会产生 dump.rdb),把新生成的dump.rdb 删除,重启redis(关闭redis也会生成dump文件),把之前修改的dump改回去,,发现一开始创建的三个set集合又回来了。
当产生了有数据的 dump.rdb 一定要进行备份,服务和备份分机隔离,分开存储
防止备份文件中的内容被替换掉。
上面是 自动触发,5秒后并且修改次数达到两次,会自动添加到 dump文件
除了这种方式还可以手动触发
涉及到了两个命令 save 和 bgsave
这两个命令的原理是在后台开启了子进程可以去备份文件
save和bgsave的区别
-
save 在主程序中会阻塞当前的redis服务器,直到持久化工作完成,在执行save命令期间,redis不能处理其他命令,这样会导致缓存功能的缺失,工作中禁止使用
-
bgsave redis会在后台异步进行快照操作,不阻塞快照同时还可以响应客户端请求,该触发方式会fork() 一个子进程,由子进程复制持久化过程
除了这两个命令,还有一个命令是 lastsave,用来查看最后一次成功执行快照的时间
执行该命令会得到一个时间戳,
将 时间戳转换成时间:date -d @时间戳
rdb的优点:
-
适合大规模的数据恢复
-
按照业务定时备份
-
对数据完整性和一致性要求不高
-
RDB文件在内存中的加载速度要比AOF快得多
rdb的缺点:
-
在一定时间间隔做一次备份,所以如果redis意外宕机,就会丢失从当前到最近一次快照之间的数据。
-
内存数据的全量同步,如果数据量太大会导致I/O严重影响服务器性能
-
RDB依赖于主进程的fork,在更大的数据集中,这可能会导致服务请求的瞬间延迟,fork的时候内存中的数据被克隆了一份,导致2倍的膨胀性
如果dump.rdb 文件在写入的时候毁坏了,比如宕机时正在写入,导致有一部分数据没有写进去
可以使用 redis-check-rdb 命令修复 dump文件
触发rdb的情景:
-
默认配置文件中的自动触发
-
手动save/bgsave 触发
-
执行 flushdb/flushall 也会产生dump文件,但里面是空的
-
执行shutdown且没有开启AOF持久化
-
主从复制时,主节点自动触发
如果想要禁用rdb,可以在配置文件中将save 注释掉
配置文件中 snapshot 的其他配置
-
stop-writes-on-bgsave-error yes 默认是yes,表示当bgsave出现错误时,停止写入,为了保证数据的一致性,如果为no,那么bgsave写入失败,也能继续接收新的写请求
-
rdbcompression yes 默认是yes,表示对dump进行压缩
-
rdbchecksum yes 默认是yes,在存储快照后,让redis使用CRC64算法进行数据校验。但会增加性能消耗
-
rdb-del-sync-files no 默认是no,在没有持久性的情况下删除复制中使用的rdb文件启用
-
二、AOF
AOF是以日志的形式来记录每个写操作,读操作不记录,只能追加文件但不能改写文件。Redis启动时会读取该文件重新构建数据,也就是redis重启会根据日志文件的内容,重新执行写的指令完成数据的恢复。
默认情况下,redis没有开启aof,需要在配置文件中配置 appendonly yes
aof的保存文件叫做:appendonly.aof
工作流程
-
Client作为命令的来源,会有多个源头源源不断的请求命令(写操作)
-
在这些命令到达Redis Server 以后并不是直接写入AOF文件,会先将这些命令放到AOF缓存中进行保存,这里的AOF 缓存区实际上是内存中的一片区域,存在的目的是当这些命令达到一定量后再写入磁盘,避免频繁的IO操作
-
aof缓冲会根据aof缓冲区同步文件的三种写回策略将命令写入磁盘上的aof文件
-
随着写入aof内容的增加为避免文件膨胀,会根据规则进行命令的合并(又称为aof重写),从而起到aof文件压缩的目的。
-
当redis服务器重启时会从aof文件载入数据
三种写回策略:
-
Always:同步写回,每个写命令执行完立刻同步地将日志写回磁盘。优点可靠性高,数据基本不丢失,缺点每个写命令都要落盘,性能影响较大
-
everysec:每秒写回,每个命令执行完,先把日志写到aof缓存区,每隔一秒把缓存区内容写入磁盘。优点性能适中,缺点宕机时丢失1秒内的数据。
-
no:操作系统去控制写回,每个命令执行完,只是先把日志写到aof地内存缓冲区,由操作系统决定何时将缓存区内容写回磁盘。优点性能好,缺点宕机丢失数据较多
配置文件
redis7的新特性:Multi-part AOF
开启aof是在配置文件中 将appendonly 设置为yes。默认是no
设置写回策略是 设置 appendfsync,默认是 everysec
设置aof文件保存路径:
-
redis6 中aof文件位置和rdb文件位置一致,都是通过配置文件的 dir属性配置
-
redis7之后多了一个配置项是 appenddirname ,就是在 dir配置的目录下再新建一个目录,在该目录下存放aof文件。所以aof文件的目录是 dir+appenddirname
设置aof文件名称:
-
redis6时有且仅有一个,用appendfilename配置
-
redis7由于有了 Multi-part AOF 新特性,所以文件结构发生了变化,由原来的单个文件拆分成多个aof文件,分为三个类型
-
BASE:表示基础aof,它一般由子进程通过重写产生,该文件最多只有一个
-
INCR:表示增量aof,一般在aofrw开始执行时被创建,该文件可能存在多个
-
HISTORY:表示历史aof,由BASE 和 INCR变化而来,每次aofrw完成时,本次aofrw之前对应的BASE和INCR aof 都将变成HISTORY,HISTORY类型的aof会被redis自动删除
为了管理这些aof文件,我们引入了一个 manifest文件来跟踪和管理这些aof
所以redis7之后一共有三份文件 base基本文件、incr增量文件、manifest清单文件
这几种文件命名的前缀还是用 appendfilename 来配置
-
数据恢复
当执行写操作时,会在 dir(通过dir配置的文件名)文件下生成 appenddirname,在该目录下会生成三个文件
测试恢复:先写几个值,生成了aof文件后,复制一份改个名,清空库,重启redis发现库是空的,然后把之前复制的aof文件改回去,再次重启redis,发现之前写的值回来了
进行写操作,会把数据写到 appendonly.aof.1.incr.aof 中
上面那种情况是正常恢复,当aof文件发生错误时,该如何恢复呢?
发生错误可以手动给aof文件添加一些错误内容
重启redis之后,发现redis-cli 根本连接不上,而且redis服务也根本没有启动。
也就是说aof文件损坏之后,redis无法启动。如果要修复可以使用
redis-check-aof --fix appendonly.aof.1.incr.aof
修复之后,redis可以启动并连接,之前的数据也回来了
aof的优缺点
优点:
-
使用aof更加持久,有不同的fsync策略
-
aof日志是一个仅附加日志,不会出现断电时损坏的问题,即使出现问题,也可以通过redis-check-aof进行修复
-
当aof文件变得很大时,redis能够在后台自动重写aof。
-
aof以易于理解和解析的格式依次包含所有操作日志,你甚至可以轻松导出 aof文件,并对其修改
缺点:
-
aof文件通常比相同数据集的等效rdb文件大
-
根据确切的fsync策略,aof可能比rdb慢
aof重写机制
由于aof持久化是redis不断将写命令记录到aof文件中,随着redis的不断进行,aof文件越来越大,占用服务器内存越大以及aof恢复要求时间越长。
为了解决这个问题,redis新增了重写机制,当aof的文件大小超过所设定的峰值时,redis就会自动启动aof文件内容压缩,只保留可以恢复数据的最小指令集(如果命令的key相同,只保留最后一条设置该key对应值的命令,也就是 set k1 v1、set k1 v2、set k1 v3,最后只保留 set k1 v3)
上面那种方式是自动触发重写机制,除此之外还可以使用 bgrewriteaof 手动触发
自动触发需要设置的内容:
-
auto-aof-rewrite-percentage 100
-
会自动记录上一次重写后aof文件的大小,如果超过了该大小的1倍,就触发
-
-
auto-aof-rewrite-min-size 64mb
-
设置aof文件的最大容量,如果超过该容量就触发
-
上面两个条件必须同时满足才会触发自动重写
当aof文件满足上面两个条件,增量文件 appendonly.aof.1.incr.aof 会变成 appendonly.aof.2.incr.aof
基础文件 appendonly.aof.1.base.aof 会变成 appendonly.aof.2.base.aof,2里面存放的就是之前增量文件中的最小指令集
步骤:
给k1 设置值,使aof文件超过1k(我们之前设置了最大容量是1k)
当超过1k并且是上一次重写的1倍后,出发了重写机制,aof文件变成了如下:
基本文件中的内容是:
只有最后的值
如果使用 bgrewriteaof 会立刻生成下一个重写文件
aof文件重写并不是对原文件进行重新整理,而是直接读取服务器现有的键值对,然后用一条命令去替代之前记录这个键值对的多条命令,生成一个新的文件后去替换原来的文件。
重写原理:
-
在重写开始前,redis 会创建一个重写子进程,这个子进程会读取现有的aof文件,并将其包含的指令进行分析压缩并写入到一个临时文件。
-
与此同时,主进程会将新接收到的写指令一边累积到内存缓冲区中,一边继续写入到原有的aof文件,这样做是保证原有的aof文件的可用性,避免在重写过程中出现意外。
-
当重写子进程完成重写工作后,它会给父进程发一个信号,父进程收到信号后就会将内存中缓存的写指令追加到新aof文件中
-
当追加结束后,redis就会用新aof文件来代替旧aof文件,之后再写指令,就会追加到新aof文件
常用aof配置:
三、RDB+AOF 混合持久化
在redis的配置文件中将 aof-use-rdb-preamble 设置为 yes
RDB 镜像做全量持久化,AOF做增量持久化
先使用RDB进行快照存储,然后使用AOF持久化记录所有的写操作,当满足重写机制或手动触发重写时,将最新的数据存储为新的RDB记录。这样的话,重启服务的时候会从 RDB和 AOF 两部分恢复数据,既保证了数据完整性,又提高了恢复数据的性能,简单来说混合持久化方式产生的文件一部分是 RDB 文件,一部分是 AOF 文件
纯缓存模式:关闭rdb 和 aof