redis 持久化AOF、RDB、混合持久化

为什么要持久化数据???

  1. Redis 的数据全部在内存里,如果突然宕机,数据就会全部丢失
  2. 即使只考虑缓存场景,如果未持久化,redis一旦服务宕机,内存中的数据将全部丢失。虽然可以从后端数据库恢复这些数据,但这种方式存在两个问题:一是,需要频繁访问数据库把缓存加载回来,会给数据库带来巨大的压力;二是,这些数据是从慢速数据库中读取出来的,性能肯定比不上从 Redis 中读取,导致使用这些数据的应用程序响应变慢。所以,对 Redis 来说,实现数据的持久化,避免从后端数据库中进行恢复,是至关重要的。

Redis 的持久化主要有两大机制,即 AOF 日志和 RDB 快照。
在这里插入图片描述
操作前准备redis环境,我是docker 启动的

docker run -p 6380:6380 --name redis -v /home/tools/redis/notpassword/redis.conf:/etc/redis/redis.conf -v /home/tools/redis/notpassword/data:/data -d redis:6.0 redis-server /etc/redis/redis.conf --appendonly yes
注释掉 protected-mode no 与 bin 127.0.0.1 否则无法远程链接

1、AOF日志

  • 原理
    AOF 日志存储的是 Redis 服务器的顺序指令序列,AOF 日志只记录对内存进行修改的指令记录,是先写内存,成功之后记录AOF日志

    为了避免额外的检查开销,Redis 在向 AOF 里面记录日志的时候,并不会先去对这些命令进行语法检查。所以,如果先记日志再执行命令的话,日志中就有可能记录了错误的命令,Redis 在使用日志恢复数据时,就可能会出错。在命令执行后才记录日志,所以不会阻塞当前的写操作

    Redis 在长期运行的过程中,AOF 的日志会越变越长,文件越来越大。如果实例宕机重启,加载 AOF 日志,重放整个 AOF 日志会非常耗时,导致长时间 Redis 无法对外提供服务,所以需要定期进行 AOF 重写,给 AOF 日志进行瘦身。

  • 开启aop 后日志文件解读
    执行命令 set name test 后查看appendonly.aof文件

    # *3 表示当前命令有三个部分,每部分都是由“$+数字”开头
    *3
    # $3表示这部分中的命令、键或值一共有多少字节。
    $3
    set
    # $4表示这部分中的命令、键或值一共有多少字节。
    $4
    name
    # $4表示这部分中的命令、键或值一共有多少字节。
    $4
    test
    

1.1、三种写回策略

AOF 机制提供了三个选择,也就是 AOF 配置项appendfsync 的三个可选值。
在这里插入图片描述

  • always:同步写回:每个写命令执行完,立马同步地将日志写回磁盘;

    • 可以做到基本不丢数据,但是它在每一个写命令后都有一个慢速的落盘操作,不可避免地会影响主线程性能(生产环境基本不会使用,严重影响性能);
  • everysec:每秒写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘;

    • 采用一秒写回一次的频率,避免了“同步写回”的性能开销,虽然减少了对系统性能的影响,但是如果发生宕机,上一秒内未落盘的命令操作仍然会丢失。所以,这只能算是,在避免影响主线程性能和避免数据丢失两者间取了个折中。
  • no:操作系统控制的写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。

    • 写完缓冲区后,就可以继续执行后续的命令,但是落盘的时机已经不在 Redis 手中了,只要 AOF 记录没有写回磁盘,一旦宕机对应的数据就丢失了;

在这里插入图片描述
一般来讲生产环境都是everysec

1.2、AOF 重写机制

Redis 提供了 bgrewriteaof 指令用于对 AOF 日志进行瘦身。其原理就是开辟一个子进程对内存进行遍历转换成一系列 Redis 的操作指令,序列化到一个新的 AOF 日志文件中。 序列化完毕后再将操作期间发生的增量 AOF 日志追加到这个新的 AOF 日志文件中,追加完毕后就立即替代旧的 AOF 日志文件了,瘦身工作就完成了。

实际上,重写机制具有“多变一”功能。所谓的“多变一”,也就是说,旧日志文件中的多条命令,在重写后的新日志中变成了一条命令。
在这里插入图片描述
如图中,这一条命令就能实现该数据的恢复,这就节省了五条命令的空间。对于被修改过成百上千次的键值对来说,重写能节省的空间当然就更大了。

重写机制和 AOF 日志由主线程写回不同,重写过程是由后台线程 bgrewriteaof 来完成的,这也是为了避免阻塞主线程,导致数据库性能下降。

每次执行重写时,主线程 fork 出后台的 bgrewriteaof 子进程。此时,fork 会把主线程的内存拷贝一份给 bgrewriteaof 子进程,这里面就包含了数据库的最新数据。然后,bgrewriteaof 子进程就可以在不影响主线程的情况下,逐一把拷贝的数据写成操作,记入重写日志

因为主线程未阻塞,仍然可以处理新来的操作。此时,如果有写操作,Redis 会把这个操作写到它的缓冲区。这样一来,即使宕机了,这个 AOF 日志的操作仍然是齐全的,可以用于恢复。

这个操作也会被写到重写日志的缓冲区。这样,重写日志也不会丢失最新的操作。等到拷贝数据的所有操作记录重写完成后,重写日志记录的这些最新操作也会写入新的 AOF 文件,以保证数据库最新状态的记录。此时,我们就可以用新的 AOF 文件替代旧文件了。
在这里插入图片描述
redis客户端操作
在这里插入图片描述
可以重新打开appendonly.aof,所有命令都合为一条

如下两个配置可以控制AOF自动重写频率

# aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就 很快,重写的意义不大
#auto‐aof‐rewrite‐min‐size 64mb
# aof文件自上一次重写后文件大小增长了100%则再次触发重写
#auto‐aof‐rewrite‐percentage 100

2、RDB快照

所谓内存快照,就是指内存中的数据在某一个时刻的状态记录。这就类似于照片,当你给朋友拍照时,一张照片就能把朋友一瞬间的形象完全记下来。

对 Redis 来说,它实现类似照片记录效果的方式,就是把某一时刻的状态以文件的形式写到磁盘上,也就是快照。这样一来,即使宕机,快照文件也不会丢失,数据的可靠性也就得到了保证。这个快照文件就称为 RDB 文件,其中,RDB 就是 Redis DataBase 的缩写。

和 AOF 相比,RDB 记录的是某一时刻的数据,并不是操作,快照是一次全量备份,是内存数据的二进制序列化形式,在存储上非常紧凑,节省空间大小。

对于 Redis 而言,它的单线程模型就决定了,我们要尽量避免所有会阻塞主线程的操作

Redis 提供了两个命令来生成 RDB 文件,分别是 save 和 bgsave

  • save:在主线程中执行,会导致阻塞;
  • bgsave:创建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞,Redis RDB 文件生成的默认配置。

在这里插入图片描述

bgsave可以避免阻塞,但是避免阻塞和正常处理写操作并不是一回事。bgsave时,主线程虽然没有阻塞,可以正常接收请求,但是,为了保证快照完整性,它只能处理读操作,因为不能修改正在执行快照的数据。此时 Redis 就会借助操作系统提供的写时复制技术(Copy-On-Write, COW),在执行快照的同时,正常处理写操作。

每次命令执行都会将所有redis内存快照到一个新的rdb文件里,并覆盖原有rdb快照文件。

简单来说,bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。此时,如果主线程对这些数据也都是读操作(例如图中的键值对 A),那么,主线程和bgsave 子进程相互不影响。但是,如果主线程要修改一块数据(例如图中的键值对 C),那么,这块数据就会被复制一份,生成该数据的副本。然后,bgsave 子进程会把这个副本数据写入 RDB 文件,而在这个过程中,主线程仍然可以直接修改原来的数据。

在这里插入图片描述

这既保证了快照的完整性,也允许主线程同时对数据进行修改,避免了对正常业务的影响。

3、混合持久化

Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。将 rdb 文件的内容和增量的 AOF 日志文件存在一起。这里的 AOF 日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小。

内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。这样一来,快照不用很频繁地执行,这就避免了频繁 fork 对主线程的影响。而且,AOF日志也只用记录两次快照间的操作,也就是说,不需要记录所有操作了,因此,就不会出现文件过大的情况了,也可以避免重写开销。

在 Redis 重启的时候,可以先加载 rdb 的内容,然后再重放增量 AOF 日志就可 以完全替代之前的 AOF 全量文件重放,重启效率因此大幅得到提升。

3.1 混合持久化配置

在这里插入图片描述

设置aof-use-rdb-preamble yes后Redis服务器在执行 AOF重写操作时,就会像执行BGSAVE命令那样,根据数据库当前的状态生成出相应的RDB数据,并将这些数据写入新建的AOF文件中,至于那些在AOF重写开始之后执行的Redis命令,则会继续以协议文本的方式追加到 新AOF文件的末尾,即已有的RDB数据的后面

在开启了RDB-AOF混合持久化功能之后,服务器生成的AOF文件将由两个部分组成,其中位于AOF文件开头的是RDB格式的数据,而跟在RDB数据后面的则是AOF格式的数据

当一个支持RDB-AOF混合持久化模式的Redis服务器启动并载入AOF文件时,它会检查AOF文件的开头是否包含了RDB格式的内容

如果包含,那么服务器就会先载入开头的RDB数据,然后再载入之后的AOF数据
如果AOF文件只包含AOF数据,那么服务器将直接载入AOF数据

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值