Redis持久化方案

Posted 即使再小的帆也能远航!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis持久化方案相关的知识,希望对你有一定的参考价值。

持久化:将内存中的数据存储硬盘进行保存,在特定的时间将保存的数据进行恢复,防止数据的意外丢失,比如服务器重启或者宕机,可以保证数据安全,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对比:

命令 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
存储效率
恢复速度
数据安全性 不安全 安全

以上是关于Redis持久化方案的主要内容,如果未能解决你的问题,请参考以下文章

Redis,持久化方案

Redis的持久化方案

Redis的持久化方案

Redis持久化方案

Redis持久化方案RDB和AOF(理论)

Redis两种持久化方案