redis之持久化机制

一、前言

最近有幸学一下后台,因为redis搞得后台同学非常头疼,顾学一下redis看看是不是真的难,确实挺难的,单这个持久化机制就研究了很久,所以记录一下。

二、持久化机制1——RDB文件快照

1、什么是RDB?

其实就是在一段时间内生成redis的一个快照文件,并且写入磁盘(这样下次启动就直接把这份快照数据读入redis内存即可)

2、如何配置?

我们可以打开redis.conf文件(估计是在根目录或者conf目录下,我用的是windows,所以直接是在根目录中找到redis.window.conf,如下图2-1所示。linux系统的redis配置文件叫redis.conf)

                                                                图2-1

打开redis.window.conf(或者redis.conf),我们可以搜索图2-2的代码,看到对应的注释,大概意思就是可以通过save [seconds] [changes]来配置RDB快照触发的时间,意思就是在seconds秒内,

如果存储的redis的key的值发生了变化或者多了或少了某个key(增删改),就会触发生成RDB快照了

                                                                        图2-2

当然,也可以直接在服务端执行bgsave命令直接生成快照,一般比较少用到

3、RDB的执行流程和原理

这里节省时间,直接引用别人的图了,如图3-1所示。 

                                                         图3-1

  1. 在进行RDB快照生成的过程中,首先主进程看一下有没有执行bgsave/bgrewriteaof/save这些命令(C语言来的),如果有就直接返回,不往下执行第二步
  2. 然后主进程会fork子进程出来(这里会导致主进程阻塞,此时不能处理客户端连接的事件),等到fork完成后,bgsave命令会返回成功信息,然后主进程不再阻塞
  3. 子进程马上创建一个RDB文件(为什么要先创建一个文件呢?卖个关子,等下讲),然后把fork下来的内存写到RDB文件中(都是二进制来的,这样的文件占用空间比较小,方便传输),记录完成后替换掉原来的RDB文件(如果原RDB文件存在的话)
  4. 子进程发送成功信息告诉主进程,主进程更新统计信息(估计记录RDB更新次数和时间)

这里要注意的是,如果主进程比较大的时候,第二个步骤容易阻塞,也是影响RDB这种机制性能的点。

那么有人会问,为什么第三步需要先创建RDB文件呢?主要是,马上创建一个文件到硬盘,这样如果突然遇到断电也不慌(试想一下,如果不先建立文件,而是先把数据写入缓冲区,待到缓冲区满了再写入文件,那么第一次写入就可能因为断电等原因,导致文件没生成,然后就没记录下缓冲区的数据了。我们的宗旨是应该尽量记录下更多的redis的快照数据才对。)

4.RDB快照文件结构

这个内容不是很重要,我大概只记得,RDB文件前五个字节固定是REDIS。然后就是如下图4-1所示了。存储的形式都是二进制格式的。所以文件相对比较少,主从复制时会比较快。

                                                                         图4-1

5.RDB优缺点

优点:

  • RDB文件是二进制文件,占用空间小,便于传输(主从复制就很快了)
  • 主进程主要在fork子进程的时候阻塞,之后都不会影响到主进程工作。(但是要注意,主进程不能太大,不然就会阻塞时间久,处理不了客户端请求了)

缺点:

  • 不能最大程度保持redis数据完整性。(举个例子,比如设置了900秒30个key变化,才触发RDB快照,那么如果在450秒内,有30key已经发生变化了,它都不会触发快照发生,得等到900秒,那这个时候如果后450秒突然宕机,那么这次的快照就保存不了了。也就是说,RDB只能保存最后一次快照的数据,有些人还是不满足于这样的性能)

三、持久化机制2——AOF

1、AOF是什么?

AOF全称append only file,就是把redis执行过的所有命令和参数都记录在一个文件内,如果redis宕机重启后,就会执行该文件的所有写命令,这样就可以保持redis的持久化了。

2、AOF配置

可以在redis.conf(redis.window.conf)中,找到图3-2-1的代码:

                                                                        图3-2-1

3、AOF的执行流程和原理

首先直接扔一张流程图:,比较复杂,不要紧。这里涉及三个进程,一个主进程和两个子进程。 

先说下主进程:

  • 当主进程接受到客户端的请求时,根据一些协议什么的,转为redis的一些命令函数然后执行读写命令。读写完毕后,就把这个redis格式的读写命令参数就会传入到AOF程序当中(可以理解为一个函数)
  • 接着AOF函数会对命令参数进行解析和处理,最后赋值给redis.h/redisServer 结构的 aof_buf 末尾(c语言)
  • 每当服务器常规任务函数被执行或者事件处理器被执行时(不理解这句话的话,就当作是某个时机触发吧,因为这里主要是讲单进程版本的redis,因为是单进程,所以有个时机才会触发下面的write和save函数操作), aof.c/flushAppendOnlyFile 函数都会被调用, 这个函数执行以下两个工作:
  1. WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件。
  2. SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中(最终写入磁盘才算是持久化完成)

AOF文件的保存模式(执行上面流程的时机)有以下三种:

  1. AOF_FSYNC_NO :不保存。(相当于完全不使用AOF机制)
  2. AOF_FSYNC_EVERYSEC :每一秒钟保存一次。(默认)(最后save操作主进程不会阻塞,因为是fork出子进程执行的,而这个子进程对应的就是图3-2-2所示红色圈住部分的子进程)
  3. AOF_FSYNC_ALWAYS :每执行一个命令保存一次。(不推荐)(最后save操作主进程会阻塞)

 

以上是主进程的执行过程,接下来讲一下图3-2-1的最后一个子进程的作用。

AOF的重写

AOF重写不是真正的重写,而是在一段时间内,redis对AOF文件进行瘦身。

举个例子,如下图3-3-3所示,redis对同一个key执行了3次set操作,所以最终s1的值为33,而前两次的set操作其实不需要记录在AOF文件中的,于是,就有了一个子进程进行对AOF文件的瘦身的操作。

                                                                 图3-3-3

AOF重写时使用的是fork的子进程的好处:

  • 不影响主进程的工作
  • 子进程处于数据安全环境下(因为不是线程,所以和主进程不共享空间和资源)

但是子进程要处理的问题是,当AOF文件重写的时候,主进程会在处理新的客户端请求(可能会有新的读写操作),这些新的读写操作怎么写入新的AOF文件当中呢?步骤如下:

  1. 主进程处理客户端的请求
  2. 主进程把客户端的请求进行命令播放,追加到现有的AOF文件中(1,2步骤上面都说过的了,主进程的基本操作)
  3. 主进程把新的命令追加到一个新的AOF缓存(内存)中(这个是主进程的一个新的步骤)
  4. fork出来的子进程,保存了主进程原有的AOF文件,于是子进程读AOF文件并写入新的AOF文件中
  5. 子进程写完后,告诉主进程我写完读写完原来的AOF文件了,然后子进程再去读第三步的AOF缓存,把新增的命令也写入新的AOF文件中
  6. 然后子进程告诉主进程,我已经写完了,然后就把新的AOF文件替换掉旧的AOF文件
     

所以AOF的重写不会导致主进程的阻塞

那么,AOF重写机制如何配置呢?我们可以找到redis.conf(redis.window.conf)文件,然后看到下面这两个配置参数:

# 表示当前aof文件大小超过上一次aof文件大小的百分之多少的时候会进行重写。如果之前没有重写过,以
启动时aof文件大小为准
auto-aof-rewrite-percentage 100
# 限制允许重写最小aof文件大小,也就是文件大小小于64mb的时候,不需要进行优化
auto-aof-rewrite-min-size 64mb

 当然,执行bgrewriteaof命令也可以触发重写机制(一般比较少用到)

四、混合持久化

因为RDB和AOF各有优缺点,所以也可以将两者混合使用,只需要在redis.conf(redis.window.conf)文件中配置如下代码段即可。

aof-use-rdb-preamble yes

开启混合持久化机制后,RDB文件的内容会写道AOF文件的头部,如下图所示

五、持久化的过程

 当真的遇到redis宕机重启时,重启会优先加载AOF文件:

  1. 首先创建一个伪客户端,该客户端没有网路功能
  2. 然后开始读取解析AOF文件,执行里面的命令

如果没有配置AOF机制,就会使用读取RDB文件

六、RDB和AOF对比

RDBAOF
优点

1、除了根据主子程fork子进程这个步骤,其他都不会阻塞主线程处理客户端的请求

2、占用空间小,主从备份快

3、性能比AOF高

1、可以尽量保持数据完整性

2、设置每秒触发一次AOF文件机制,不会阻塞主进程

缺点1、不能最大程度保持数据完整性(只能保持最后一次快照)

1、性能比较慢

2、文件占用空间较大

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值