12.redis 持久化

redis 持久化

  • redis 持久化
    • redis持久化策略
      • RDB => Redis DataBase 定期备份
        • rdb 文件处理
        • rdb 优缺点
      • AOF => Append Only File 实时备份
      • AOF 工作流程
      • AOF 缓冲区刷新策略
      • AOF 重写机制
        • AOF 重写流程
    • 混合持久化
    • 持久化流程
    • 总结

redis 持久化

redis 是一个内存数据库,把数据存储在内存中的,内存中的数据是不持久的,要想做到持久,就需要让redis把数据存储到硬盘上。
为了保证速度块,数据肯定还是得在内存中,但是为了持久化,数据还得想办法存储在硬盘上。

redis持久化策略

RDB => Redis DataBase 定期备份

RDB 定期的把 Redis 内存中的所有数据,都给写入到硬盘中,生成一个 “快照”。
“定期”具体来说又分为两种方式:

  1. 手动触发
    即通过redis客户端,执行特定的命令(save / bgsave),来触发快照生成。

    • save
      执行 save 命令的时候,redis 就会全力以赴的进行 “快照生成” 操作,此时就会阻塞 redis 其他客户端的命令~~ (进而导致类似于 keys *的后果)

      save 命令就是直接再当前进程中,直接往 /var/lib/redis/dump.rdb 文件中写入,没有文件替换操作。

    • bgsave bg => background(后面)
      bgsave 不会影响 redis 服务器处理其他客户端的请求和命令。
      其中bgsave的执行流程图如下:
      12.redis 持久化_第1张图片
      1.父进程先判断当前是否已经存在其他正在工作的子进程。
      即比如现在已经有一个子进程正在执行 bgsave,此时就直接把当前的 bgsave 返回~~
      2.如果没有其他工作的子进程,就通过 fork 这样的系统调用去创建一个子进程
      3.默认情况下父进程会阻塞等待子进程退出。
      即父进程设置了"nohup"参数为"no"。这就意味着父进程将会阻塞等待子进程完成持久化操作,并且在此期间无法处理新的命令请求。
      如果父进程设置了"nohup"参数为"yes",它将不会等待子进程退出。此时子进程负责进行写文件,生成快照。父进程继续接收客户端的请求,继续正常提供服务。
      4.子进程完成整体的持久化过程之后,就会通知父进程,父进程就会更新一些统计信息,进而子进程就可以结束销毁了。
      其中 redis 生成的快照 rdb 文件,是存放在 redis 的工作目录中的。该路径也是在redis 配置文件中进行设置的。配置文件通常在 /etc/redis/redis.conf
      在这里插入图片描述
      rdb 机制生成的镜像文件,redis 服务器默认就是开启了 rdb 的
      12.redis 持久化_第2张图片
      其中 rbd 是 一个二进制文件,即把内存中的数据以压缩的形式,保存到这个二进制文件中。
      当子进程生成 rdb 镜像操作的时候,此时就会把要生成的快照数据,先保存到一个临时文件中,当这个快照生成完毕之后,再删除之前的的 rdb 文件,把新生成的临时的 rdb 文件名字改成刚才的 dump.rdb,至始至终,rdb文件只有一个。

  2. 自动触发
    在redis配置文件中,设置一下,让redis 每隔多长时间/每产生多少次修改就触发。
    默认配置是下面的三种的档位:

    1. 时间过了900秒,且期间至少有1 次key的变化时
    2. 时间过了300秒,且期间至少有10次key的变化时
    3. 时间过了60秒,且期间至少有10000次key的变化时
    

12.redis 持久化_第3张图片

rdb 文件处理

  • 保存:RDB ⽂件保存再 dir 配置指定的⽬录(默认 /var/lib/redis/)下,⽂件名通过 dbfilename 配置(默认 dump.rdb)指定。可以通过执行 config set dir {newDir} 和 config set dbfilename {newFilename} 运⾏期间动态执行,当下次运行时 RDB ⽂件会保存到新目录。
  • 压缩:Redis 默认采用 LZF 算法对⽣成的 RDB 文件做压缩处理,压缩后的⽂件远远小于内存大小d,默认开启,可以通过参数 config set rdbcompression {yes|no} 动态修改。
  • 校验:如果 Redis 启动时加载到损坏的 RDB 文件会拒绝启动。这时可以使用Redis 提供的 redischeck-dump ⼯具检测 RDB 文件并获取对应的错误报告。

rdb 优缺点

  • RDB 是⼀个紧凑压缩的⼆进制⽂件,代表 Redis 在某个时间点上的数据快照。非常适用于备份,全 量复制等场景。⽐如每 6 小数执行 bgsave 备份,并把 RDB ⽂件复制到远程机器或者⽂件系统中 (如 hdfs)用于灾备。
  • Redis 加载 RDB 恢复数据远远快于 AOF 的⽅式。
  • RDB 方式数据没办法做到实时持久化 / 秒级持久化。因为 bgsave 每次运行都要执行 fork 创建⼦进程,属于重量级操作,频繁执行成本过高。
  • RDB 文件使用特定⼆进制格式保存,Redis 版本演进过程中有多个 RDB 版本,兼容性可能有⻛险。

AOF => Append Only File 实时备份

AOF 类似于 mysql 的binlong,就会把用户的每个操作,都记录到文件中。
当redis重新启动的时候,就会读取这个aof文件中的内容,用来恢复数据。
当开启 AOF 的时候,rdb 文件就不生效了,启动的时候就不再读取rdb文件内容了,以AOF文件为主。
AOF是一个文本文件,默认一般是关闭状态,修改配置文件来开启 AOF 功能。

12.redis 持久化_第4张图片
其中上面那行表示是否开启 AOF,下面那行表示的是生成的AOF文件名,它生成所存放的路径和 rdb 所在的目录是一样的。

AOF 工作流程

AOF 工作流程图如下:
12.redis 持久化_第5张图片
步骤1) 所有的写⼊命令会追加到 aof_buf(缓冲区)中。
步骤2) AOF 缓冲区根据对应的策略向硬盘做同步操作。
步骤3) 随着 AOF ⽂件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
步骤4) 当 Redis 服务器启动时,可以加载 AOF 文件进行数据恢复。

AOF 缓冲区刷新策略

Redis 提供了多种 AOF 缓冲区同步⽂件策略,由参数 appendfsync 控制,不同值的含义。默认是 everysec级别。
12.redis 持久化_第6张图片

  • always::只要写入到缓存区就立即刷新,频率最高的,数据最可靠的,性能最低。
  • everysec:每秒刷新一次缓冲区,频率较低一些,数据可靠性低一些,性能会提高。
  • no:Redis不会主动将写入操作同步到磁盘,而是依赖操作系统来处理磁盘同步。

系统调用 write 和 fsync 说明:

  • write 操作会触发延迟写(delayed write)机制。Linux 在内核提供⻚缓冲区⽤来提供硬盘 IO 性 能。write 操作在写⼊系统缓冲区后⽴即返回。同步硬盘操作依赖于系统调度机制,例如:缓冲区 ⻚空间写满或达到特定时间周期。同步⽂件之前,如果此时系统故障宕机,缓冲区内数据将丢失。
  • fsync 针对单个⽂件操作,做强制硬盘同步,fsync 将阻塞直到数据写⼊到硬盘。

AOF 重写机制

随着命令不断写⼊ AOF,⽂件会越来越⼤,为了解决这个问题,Redis 引⼊ AOF 重写机制压缩⽂件体积。AOF ⽂件重写是把 Redis 进程内的数据转化为写命令同步到新的 AOF ⽂件。
为什么重写后的 AOF 可以变小?有如下原因:

  • 进程内已过期的数据不再写⼊⽂件。
  • 旧的 AOF 中的⽆效命令,例如 del、hdel、srem 等重写后将会删除,只需要保留数据的最终版本。
  • 多条写操作合并为⼀条,例如 lpush list a、lpush list b、lpush list 从可以合并为 lpush list a b c。

较小的 AOF ⽂件一方面降低了硬盘空间占⽤,一方面可以提升启动 Redis 时数据恢复的速度。

AOF 重写过程一样也是分为手动触发和自动触发:

  1. 手动触发
    手动触发:调用 bgrewriteaof 命令
  2. 自动触发
    自动触发:根据 auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 参数确定自动触发时机。
  • auto-aof-rewrite-min-size:表示触发重写时 AOF 的最小文件大小,默认为 64MB。
  • auto-aof-rewrite-percentage:代表当前 AOF 占用小相比较上次重写时增加的比例。

AOF 重写流程

12.redis 持久化_第7张图片

  1. 执行 AOF 重写请求。
    如果当前进程正在执行 AOF 重写,请求不执⾏。
    如果当前进程正在执行 bgsave 操作,重写命令延迟到 bgsave 完成之后再执行。

  2. 父进程执行 fork 创建子进程。

  3. 重写
    a. 父进程 fork 之后,继续响应其他命令。所有修改操作写⼊ AOF 缓冲区,并根据 appendfsync 策略同步到硬盘,保证旧 AOF ⽂件机制正确。
    b. 子进程只有 fork 之前的所有内存信息,父进程中需要将 fork 之后这段时间的修改操作写⼊AOF 重写缓冲区(即aof_rewrite_buf)中。

  4. 子进程根据内存快照,将命令合并到新的 AOF ⽂件中。

  5. 子进程完成重写
    a. 新⽂件写⼊后,子进程发送信号给父进程。
    b. 父进程把 aof_rewrite_buf 缓冲区内临时保存的命令追加到新 AOF ⽂件中。
    c. ⽤新 AOF ⽂件替换⽼ AOF ⽂件。

混合持久化

混合持久化指的是将Redis的数据同时持久化到磁盘的两种方式的结合使用。
混合持久化将这两种方式结合起来:

  • Redis会定期执行RDB快照,将内存中的数据快照保存到磁盘上的RDB文件中。
  • 同时,Redis会将写操作命令追加到AOF日志中,以保持AOF文件的实时更新。

这样,即使Redis在RDB快照之间崩溃,也可以通过AOF日志还原最后一次快照之后的数据。而且,RDB提供了一个全量备份,可以用于更长时间的数据恢复。

当配置文件中,开启这个选项时,AOF文件内容不是文本文件,而是二进制的。
12.redis 持久化_第8张图片

持久化流程

当 Redis 启动时,会根据 RDB 和 AOF ⽂件的内容,进⾏数据恢复,具体流程如下:
12.redis 持久化_第9张图片

总结

  • Redis 提供了两种持久化⽅案:RDB 和 AOF。
  • RDB 视为内存的快照,产⽣的内容更为紧凑,占用空间较⼩,恢复时速度更快。但产⽣ RDB 的开销较⼤,不适合进⾏实时持久化,⼀般⽤于冷备和主从复制。
  • AOF 视为对修改命令保存,在恢复时需要重放命令。并且有重写机制来定期压缩 AOF ⽂件。
  • RDB 和 AOF 都使⽤ fork 创建⼦进程,利⽤ Linux ⼦进程拥有⽗进程内存快照的特点进⾏持久化,尽可能不影响主进程继续处理后续命令。

你可能感兴趣的:(Redis,redis,数据库)