世上最全redis 持久化机制 RDB 和AOF,让你一篇文章全面理解redis持久化

目录

前言:

为什么要做redis持久化:

redis持久化的机制:

RDB持久化

rdb快照的方式:

   配置:

AOP持久化

RDB和AOF性能比较

混合持久化:


前言

                项目中,我们在碰到需要执行耗时特别久,且结果不频繁变动的SQL,就特别适合将运行结果放入缓存。这样,后面的请求就去缓存中读取,使得请求能够迅速响应。或者在大并发的情况下,所有的请求直接访问数据库,数据库会出现连接异常。这个时候,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问数据库。

为什么要做redis持久化:

因为redis的数据是存放在内存中,如果发生了宕机,数据将会全部丢失。为了防止宕机时数据丢失,就需要对redis进行数据持久化。

redis持久化的机制:

redis持久化目前有两种方式:RDB、AOF

RDB持久化

        默认情况下,redis 将内存数据库以快照的方式保存在名字为 dump.rdb的二进制文件中。 

rdb快照的方式:

       手动触发:手动触发持久化的操作有两个: save 和 bgsave ,它们主要区别体现在:是否阻塞 Redis 主线程的执行。

       save:在客户端中执行 save 命令,就会触发 Redis 的持久化,但同时也是使 Redis 处于阻塞状态,直到 RDB 持久化完成,才会响应其他客户端发来的命令,所以在生产环境一定要慎用

save 命令使用如下:

如图所示:手动执行save后rdb文件重新生成。

save命令执行流程:

如图所示:手动执行save命令时,redis的线程属于阻塞状态,此时redis不接收任何操作,直到rdb文件生成完毕。 

       bgsave:在客户端中执行 bgsave 命令,就会触发 Redis 的持久化

127.0.0.1:6379> bgsave
Background saving started
127.0.0.1:6379> quit
[ysfdev@dev51111 upredis-2.2.0-centos7-x86_64]$ ls dump.rdb -l
-rw-r--r-- 1 ysfdev app 75 Mar  8 11:11 dump.rdb

1) 执行bgsave命令,Redis父进程首先判断:当前是否在执行save,或bgsave/bgrewriteaof(aof文件重写命令)的子进程,如果在执行则bgsave命令直接返回。bgsave/bgrewriteaof 的子进程不能同时执行,主要是基于性能方面的考虑:两个并发的子进程同时执行大量的磁盘写操作,可能引起严重的性能问题。

2)父进程执行fork操作创建子进程,fork操作过程中父进程会阻塞的,Redis不能执行来自客户端的任何命令;通过info stats命令查看lastest_fork_usee选项,可以获取最近一个fork操作的耗时,单位为微秒。

3)父进程fork完成后,bgsave命令返回”Background saving started”信息并不再阻塞父进程,并可以响应其他命令;

4)子进程创建RDB文件,根据父进程内存快照生成临时快照文件,完成后对原有文件进行原子替换;执行lastsave命令可以获取最后一次生成RDB的时间,对应info统计的rdb_last_save_time选项。

5)子进程发送信号给父进程表示完成,父进程更新统计信息。
 

        自动触发:

1、save n m        

   配置:

        打开redis.conf文件

################################ SNAPSHOTTING  ################################
#
# Save the DB on disk:
#
#   save <seconds> <changes>
#
#   Will save the DB if both the given number of seconds and the given
#   number of write operations against the DB occurred.
#
#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
#
#   Note: you can disable saving completely by commenting out all "save" lines.
#
#   It is also possible to remove all the previously configured save
#   points by adding a save directive with a single empty string argument
#   like in the following example:
#
#   save ""

save 900 1
save 300 10
save 60 10000

   对redis的rdb机制进行设置,若在n秒内,有m个key被改动就进行快照保存到rdb文件中。

redis的默认配置为:若900秒内有1个key被改动,300秒内有10个key被改动,60秒内有10000个key被改动就进行快照保存。当满足任意一个配置时都会调用bgsave.

2、flushall

flushall 命令用于清空 Redis 数据库,在生产环境下一定慎用,当 Redis 执行了 flushall 命令之后,则会触发自动持久化,把 RDB 文件清空。

3、主从同步触发

在 Redis 主从复制中,当从节点执行全量复制操作时,主节点会执行 bgsave 命令,并将 RDB 文件发送给从节点,该过程会自动触发 Redis 持久化。

                

AOF持久化

当然rdb快照也是存在问题的,如果redis宕机,近期发生变化的数据还未保存到快照中,这些数据依然会丢失。且rdb快照因为每次进行bgsave操作都要执行fork操作创建子进程,属于重量级操作,频繁执行成本过高,所以无法做到实时持久化,或者秒级持久化。另外,由于Redis版本的不断迭代,存在不同格式的RDB版本,有可能出现低版本的RDB格式无法兼容高版本RDB文件的问题。

AOF 持久化,将修改的每一条指令记录进文件 appendonly.aof 中. (先写入os cache,每隔一段时间fsync到磁盘)

AOF 也可配置redis 多久将数据 fsync 同步到磁盘一次。

redis.conf配置方式:

appendonly no  

默认为no,如果需要持久化,可以手动改为yes

AOF持久化并不会立即将命令写入到硬盘文件中,而是写入到硬盘缓存,在接下来的策略中,配置多久来从硬盘缓存写入到硬盘文件。所以在一定程度一定条件下,还是会有数据丢失,不过你可以大大减少数据损失

# appendfsync always            每次操作都会写到磁盘中,非常慢,非常安全
appendfsync everysec            每秒同步一次,会丢失一秒的数据,默认的配置
# appendfsync no                    从不同步,非常快,不安全

AOF机制文件重写原理

但是aof文件也有个问题,随着对redis的操作越来越多,aof文件也会越来越大。为了压缩aof的持久化文件。redis提供了bgrewriteaof命令。将内存中的数据以命令的方式保存到临时文件中,同时会fork出一条新进程来将文件重写。Redis服务器可以创建一个新的AOF文件来替代现有的AOF文件,新旧两个文件所保存的数据库状态是相同的,但是新的AOF文件不会包含任何浪费空间的冗余命令,通常体积会较旧AOF文件小很多。

  • Redis不希望AOF重写会造成服务器无法处理请求,所以Redis决定将AOF重写程序放到子进程(后台)里执行。这样处理的最大好处是: 
    • 子进程进行AOF重写期间,主进程可以继续处理命令请求;
    • 子进程带有主进程的数据副本,使用子进程而不是线程,可以避免在锁的情况下,保证数据的安全性。

使用子进程进行AOF重写的问题

  • 子进程在进行AOF重写期间,服务器进程还要继续处理命令请求,而新的命令可能对现有的数据进行修改,这会让当前数据库的数据和重写后的AOF文件中的数据不一致。

如何修正

  • 为了解决这种数据不一致的问题,Redis增加了一个AOF重写缓存,这个缓存在fork出子进程之后开始启用,Redis服务器主进程在执行完写命令之后,会同时将这个写命令追加到AOF缓冲区和AOF重写缓冲区
  • 即子进程在执行AOF重写时,主进程需要执行以下三个工作: 
    • 执行client发来的命令请求;
    • 将写命令追加到现有的AOF文件中;
    • 将写命令追加到AOF重写缓存中。

完成AOF重写之后

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

    • 将AOF重写缓存中的内容全部写入到新的AOF文件中;这个时候新的AOF文件所保存的数据库状态和服务器当前的数据库状态一致;
    • 对新的AOF文件进行改名,原子的覆盖原有的AOF文件;完成新旧两个AOF文件的替换。
  • 当这个信号处理函数执行完毕之后,主进程就可以继续像往常一样接收命令请求了。在整个AOF后台重写过程中,只有最后的“主进程写入命令到AOF缓存”和“对新的AOF文件进行改名,覆盖原有的AOF文件。”这两个步骤(信号处理函数执行期间)会造成主进程阻塞,在其他时候,AOF后台重写都不会对主进程造成阻塞,这将AOF重写对性能造成的影响降到最低。

以上,即AOF后台重写,也就是BGREWRITEAOF命令的工作原理。

触发AOF后台重写的条件

  • AOF重写可以由用户通过调用BGREWRITEAOF手动触发。
  • 服务器在AOF功能开启的情况下,会维持以下三个变量:

    • 记录当前AOF文件大小的变量aof_current_size
    • 记录最后一次AOF重写之后,AOF文件大小的变量aof_rewrite_base_size
    • 增长百分比变量aof_rewrite_perc
  • 每次当serverCron(服务器周期性操作函数)函数执行时,它会检查以下条件是否全部满足,如果全部满足的话,就触发自动的AOF重写操作:

    • 没有BGSAVE命令(RDB持久化)/AOF持久化在执行;
    • 没有BGREWRITEAOF在进行;
    • 当前AOF文件大小要大于server.aof_rewrite_min_size(默认为1MB),或者在redis.conf配置了auto-aof-rewrite-min-size大小;
    • 当前AOF文件大小和最后一次重写后的大小之间的比率等于或者等于指定的增长百分比(在配置文件设置了auto-aof-rewrite-percentage参数,不设置默认为100%)

如果前面三个条件都满足,并且当前AOF文件大小比最后一次AOF重写时的大小要大于指定的百分比,那么触发自动AOF重写。

RDB和AOF性能比较

机制

RDB

AOP

启动优先级

体积

恢复速度

数据安全性

容易丢数据

根据策略决定

混合持久化:

redis支持两种机制同时使用,用 AOF 来保证数据不丢失,作为数据恢复的第一选择;用 RDB 来做不同程度的冷备,在 AOF 文件都丢失或损坏不可用的时候,还可以使用 RDB 来进行快速的数据恢复。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值