本文为redis学习笔记的第五篇文章。redis处理数据都是在内存中进行,所以速度特别快,同样,它也可以支持持久化,这里注意,并不是说redis要来充当mysql那种角色,其实更多的是为了在崩溃的时候快速恢复以及主从复制这样的功能。redis的持久化主要有两种方式,一种是RDB,一种是AOF,对于他们的原理和区别都是比较重要的面试考察点,需要掌握。

1. 什么是持久化

redis所有数据保持在内存中,对数据的更新将异步地保存到磁盘中。

2. 持久化的方式

快照—mysql dump或者redis rdb

写日志—mysql binlog或者hbase glog或者redis aof

3. RDB

什么是RDB

image

触发机制三种主要方式

  • save(同步持久化,会造成redis主线程的阻塞,不推荐使用)

save是同步的,当保存的数据量很大时,可能造成redis的阻塞,即客户端访问redis被阻塞。

image

他的文件策略是:如果存在老的RDB文件,则新的替换老的。复杂度为O(n)

  • bgsave(异步,fork一个子进程来进行持久化,不会造成主线程的阻塞)

一般情况下,fork是比较快的,但是也可以会慢,这时会阻塞redis。只要fork不慢,客户端不会被阻塞。

image

他的文件策略和复杂度与save是一样的。

savebgsave两者对比:

image

  • 自动

redis的自动保存的默认配置是:

配置 seconds changes
save 900 1
save 300 10
save 60 10000

就是说,在60秒内改变了10000条数据,就自动保存;在300秒内有10条改变才自动保存;900秒内有1一条改变就保存。

RDB总结

  1. RDBRedis内存到硬盘的快照,用于持久化。
  2. save通常会阻塞redis
  3. bgsave不会阻塞redis,但是会fork新进程。
  4. save自动配置满足任一就会被执行。
  5. 有些触发机制不容忽视。

4. AOF

RDB问题

  • 全量数据存入磁盘

O(n)数据的备份,很耗时间;对于bgsave来说,fork()是一个很消耗内存的操作;将数据全写到硬盘,必然对硬盘IO占用很大。

  • 宕机丢失数据多

还有一点是:某个时间点宕机,那么在某个时间段的数据就丢失了

AOF原理

将对redis的操作追加到aof文件中。当redis宕机之后,使用aof恢复所有的操作继而实现数据的恢复。

AOF三种策略

  • always

image

  • everysec

image

redis出现故障,有可能丢失一秒的数据。redis默认方式。

  • no

三种策略的比较

image

AOF重写

image

好处是:减少硬盘占用、减少数据丢失

下面是AOF的bgrewirteaof的过程:

image

注意:这里的重写并不是上面演示的,将原来的aof文件进行重写,而是根据redis现在的内存数据进行一次回溯。

aof重写流程

image

也就是说,子进程在执行 AOF 重写时,主进程需要执行以下三个工作:

  • 1.处理命令请求;
  • 2.将写命令追加到现有的 AOF 文件中;
  • 3.将写命令追加到 AOF 重写缓存中。

如此可以保证:

  • 现有的AOF功能继续执行,即使 AOF 重写期间发生停机,也不会有任何数据丢失;
  • 所有对数据库进行修改的命令都会被记录到 AOF 重写缓存中。

当子进程完成对 AOF 文件重写之后,它会向父进程发送一个完成信号,父进程接到该完成信号之后,会调用一个信号处理函数,该函数完成以下工作:(阻塞)

  • 将 AOF 重写缓存中的内容全部写入到新的 AOF 文件中;(现有 AOF 文件、新的 AOF 文件和数据库三者的状态就完全一致了)
  • 对新的 AOF 文件进行改名,覆盖原有的 AOF 文件。(执行完毕后,程序就完成了新旧两个 AOF 文件的替换)

当这个信号处理函数执行完毕之后,主进程就可以继续像往常一样接收命令请求了。在整个 AOF 后台重写过程中,只有最后的“主进程写入命令到AOF缓存”和“对新的 AOF 文件进行改名,覆盖原有的 AOF 文件”这两个步骤会造成主进程阻塞,在其他时候, AOF 后台重写都不会对主进程造成阻塞,这将 AOF 重写对性能造成的影响降到最低。

小结:

  • AOF 重写的目的是轻量地保存数据库状态,整个重写过程基本上不影响 Redis 主进程处理命令请求;
  • AOF在redis宕机的时候最多丢失一秒的数据,比RDB要好一点,并且可读性高,基本上能看得懂
  • AOF 重写其实是一个有歧义的名字,实际上重写工作是针对数据库的当前值来进行的,重写过程中不会读写、也不适用原来的 AOF 文件;
  • AOF 可以由用户手动触发,也可以由服务器自动触发。

5. 持久化的取舍和选择

RDB和AOF对比

image

可以看出,世界上没有完美的东西,只有合适的东西。AOF同样存在一些问题:AOF文件的体积通常要大于RDB文件的体积、且恢复速度慢。

RDB最佳策略

“关”:建议关闭,但是后面主从复制功能是需要他的,因为需要主节点执行dbsave,然后将rdb文件传给从节点。所以说,关不是永久关。

“集中管理”:虽然RDB很重,但是对于数据备份是很重要的,按照小时或者天集中地进行备份比较好,因为他的文件很小,利于传输。

“主从,从开”:有时候从节点打开这个功能是比较好的,但是备份太频繁,取决于实际的场景。

AOF最佳策略

  • “开”:建议打开,如果仅仅是作为一个普通缓存,对于数据要求不是很高,这次数据丢了,下次可以从数据库取(数据库压力不是很大),这种情况就建议关闭,因为AOF还是有性能开销的。
  • “everysec”

Redis4

Redis 4.0 新增了 RDB-AOF 混合持久化格式, 这是一个可选的功能,

在开启了这个功能之后, AOF 重写产生的文件将同时包含 RDB 格式的内容和 AOF 格式的内容, 其中 RDB 格式的内容用于记录已有的数据, 而 AOF 格式的内存则用于记录最近发生了变化的数据, 这样 Redis 就可以同时兼有 RDB 持久化和 AOF 持久化的优点 —— 既能够快速地生成重写文件, 也能够在出现问题时, 快速地载入数据。

RDB和AOF共存的情况下如何恢复数据:

image

  • 优点:
    • 混合持久化结合了RDB持久化 和 AOF 持久化的优点,
    • 由于绝大部分都是RDB格式,加载速度快,同时结合AOF,增量的数据以AOF方式保存了,数据更少的丢失。
  • 缺点:
    • 兼容性差,一旦开启了混合持久化,在4.0之前版本都不识别该aof文件,同时由于前部分是RDB格式,阅读性较差

策略是:

6. 总结