Redis持久化
为什么要持久化
Redis数据存储在缓存,这样虽然很快,但是一但Redis崩了,重启之后缓存中的数据就会全部丢失,进而引发灾难性问题(缓存雪崩等)。
- 缓存雪崩
当Redis正常工作时,很多数据可以直接从Redis中获取,不需要每次都查询数据,从而缓解数据库的压力提升系统的性能和吞吐量。
但是当Redis突然挂掉时(进程被杀、机器坏了、断电等灾难性故障),如果没有做持久化配置,重启之后的Redis是无法恢复之前的缓存数据的,此时原本通过查询缓存就能解决的请求会全部都怼到数据库上面(程序的处理逻辑一般都是当请求查询缓存没有命中时,就会去查询数据库),数据库承受不住高并发就会挂掉。Redis中的数据大部分都是从数据库中获取的,数据库挂掉之后,Redis中的数据也就无法恢复了。
如果Redis做了持久化配置 ,重启之后会先恢复数据,进而就避免了后面的一系列问题。
Redis持久化两种方案
Redis持久化是指将缓存中的数据同步到磁盘中,当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。
Redis提供了两种不同的持久化方法来将数据存储到硬盘里面。一种方法叫快照(snapshotting,RDB),它可以将存在于某一时刻的所有数据都写入硬盘里面(dump.rdb文件)。另一种方法叫只追加文件(append-only file,AOF),它会在执行写命令时,将被执行的写命令复制到硬盘里面(appendonly.aof文件)。
-
RDB(redis database)
在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是Snapshot快照,它恢复时是将快照文件直接读到内存里。
Redis会单独创建(fork)一个子进程来进行持久化,将当前父进程的数据库数据复制到子进程的内存中,然后由子进程写入到临时文件中,持久化的过程结束了,再用这个临时文件替换上次的快照文件,然后子进程退出,内存释放。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。
如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那么RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
Fork:Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。
-
AOF(append-only file)
以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,Redis启动之初会读取该文件来重新构建数据,换言之,Redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作 。
RDB配置
-
RDB的开启配置
要启用RDB,需要修改Redis的配置文件redis.conf
#save: 多久执行一次自动快照操作
save 900 1 #900秒时间,至少有一条数据更新,Redis就会自动触发BGSAVE命令
save 300 10 #300秒时间,至少有10条数据更新,Redis就会自动触发BGSAVE命令
save 60 10000 #60秒时间,至少有10000条数据更新,Redis就会自动触发BGSAVE命令
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触发条件
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
- 关闭rdb的命令:
redis-cli config set save " "
- 修改配置文件redis.conf
save ""
#save 900 1
#save 300 10
#save 60 10000
将save的具体配置注释掉,并打开save "" 的注释,使得 save " " 生效,即可关闭rdb;
AOF配置
- AOF的开启配置
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:设置重写的基准值
# 如果觉得AOF重写执行得过于频繁,可以把auto-aof-rewrite-percentage设置100以上,可以适当降低重写频率
auto-aof-rewrite-percentage 100
# Auto-aof-rewrite-percentage:设置重写的基准值
auto-aof-rewrite-min-size 64mb
** 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时触发)
- AOF触发机制
直接根据 appendfsync 的设置进行触发
- AOF的关闭
关闭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相同
补充
持久化的方案(Redis默认是RDB):rdb 默认是开启的
如果有开启aof 则不会从rdb去恢复数据,只会从aof文件恢复
所以如果我们开启了aof 则可以关闭rdb 以节省磁盘空间(磁盘空间足够可以都保留)
Redis 提供了多种不同级别的持久化方式:
1、RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)。
2、AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。
3、Redis 还可以同时使用 AOF 持久化和 RDB 持久化。 在这种情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。