redis 持久化策略

Redis 的持久化策略

redis 提供了两种持久化策略:

  • RDB:指定间隔时间内超过指定操作 redis 数据库的次数进行快照储存

  • AOF:记录对 redis 服务器的操作命令,重启时执行这些命令来恢复数据


RDB持久化配置
# 时间策略    -- 可配置多个
save 900 1   -- 表示900s内如有1条操作命令,就会触发一次快照
save 300 10  -- 表示300s内如有10条操作命令,就会触发一次快照
save ""      -- 表示禁用 RDB 配置  

# 文件名称
dbfilename dump.rdb

# 文件保存路径
dir /home/work/app/redis/data/

# 如果持久化出错,主进程是否停止写入
stop-writes-on-bgsave-error yes

# 是否压缩
rdbcompression yes

# 导入时是否检查
rdbchecksum yes

AOF 持久化配置
# 是否开启aof
appendonly yes/no

# 文件名称
appendfilename "appendonly.aof"

# 同步方式
appendfsync everysec

# aof重写期间是否同步
no-appendfsync-on-rewrite no

# 重写触发配置
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 加载aof时如果有错如何处理
aof-load-truncated yes

# 文件重写策略
aof-rewrite-incremental-fsync yes

appendfsync everysec 它其实有三种模式:

  • always:把每个写命令都立即同步到 aof,很慢,但是很安全
  • everysec:每秒同步一次,是折中方案
  • no:redis不处理交给 OS 来处理,非常快,但是也最不安全

一般情况下都采用 everysec 配置,这样可以兼顾速度与安全,最多损失1s的数据。

aof-load-truncated yes 如果该配置启用,在加载时发现 aof 尾部不正确是,会向客户端写入一个log,但是会继续执行,如果设置为 no ,发现错误就会停止,必须修复后才能重新加载。


工作原理

Redis 有内部的定时任务机制来保证持久化策略的运行。定时任务执行的频率可以在配置文件中通过 hz 10 来设置(这个配置表示1s内执行10次,也就是每100ms触发一次定时任务)。该值最大能够设置为:500,但是不建议超过:100,因为值越大说明执行频率越频繁越高,这会带来CPU的更多消耗,从而影响主进程读写性能。

定时任务使用的是 Redis 自己实现的 TimeEvent,它会定时去调用一些命令完成定时任务,这些任务可能会阻塞主进程导致Redis性能下降。因此我们在配置 Redis 时,一定要整体考虑一些会触发定时任务的配置,根据实际情况进行调整。


RDB 原理

在 Redis 中 RDB 持久化的触发分为两种:自己手动触发与 Redis 定时触发。

针对RDB方式的持久化,手动触发可以使用:

  • save:会阻塞当前 Redis 服务器,直到持久化完成,线上应该禁止使用。
  • bgsave:该触发方式会 fork 一个子进程,由子进程负责持久化过程,因此阻塞只会发生在 fork 子进程的时候。

而自动触发的场景主要是有以下几点:

  • 根据我们的 save m n 配置规则自动触发;
  • 从节点全量复制时,主节点发送 rdb 文件给从节点完成复制操作,主节点会触发 bgsave
  • 执行 debug reload 时;
  • 执行 shutdown时,如果没有开启 aof,也会触发。

由于 save 基本不会被使用到,我们重点看看 bgsave 这个命令是如何完成 RDB 的持久化的。
在这里插入图片描述
这里注意的是 fork 操作会阻塞,导致 Redis 读写性能下降。我们可以控制单个 Redis 实例的最大内存,来尽可能降低 Redis 在 fork 时的事件消耗。以及上面提到的自动触发的频率减少 fork 次数,或者使用手动触发,根据自己的机制来完成持久化。


AOF 原理

AOF 的整个流程大体来看可以分为两步,一步是命令的实时写入(如果是 appendfsync everysec 配置,会有1s损耗),第二步是对 aof 文件的重写。

对于增量追加到文件这一步主要的流程是:命令写入=》追加到 aof_buf =》同步到 aof 磁盘。那么这里为什么要先写入 buf 在同步到磁盘呢?如果实时写入磁盘会带来非常高的磁盘 IO,影响整体性能。

aof 重写是为了减少 aof 文件的大小,可以手动或者自动触发,关于自动触发的规则请看上面配置部分。fork 的操作也是发生在重写这一步,也是这里会对主进程产生阻塞。

手动触发: bgrewriteaof自动触发 就是根据配置规则来触发,当然自动触发的整体时间还跟Redis 的定时任务频率有关系。

下面来看看重写的一个流程图:
在这里插入图片描述
对于上图有四个关键点补充一下:

  1. 在重写期间,由于主进程依然在响应命令,为了保证最终备份的完整性;因此它依然会写入旧的AOF file 中,如果重写失败,能够保证数据不丢失。
  2. 为了把重写期间响应的写入信息也写入到新的文件中,因此也会为子进程保留一个 buf,防止新写的 file 丢失数据。
  3. 重写是直接把当前内存的数据生成对应命令,并不需要读取老的 AOF 文件进行分析、命令合并。
  4. AOF 文件直接采用的文本协议,主要是兼容性好、追加方便、可读性高可认为修改修复。

不管是RDB还是AOF都是先写入一个临时文件,然后通过 rename 完成文件的替换工作。


从持久化中恢复数据

数据的备份、持久化做完了,我们如何从这些持久化文件中恢复数据呢?如果一台服务器上有既有RDB 文件,又有 AOF 文件,该加载谁呢?

其实想要从这些文件中恢复数据,只需要重新启动 Redis 即可。我们还是通过图来了解这个流程:

在这里插入图片描述
启动时会先检查 AOF 文件是否存在,如果不存在就尝试加载 RDB。那么为什么会优先加载 AOF 呢?因为 AOF 保存的数据更完整,通过上面的分析我们知道 AOF 基本上最多损失1s的数据。


性能与实践

通过上面的分析,我们都知道 RDB 的快照、AOF 的重写都需要 fork,这是一个重量级操作,会对Redis 造成阻塞。因此为了不影响 Redis 主进程响应,我们需要尽可能降低阻塞。

  1. 降低 fork 的频率,比如可以手动来触发 RDB 生成快照、与 AOF 重写;
  2. 控制 Redis 最大使用内存,防止 fork 耗时过长;
  3. 使用更牛逼的硬件;
  4. 合理配置 Linux 的内存分配策略,避免因为物理内存不足导致 fork 失败。

在线上我们到底该怎么做?我提供一些自己的实践经验。

  1. 如果 Redis 中的数据并不是特别敏感或者可以通过其它方式重写生成数据,可以关闭持久化,如果丢失数据可以通过其它途径补回;
  2. 自己制定策略定期检查Redis的情况,然后可以手动触发备份、重写数据;
  3. 单机如果部署多个实例,要防止多个机器同时运行持久化、重写操作,防止出现内存、CPU、IO资源竞争,让持久化变为串行;
  4. 可以加入主从机器,利用一台从机器进行备份处理,其它机器正常响应客户端的命令;
  5. RDB 持久化与 AOF 持久化可以同时存在,配合使用。

本文转载自:https://segmentfault.com/a/1190000015983518

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值