Redis持久化方案

litterfrog 2020-05-11

持久化:将内存中的数据存储硬盘进行保存,在特定的时间将保存的数据进行恢复,防止数据的意外丢失,比如服务器重启或者宕机,可以保证数据安全,Redis有两种持久化方案,一个是持久化数据,叫做RDB;一个是持久化命令,叫做AOF

RDB

定期将内存中的数据生成快照保存到磁盘里面,保存的文件为后缀为.rdb的压缩过的二进制文件,当redis重启后,会读取rdb文件恢复数据。RDB 功能最核心的是 rdbSaverdbLoad 两个函数, 前者用于生成 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对比:

命令savebgsave
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 文件存在也不会加载

对比

方案RDBAOF
存储效率
恢复速度
数据安全性不安全安全

相关推荐

DiamondTao / 0评论 2020-08-30