十一、Redis持久化-RDB、AOF

Redis提供了两种持久化数据的方式。一种是RDB快照,另一种是AOF日志。RDB快照是一次全量备份,AOF日志是连续的增量备份。RDB快照是以二进制的方式存放Redis中的数据,在存储上比较紧凑;AOF日志记录的是对内存数据修改的指令文本记录。Redis提供的持久化机制,可以有效的避免Redis因为进程退出导出的数据丢失问题。

1、RDB快照持久化

RDB持久化是在某个时间点做一次全量的数据备份。触发RDB持久化的方式分为手动触发自动触发。

1.1、手动触发

手动触发分别对应savebgsave命令

  • save命令:会阻塞当前Redis服务器,直到RDB过程完成为止,如果数据量较大的话,会造成长时间的阻塞,线上环境不建议使用。
  • bgsave命令:就是background save。执行bgsave命令时Redis主进程会fork一个子进程来进行数据的备份,完成后自动结束(操作系统的copy on write机制,简称COW)。所以Redis主进程阻塞时间只在fork阶段那一会。相对于save命令,阻塞时间更短。

1.2、自动触发

  • 配置redis.conf,触发规则,自动执行
c 复制代码
# 当在规定的时间内,Redis发生了写操作的个数满足条件,会触发发生BGSAVE命令。
# save <seconds> <changes>
# 当用户设置了多个save的选项配置,只要其中任一条满足,Redis都会触发一次BGSAVE操作
save 900 1 
save 300 10 
save 60 10000
# 以上配置的含义:900秒之内至少一次写操作、300秒之内至少发生10次写操作、
# 60秒之内发生至少10000次写操作,只要满足任一条件,均会触发bgsave
  • 执行shutdown命令关闭服务器时,如果没有开启AOF持久化功能,那么会自动执行一次bgsave命令。
  • 如果从节点执行全量复制操作,主节点会自动执行bgsave命令生成RDB文件并发送给从节点。更多细节见主从同步。
  • 执行debug reload命令重新加载Redis时,也会自动触发save操作。

1.3、RDB执行流程

Redis使用操作系统的多进程(Copy On Write, COW)机制来实现RDB快照持久化。

  1. 执行bgsave命令时,Redis主进程会检查是否有子进程在执行RDB/AOF持久化任务,如果有的话,直接返回。
  2. Redis主进程会fork一个子进程来执行RDB的持久化操作,fork操作会阻塞主进程(影响Redis的读写),fork操作完成之后,会发消息给主进程,从而不再阻塞主进程。(阻塞主进程只在fork子进程时,后续的子进程处理操作都不会阻塞主进程);通过 info stats 命令可以查看latest_fork_usec选项,可以获取最近一个fork操作的耗时,单位为微秒。
  3. 主进程fork完子进程后,bgsave命令会返回"BackGround saving started"信息,并不再阻塞主进程,可以继续响应其他命令。
  4. 子进程创建RDB文件,根据主进程生成临时快照文件,持久化完成后会使用临时快照文件替换掉原来的RDB文件(该过程不会影响主进程的读写,但Redis的写操作不会同步到主进程的内存中,而是会写到一个临时的内存区域作为一个副本)。执行lastsave命令可以获取最后一次生成的RDB时间,对应info统计的rdb_last_save_time选项。
  5. 子进程完成RDB持久化后会发消息给主进程,通知RDB持久化完成(同时将上阶段内存副本中的增量写数据同步到主内存中)。

1.4、RDB优缺点

1.4.1、优点

  • RDB文件小(二进制,存储比较紧凑),非常适合定时备份,用于灾难恢复。
  • Redis加载RDB文件的速度比AOF快很多,因为RDB文件中直接存储的是内存数据,而AOF文件中存储的是一条条命令,需要重新执行一遍。

1.4.2、缺点

  • RDB无法做到实时持久化,若在两次bgsave命令间宕机,则会丢失两次执行区间内的增量数据,不适合用于实时性要求较高的场景。
  • RDB的cow机制中,fork子进程属于重量级操作,并且会阻塞主进程
  • RDB文件使用特定的二进制格式保存,Redis版本演化过程中有多个格式的RDB版本,存在老版本Redis服务无法兼容新版RDB文件格式的问题。

2、AOF日志持久化

AOF(append only file)持久化 :以独立日志的方式记录每次的写命令,重启时需要重新执行一遍AOF文件中的命令来达到恢复数据的目的。AOF日志会在持续运行中逐渐增大,由于Redis重启过程需要优先加载AOF日志进行指令重放以恢复数据,恢复时间会无比漫长。所以需要定期进行AOF重写,对AOF日志进行瘦身(合并命令),目前AOF是Redis的主流持久化方式。

2.1、开启方式

AOF默认是关闭的,通过redis.conf配置文件进行开启。

cpp 复制代码
## 此选项为aof功能的开关,默认为"no",可以通过"yes"来开启aof功能  
## 只有在"yes"下,aof重写/文件同步等特性才会生效  
appendonly yes  

## 指定aof文件名称  
appendfilename appendonly.aof  

## 指定aof操作中文件同步策略,有三个合法值:always everysec no,默认为everysec  
appendfsync everysec  
## 在aof-rewrite期间,appendfsync是否暂缓文件同步,"no"表示"不暂缓","yes"表示"暂缓",默认为"no"  
no-appendfsync-on-rewrite no  

## aof文件rewrite触发的最小文件尺寸(mb,gb),只有大于此aof文件大于此尺寸是才会触发rewrite,默认"64mb",建议"512mb"  
auto-aof-rewrite-min-size 64mb  

## 相对于"上一次"rewrite,本次rewrite触发时aof文件应该增长的百分比  
## 每一次rewrite之后,redis都会记录下此时"新aof"文件的大小(例如A)
## aof文件增长到A*(1 + p)之后,触发下一次rewrite,每一次aof记录的添加,都会检测当前aof文件的尺寸。  
auto-aof-rewrite-percentage 100


AOF是对文件的操作,因此对于变更比较频繁的服务,那么会造成磁盘的IO负荷加重。此外因为Linux对文件的操作是采用'延迟写入'的方式,因此并非每次对文件的write操作都会立即写入到磁盘中,而是进入到一个buffer中,当buffer中的数据达到阈值时,就会触发实际写入(也有其他时机),这是Linux对文件系统的优化。

同时Linux也提供fsync(int fd)函数,可以用来将指定文件的内容强制刷新到磁盘中。只要Redis进程实时调用fsync函数就可以保证AOF日志的内容不会丢失。但是fsync是个磁盘IO操作,他很慢!如果Redis执行一条指令就要执行fsync一次,那么Redis的性能就会收到很大的影响。

因此,Redis在其配置文件中提供了3中策略,用来同步AOF日志记录:

  • always:每一条AOF指令都立即同步到磁盘文件中,性能很低,但是很安全。
  • everysec:每秒同步一次,性能和安全都比较中庸,也是Redis推荐的方式。如果遇到服务器宕机的情况,最多会丢失1s的AOF日志记录。
  • no:Redis永不直接调用fsync文件同步,而是将文件同步操作交给系统来决定,何时同步磁盘。性能较好,但是不安全。

2.2、重写(rewrite)机制

随着Redis运行时间的增长,AOF日志文件会越来越大,为了解决这个问题,Redis需要定期对AOF日志进行重写,来对AOF日志文件进行瘦身。
AOF Rewrite虽然是'压缩'AOF文件的过程,但是并非是采用'基于原AOF文件'进行重写或者压缩操作的。而是类似RDB快照的方式:基于Copy On Write,全量遍历内存中的数据,然后逐个序列化到文件汇总。因此AOF rewrite能够正确反映当前内存数据的状态。
AOF重写(bgrewriteaof)和ADB(bgsave)过程类似,都是fork一个子进程来进行处理。
AOF对日志文件进行压缩时,为了防止单条命令过大造成客户端缓冲区溢出,对于list、set、zset、hash等类型操作,以64个元素为界进行拆分成多条。
AOF重写降低了文件的大小,另一方面,更小的文件可以更快的被Redis加载。

在重写过程中,对于新的变更操作将仍然被写入到原AOF文件中,同时这些新的变更操作也会被Redis收集起来(aof-rewrite-buffer)。当内存中的数据全被写入到新的AOF文件后,收集的新的变更操作也会一并追加到新AOF文件中。然后将新的AOF文件命名为appendonly.aof,使用新的AOF文件替换掉老的AOF文件。

2.3、触发机制

RDB类似,AOF也有两种触发机制**:手动触发自动触发**。

2.3.1、手动触发

直接调用bgrewriteaof命令。

redis-cli -h ip -p port bgrewriteaof

2.3.2、自动触发

根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机:

auto-aof-rewrite-min-size:表示运行AOF文件重写时的文件最小体积,默认为64MB。

auto-aof-rewrite-percentage:代表当前AOF文件空间(auto_current_size)和上一次重写后AOF文件空间(aof_base_size)的值

自动触发时机=auto_current_size>auto_aof_rewrite_min_size && (auto_current_size-auto_base_size)/auto_base_size >= auto_aof_rewrite_percentage

其中aof_current_size和aof_base_size可以在info Persistence统计信息中查看。

Redis重启时,可以加载AOF文件进行数据恢复。

2.4、AOF优缺点

2.4.1、优点

AOF只是追加写入文件,对服务器性能影响较小,速度比RDB要快,消耗的内存较少。

2.4.2、缺点

  • AOF方式生成的日志文件会越来越大,因此需要不断的进行AOF重写,进行瘦身。
  • 即使经过AOF重写,由于文件是文本文件,文件提交较大(相比较于二进制文件)。
  • AOF重写命令式的恢复数据,速度明显比RDB慢。

3、Redis 4.0混合式持久化

  • 仅使用RDB快照方式恢复数据,由于快照时间粒度较大,会丢失大量的数据。
  • 仅使用AOF重放方式恢复数据,日志性能相对于RDB来说慢。且需要不停的进行日志的重写。在Redis实例很大的情况下,启动需要花费很长的时间。

Redis 4.0为了解决这个问题,带来一个全新的持久化选项--**混合持久化。**将RDB的内容和增量的AOF日志文件放在一起。这里的AOF日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量AOF日志,通常这部分AOF日志很小。相当于:

  • 大量数据使用粗粒度(时间上)的rdb快照方式,性能高,回复时间快。
  • 增量数据使用细粒度(时间上)的AOF日志,尽量保证数据不丢失。

Redis重启时,可以先加载RDB文件,然后在重放AOF日志就可以完全替代之前的AOF全量文件重放,重启效率因此大幅度提升。

相关推荐
水月梦镜花2 小时前
redis:list列表命令和内部编码
数据库·redis·list
掘金-我是哪吒3 小时前
微服务mysql,redis,elasticsearch, kibana,cassandra,mongodb, kafka
redis·mysql·mongodb·elasticsearch·微服务
ketil275 小时前
Ubuntu 安装 redis
redis
王佑辉6 小时前
【redis】redis缓存和数据库保证一致性的方案
redis·面试
Karoku0667 小时前
【企业级分布式系统】Zabbix监控系统与部署安装
运维·服务器·数据库·redis·mysql·zabbix
gorgor在码农7 小时前
Redis 热key总结
java·redis·热key
想进大厂的小王7 小时前
项目架构介绍以及Spring cloud、redis、mq 等组件的基本认识
redis·分布式·后端·spring cloud·微服务·架构
Java 第一深情7 小时前
高性能分布式缓存Redis-数据管理与性能提升之道
redis·分布式·缓存
minihuabei13 小时前
linux centos 安装redis
linux·redis·centos
monkey_meng15 小时前
【Rust中多线程同步机制】
开发语言·redis·后端·rust