一文看懂Redis的持久化原理

Redis为持久化提供了两种方式:redis

  • RDB:在指定的时间间隔能对你的数据进行快照存储。
  • AOF:记录每次对服务器写的操做,当服务器重启的时候会从新执行这些命令来恢复原始的数据。

本文将经过下面内容的介绍,但愿可以让你们更全面、清晰的认识这两种持久化方式,同时理解这种保存数据的思路,应用于本身的系统设计中。shell

  • 持久化的配置
  • RDB与AOF持久化的工做原理
  • 如何从持久化中恢复数据
  • 关于性能与实践建议

持久化的配置

为了使用持久化的功能,咱们须要先知道该如何开启持久化的功能。安全

RDB的持久化配置

# 时间策略
save 900 1
save 300 10
save 60 10000
 # 文件名称
dbfilename dump.rdb
 # 文件保存路径
dir /home/work/app/redis/data/
 # 若是持久化出错,主进程是否中止写入
stop-writes-on-bgsave-error yes
 # 是否压缩
rdbcompression yes
 # 导入时是否检查
rdbchecksum yes
复制代码

配置其实很是简单,这里说一下持久化的时间策略具体是什么意思。bash

  • save 900 1 表示900s内若是有1条是写入命令,就触发产生一次快照,能够理解为就进行一次备份
  • save 300 10 表示300s内有10条写入,就产生快照

下面的相似,那么为何须要配置这么多条规则呢?由于Redis每一个时段的读写请求确定不是均衡的,为了平衡性能与数据安全,咱们能够自由定制什么状况下触发备份。因此这里就是根据自身Redis写入状况来进行合理配置。服务器

stop-writes-on-bgsave-error yes 这个配置也是很是重要的一项配置,这是当备份进程出错时,主进程就中止接受新的写入操做,是为了保护持久化的数据一致性问题。若是本身的业务有完善的监控系统,能够禁止此项配置, 不然请开启。app

关于压缩的配置 rdbcompression yes ,建议没有必要开启,毕竟Redis自己就属于CPU密集型服务器,再开启压缩会带来更多的CPU消耗,相比硬盘成本,CPU更值钱。运维

固然若是你想要禁用RDB配置,也是很是容易的,只须要在save的最后一行写上:save ""性能

AOF的配置

# 是否开启aof
appendonly yes
 # 文件名称
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
复制代码

仍是重点解释一些关键的配置:spa

appendfsync everysec 它其实有三种模式:debug

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

通常状况下都采用 everysec 配置,这样能够兼顾速度与安全,最多损失1s的数据。

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

工做原理

关于原理部分,咱们主要来看RDB与AOF是如何完成持久化的,他们的过程是如何。

在介绍原理以前先说下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的持久化的。

image1

这里注意的是 fork 操做会阻塞,致使Redis读写性能降低。咱们能够控制单个Redis实例的最大内存,来尽量下降Redis在fork时的事件消耗。以及上面提到的自动触发的频率减小fork次数,或者使用手动触发,根据本身的机制来完成持久化。

AOF的原理

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

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

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

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

下面来看看重写的一个流程图:

image2

对于上图有四个关键点补充一下:

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

不能是RDB仍是AOF都是先写入一个临时文件,而后经过 rename 完成文件的替换工做。

从持久化中恢复数据

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

其实想要从这些文件中恢复数据,只须要从新启动Redis便可。咱们仍是经过图来了解这个流程:

image2

启动时会先检查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持久化能够同时存在,配合使用。

本文的内容主要是运维上的一些注意点,但咱们开发者了解到这些知识,在某些时候有助于咱们发现诡异的bug。接下来会介绍Redis的主从复制与集群的知识。

公众号:dayuTalk

公众号
相关文章
相关标签/搜索