Redis持久化

前言

Redis 提供了多种不同级别的持久化方式:RDB和AOF

RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)。

AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。

Redis 还可以同时使用 AOF 持久化和 RDB 持久化。 在这种情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。

一、RDB

RDB是默认开启的

1.1 RDB机制

RDB其实就是把数据以快照的形式保存在磁盘上。什么是快照呢,你可以理解成把当前时刻的数据拍成一张照片保存下来。

RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式,这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。

在我们安装了redis之后,所有的配置都是在redis.conf文件中,里面保存了RDB和AOF两种持久化机制的各种配置。

既然RDB机制是通过把某个时刻的所有数据生成一个快照来保存,那么就应该有一种触发机制,是实现这个过程。对于RDB来说,提供了三种机制:save、bgsave、自动化。我们分别来看一下

save触发方式

该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。具体流程如下
在这里插入图片描述
执行完成时候如果存在老的RDB文件,就把新的替代掉旧的。我们的客户端可能都是几万或者是几十万,这种方式显然不可取。

bgsave触发方式

执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体流程如下
在这里插入图片描述
bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。 bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。此时,如果主线程对这些 数据也都是读操作,那么,主线程和 bgsave 子进程相互不影响。但是,如果主线程要修改一块数据,那 么,这块数据就会被复制一份,生成该数据的副本。然后,bgsave 子进程会把这个副本数据写入 RDB 文 件,而在这个过程中,主线程仍然可以直接修改原来的数据

自动触发

自动触发是由我们的配置文件来完成的。在redis.conf配置文件中,里面有如下配置,我们可以去设置:

################################ SNAPSHOTTING  ################################

#在下面的示例中,行为将是保存:
#900秒(15分钟)内,如果有一把key改变,就执行持久化
#300秒(5分钟)后,如果更改了10个key,就执行持久化
#60秒后,如果至少10000个密key发生更改,就执行持久化

save 900 1
save 300 10
save 60 10000

#当启用了RDB且最后一次后台保存数据失败,Redis会拒绝新的写入。这会让用户意识到数据没有正确持久化到磁盘上,否则没有人会注意到灾(disaster)#发生了。如果Redis重启了,那么又可以重新开始接收数据了
stop-writes-on-bgsave-error yes

#默认值是yes。对于存储到磁盘中的快照,可以设置是否进行压缩存储。
rdbcompression yes

#默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来校验数据的完整性,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。
rdbchecksum yes

#RDB存储数据库的文件名
dbfilename dump.rdb

#工作目录。
dir ./ 

配置自动生成rdb文件后台使用的是bgsave方式

1.2 RDB执行流程

在这里插入图片描述

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

(2) 父进程执行fork操作创建子进程,这个过程中父进程是阻塞的,Redis不能执行来自客户端的任何命令

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

(4) 子进程创建RDB文件,根据父进程内存快照生成临时快照文件,完成后对原有文件进行原子替换

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

1.3 RDB的恢复

(1) 先停掉redis服务

(2) 将dump.rdb文件恢复到redis的数据目录中

(3) 将redis的rdb文件恢复成dump.rdb

(4) 启动redis服务

1.4 RDB的优缺点

RDB 的优点

RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复。

生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。

RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

RDB 的缺点

RDB快照是一次全量备份,存储的是内存数据的二进制序列化形式,存储上非常紧凑。当进行快照持久化时,会开启一个子进程专门负责快照持久化,子进程会拥有父进程的内存数据,父进程修改内存子进程不会反应出来,所以在快照持久化期间修改的数据不会被保存,可能丢失数据。

二、AOF

AOF和RDB同时开启,redis优先会取AOF存储数据
AOF的恢复步骤和RDB一样

2.1 AOF执行过程

AOF是以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作

其执行过程如下:

(1)客户端的请求写命令会被append追加到AOF缓冲区内;
(2)AOF缓冲区根据AOF持久化策略【always,everysec,no】将操作sync同步到磁盘的AOF文件中;
(3)AOF文件大小超过重写策略或手动重写时,会对AOF文件rewrite重写,压缩AOF文件容量;
(4) Redis服务重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的;

2.2 AOF配置
############################## APPEND ONLY MODE ###############################


#AOF开关 默认on关闭,这里我们改成yes
appendonly yes 

#AOF存储数据文件名字,其位置和dump.rdb位置一样
appendfilename "appendonly.aof"

#AOF的fsync策略有三种可以选择:

#每次写入一条数据就执行一次fsync;
#每隔一秒执行一次fsync;
#一种是不主动执行fsync。
#always: 每次写入一条数据立即写日志fsync到磁盘上去,性能非常非常差,吞吐量很低; 
#everysec: 每秒 fsync 一次,足够快,并且在故障时只会丢失 1 秒钟的数据;
#no: 从不 fsync ,将数据交给操作系统来处理。更快,也更不安全的选择。

# appendfsync always
appendfsync everysec
# appendfsync no


#AOF重写是AOF持久化的一个机制,用来压缩AOF文件,通过fork一个子进程,重新写一个新的AOF文件,
#该次重写不是读取旧的AOF文件进行复制,而是读取内存中的Redis数据库,重写一份AOF文件,有点类似于RDB的快照方式

#yes,表示重写时,不写入AOF文件,只写入缓存,用户请求不会堵塞,但是如果重写期间宕机,就会丢失数据
#默认on,表示重写时,数据写入AOF文件,但用户请求会堵塞
no-appendfsync-on-rewrite no

#redis重写触发条件:要同时满足auto-aof-rewrite-percentage和auto-aof-rewrite-min-size

#redis重写触发条件:设置重写的基准值,AOF文件达到100%时进行重写(文件是原来的2倍)
auto-aof-rewrite-percentage 100
#redis重写触发条件:设置重写的基准值,AOF文件大于64M
auto-aof-rewrite-min-size 64mb



#指redis在恢复时,会忽略最后一条可能存在问题的指令。默认值yes。即在aof写入时,可能存在指令写错的问题(突然断电,写了一半),这种情况下,yes会log并继续,而no会直接恢复失败.
aof-load-truncated yes

#是否开启混合持久化,默认开启
aof-use-rdb-preamble yes

注意,AOF重写redis会fork出一个子进程去做(与bgsave命令类似),不会对redis正常命令处理有太多 影响

2.3 AOF的优缺点

AOF 的优点

使用 AOF 持久化会让 Redis 变得非常耐久(much more durable):你可以设置不同的 fsync 策略,比如无 fsync ,每秒钟一次 fsync ,或者每次执行写入命令时 fsync 。 AOF 的默认策略为每秒钟 fsync 一次,在这种配置下,Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据( fsync 会在后台线程执行,所以主线程可以继续努力地处理命令请求)。

AOF 文件是一个只进行追加操作的日志文件(append only log), 因此对 AOF 文件的写入不需要进行 seek , 即使日志因为某些原因而包含了未写入完整的命令(比如写入时磁盘已满,写入中途停机,等等), redis-check-aof 工具也可以轻易地修复这种问题。

Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。

AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。

AOF 的缺点

对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。

根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间

AOF 在过去曾经发生过这样的 bug : 因为个别命令的原因,导致 AOF 文件在重新载入时,无法将数据集恢复成保存时的原样。(举个例子,阻塞命令 brpoplpush 就曾经引起过这样的 bug 。) 测试套件里为这种情况添加了测试: 它们会自动生成随机的、复杂的数据集, 并通过重新载入这些数据来确保一切正常。 虽然这种 bug 在 AOF 文件中并不常见, 但是对比来说, RDB 几乎是不可能出现这种 bug 的

三、RDB 和 AOF ,我应该用哪一个?
命令RDBAOF
启动优先级
体积
恢复速度
数据安全性容易丢数据根据策略决定

生产环境可以都启用,redis启动时如果既有rdb文件又有aof文件则优先选择aof文件恢复数据,因为aof 一般来说数据更全一点。

Redis 4.0 混合持久化

重启 Redis 时,我们很少使用 RDB来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重 放,但是重放 AOF 日志性能相对 RDB来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很 长的时间。 Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。 通过如下配置可以开启混合持久化(必须先开启aof):

//是否开启混合持久化,默认开启
aof‐use‐rdb‐preamble yes

如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将 重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一 起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改 名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换。

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

混合持久化AOF文件结构如下
在这里插入图片描述

三、redis正常关闭与非正常关闭持久化

特殊情况:当redis最新改变了数据,但是时间又没有达到conf中设置的写入磁盘的时间,此时redis.server关闭了,最新修改的数据会丢失还是保存在磁盘中呢?

第一种:正常关闭

在客户端执行shutdown,数据会保存
注意:使用shutdown命令的前提是,如果conf文件中设置了密码,客户端启动需要带上密码,才可以使用shutdown

第二种:非正常关闭,如:kill -9直接杀死进程、断电等,数据会丢失

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值