Redis持久化方案
持久化:将内存中的数据存储硬盘进行保存,在特定的时间将保存的数据进行恢复,防止数据的意外丢失,比如服务器重启或者宕机,可以保证数据安全,Redis有两种持久化方案,一个是持久化数据,叫做RDB;一个是持久化命令,叫做AOF
RDB
定期将内存中的数据生成快照保存到磁盘里面,保存的文件为后缀为.rdb的压缩过的二进制文件,当redis重启后,会读取rdb文件恢复数据。RDB 功能最核心的是 rdbSave 和 rdbLoad 两个函数, 前者用于生成 RDB 文件并保存到磁盘,而后者则用于将 RDB 文件中的数据重新载入到内存中
RDB 文件是一个单文件的全量数据,很适合数据的容灾备份与恢复,通过 RDB 文件恢复数据库耗时较短,通常 1G 的快照文件载入内存只需 20s 左右。Redis 提供了手动触发保存、自动保存间隔两种 RDB 文件的生成方式,下面先介绍 RDB 的创建和载入过程。
手动保存
方式一:执行 save
命令,手动执行保存操作,立即执行,但是save命令因为是立即执行,是同步的,所以会阻塞当前的Redis服务器,直到当前RDB过程完成为止,有可能会造成长时间的阻塞,所以并不推荐使用!
方式二:bgsave
命令,手动启动保存操作,在后台执行;是异步的,bgsave的原理是在后台使用fork函数复制一份当前进程的副本(子进程)去执行;bgsave是对save造成阻塞的问题做了优化,将生成rdb文件的操作放在后台执行,Redis内部涉及rdb的操作都用bgsave完成
bgsave执行流程:
1.客户端发起 BGSAVE 命令,Redis 主进程判断当前是否存在正在执行备份的子进程,如果存在则直接返回
2.如果没有的话会fork一个子进程,子进程根据父进程的内存数据生成临时的快照文件,然后替换原文件
3.子进程备份完毕后向父进程发送完成信息,父进程更新统计信息
save和bgsave对比:
命令 | save | bgsave |
---|---|---|
IO 类型 | 同步 | 异步 |
是否阻塞 | 全程阻塞 | fork时阻塞 |
优点 | 不会消耗额外的内存 | 不阻塞客户端 |
缺点 | 阻塞客户端 | fork子线程会消耗内存 |
自动保存
在redis.conf中进行配置save,当满足了条件时会自动执行持久化,该操作也是通过bgsave完成的;
#配置自动持久化的 条件 save 90 1 --90秒内有一次变更 save 300 10 --300秒内有10次变更 save 60 10000 --60秒内有10000次变更 dbfilename dump.rdb --持久化文件名称 stop-writes-on-bgsave-error yes -- 在持久化过程中出错的话停止写入,默认开启 rdbcompression yes -- 使用压缩校验,会加大CPU压力,但是会减少文件体积 dir ./ 持久化文件写入的目录。默认为当前启动目录。
持久化的流程:
1.父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件
2.当子进程写入完所有数据后会用该临时文件替换旧的RDB文件,至此一次快照操作完成。
可能会有一个问题,那就是当子进程执行的时候,父进程如果此时又有新的写命令怎么办呢?
执行 fork函数时会使用写时(copy-write)策略,即fork执行的那一刻父子进程共享一份数据,当父进程有写的命令时,也会复制一份到子进程,保证子进程的数据不受影响
RDB优点:
- RDB是一个压缩的二进制文件,存储效率和恢复速度比AOF要快
- RDB可以基于某个时间点进行持久化,适用于数据备份
RDB缺点:
- 安全性不如AOF,根据配置可能要几分钟才会进行持久化,如果服务器宕机,会丢失几分钟的数据
- 数据集大时,fork的子进程会耗费内存和时间
AOF
将redis执行的写命令记录到aof日志文件中,服务器重启时再次执行aof文件中的命令恢复数据;AOF主要是为了解决数据持久化的实时性,保证数据不丢失,目前是主流方式
相关配置:
appendonly yes|no --开启AOF持久化功能 appendfsync always|everysec|no --策略 #重写相关配置 no-appendfsync-on-rewrite yes|no --是否开启重写机制,默认触发规则是上一次重写的64倍且大于1M auto-aof-rewrite-percentage 100 --默认触发规则是上次 rewrite 的一倍 auto-aof-rewrite-min-size 64mb --大于 64M
AOF文件写入的三个步骤:
1.命令追加:将Redis 执行的写命令追加到 AOF 的缓冲区 aof_buf
- 为了避免每次有写命令就直接写入磁盘,导致磁盘 IO 成为 Redis 的性能瓶颈
2.文件写入(write)和文件同步(fsync):AOF 根据对应的策略将 aof_buf 的数据同步到硬盘
- wirte:为了提高文件的写入效率,当用户调用 write 函数将数据写入文件时,操作系统会先把数据写入到一个内存缓冲区里,当缓冲区被填满或超过了指定时限后,才真正将缓冲区的数据写入到磁盘里。
- fsync:虽然操作系统底层对 write() 函数进行了优化 ,但也带来了安全问题。如果宕机内存缓冲区中的数据会丢失,因此系统同时提供了同步函数 fsync() ,强制操作系统立刻将缓冲区中的数据写入到磁盘中,从而保证了数据持久化。有三种同步策略
- always(每次):每次写入都记录一次,数据完全不会丢失,性能较低
- everysec(每秒):每秒记录一次,数据准确性较高,性能较高,在系统突然宕机的情况下会丢失1秒的数据
- no(系统控制):由系统控制同步到AOF文件的周期,整体过程不可控
3.文件重写(rewrite):定期对 AOF 进行重写,从而实现对写命令的压缩。
- 对aof文件进行压缩,只保留可以恢复数据的最小指令集,比如对同一个key操作的命令只保留最后一个,已经超时的数据不再写入aof文件
AOF优点:
- AOF可以保证数据最多只有1秒的丢失,AOF比RDB更安全
AOF缺点 :
- 对于相同的数据集,AOF 文件的体积要远远大于 RDB 文件,数据恢复会比较慢
混合持久化
在重启 Redis 服务器时,一般很少使用 RDB 快照文件来恢复内存状态,因为会丢失大量数据。更多的是使用 AOF 文件进行命令重放,但是执行 AOF 命令性能相对 RDB 来说要慢很多。这样在 Redis 数据很大的情况下,启动需要消耗大量的时间。
鉴于 RDB 快照可能会造成数据丢失,AOF 指令恢复数据慢,Redis 4.0 版本提供了一套基于 AOF-RDB 的混合持久化机制,保留了两种持久化机制的优点。这样重写的 AOF 文件由两部份组成,一部分是 RDB 格式的头部数据,另一部分是 AOF 格式的尾部指令。
Redis 4.0 版本的混合持久化功能默认是关闭的,通过配置 aof-use-rdb-preamble 为 yes 开启此功能:
aof-use-rdb-preamble yes
恢复机制
1.当 AOF 持久化功能开启时,Redis 服务器启动时优先执行 AOF 文件的命令恢复数据,只有当 AOF 功能关闭时,才会优先载入 RDB 快照的文件数据
2.当 AOF 功能开启,且 AOF 文件不存在时,即使 RDB 文件存在也不会加载
对比
方案 | RDB | AOF |
---|---|---|
存储效率 | 快 | 慢 |
恢复速度 | 快 | 慢 |
数据安全性 | 不安全 | 安全 |