Redis?持久化技术
RDB
是默认持久化方式,但
Redis
允许
RDB
与
AOF
两种持久化技术同时
开启,此时系统会使用
AOF
方式做持久化,即
AOF
持久化技术的优先级要更高。同样的道
理,两种技术同时开启状态下,系统启动时若两种持久化文件同时存在,则优先加载
AOF
持久化文件。
RDB 持久化
RDB
,
Redis DataBase
,是指将内存中某一时刻的数据快照
全量
写入到指定的
rdb
文件的
持久化技术。
RDB
持久化默认是开启的。当
Redis
启动时会自动读取
RDB
快照文件,将数据 从硬盘载入到内存,以恢复 Redis
关机前的数据库状态。
RDB
持久化的执行有三种方式:手动
save
命令、手动
bgsave
命令,与自动条件触发。
手动
save 命令,手动
bgsave
命令
通过在
redis-cli
客户端中执行
save
命令可立即进行一次持久化保存。
save
命令在执行期
间会阻塞
redis-server
进程,直至持久化过程完毕。而在
redis-server
进程阻塞期间,
Redis
不能处理任何读写请求,无法对外提供服务。
通过在
redis-cli
客户端中执行
bgsave
命令可立即进行一次持久化保存。不同于
save
命
令的是,正如该命令的名称一样,
background save
,后台运行
save
。
bgsave
命令会使服务器
进程
redis-server
生成一个子进程,由该子进程负责完成保存过程。在子进程进行保存过程
中,不会阻塞
redis-server
进程对客户端读写请求的处理。
自动条件触发
自动条件触发的本质仍是
bgsave
命令的执行。只不过是用户通过在配置文件中做相应
的设置后,
Redis
会根据设置信息自动调用
bgsave
命令执行。
在进行持久化过程中,如果 redis-server 进程接收到了用户写请求,则系统会将?
内存中发生数据修改的物理块
copy
出一个副本。等内存中的全量数据
copy
结束后,会再将
副本中的数据
copy
到
RDB
临时文件。这个副本的生成是由于
Linux
系统的
写时复制技术
(
Copy-On-Write
)实现的
写时复制技术是
Linux
系统的一种进程管理技术。
原本在
Unix
系统中,当一个主进程通过
fork()
系统调用创建子进程后,内核进程会复制主进
程的整个内存空间中的数据,然后分配给子进程。这种方式存在的问题有以下几点:
?
这个过程非常耗时
?
这个过程降低了系统性能
?
如果主进程修改了其内存数据,子进程副本中的数据是没有修改的。即出现了数据冗余,
而冗余数据最大的问题是数据一致性无法保证。
现代的
Linux
则采用了更为有效的方式:写时复制。子进程会继承父进程的所有资源,其中
就包括主进程的内存空间。即子进程与父进程共享内存。只要内存被共享,那么该内存就是
只读的(写保护的)。而写时复制则是在任何一方需要写入数据到共享内存时都会出现异常,
此时内核进程就会将需要写入的数据
copy
出一个副本写入到另外一块非共享内存区域。
?
?
AOF 持久化
AOF
,
Append Only File
,是指
Redis
将每一次的写操作都以日志的形式记录到一个
AOF
文件中的持久化技术。当需要恢复内存数据时,将这些写操作重新执行一次,便会恢复到之
前的内存数据状态。
默认情况下
AOF
持久化是没有开启的,通过修改配置文件中的
appendonly
属性为
yes
可以开启。
Redis 7
发生了重大变化。原来只有一个
appendonly.aof
文件,现在具有了三类多个
文件:
?
基本文件:可以是
RDF
格式也可以是
AOF
格式。其存放的内容是由
RDB
转为
AOF
当
时内存的快照数据。该文件可以有多个。
?
增量文件:以操作日志形式记录转为
AOF
后的写入操作。该文件可以有多个。
?
清单文件:用于维护
AOF
文件的创建顺序,保障激活时的应用顺序。该文件只有一个。
混合式持久化开启
对于基本文件可以是
RDF
格式也可以是
AOF
格式。通过
aof-use-rdb-preamble
属性可以
选择。其默认值为
yes
,即默认
AOF
持久化的基本文件为
rdb
格式文件,也就是默认采用混
合式持久化。
AOF
文件格式
AOF
文件包含三类文件:基本文件、增量文件与清单文件。其中基本文件一般为
rdb
格
式,在前面已经研究过了。下面就来看一下增量文件与清单文件的内容格式。
增量文件扩展名为
.aof
,采用
AOF
格式。
AOF
格式其实就是
Redis
通讯协议格式,
AOF
持久化文件的本质就是基于
Redis
通讯协议的文本,将命令以纯文本的方式写入到文件中。
清单文件
appendonly.aof.manifest
该文件首先会按照
seq
序号列举出所有基本文件,基本文件
type
类型为
b
,然后再按照
seq
序号再列举出所有增量文件,增量文件
type
类型为
i
。
对于
Redis
启动时的数据恢复,也会按照该文件由上到下依次加载它们中的数据。
rewrite
随着使用时间的推移,
AOF
文件会越来越大。为了防止
AOF
文件由于太大而占用大量
的磁盘空间,降低性能,
Redis
引入了
Rewrite
机制来对
AOF
文件进行压缩。
所谓
Rewrite
其实就是对
AOF
文件进行重写整理。当
Rewrite
开启后,主进程
redis-server
创建出一个子进程
bgrewriteaof
,由该子进程完成
rewrite
过程。其首先对现有
aof
文件进行
rewrite
计算,将计算结果写入到一个临时文件,写入完毕后,再
rename
该临时文件为原
aof
文件名,覆盖原有文件。
Rewrite
过程的执行有两种方式。一种是通过
bgrewriteaof
命令手动开启,一种是通过
设置条件自动开启。
appendfsync
当客户端提交写操作命令后,该命令就会写入到
aof_buf
中,而
aof_buf
中的数据持久
化到磁盘
AOF
文件的过程称为数据同步。
何时将
aof_buf
中的数据同步到
AOF
文件?采用不同的数据同步策略,同时的时机是不
同的,有三种策略:
?
always
:写操作命令写入
aof_buf
后会立即调用
fsync()
系统函数,将其追加到
AOF
文件。
该策略效率较低,但相对比较安全,不会丢失太多数据。最多就是刚刚执行过的写操作
在尚未同步时出现宕机或重启,将这一操作丢失。
?
no
:写操作命令写入
aof_buf
后什么也不做,不会调用
fsync()
函数。而将
aof_buf
中的
数据同步磁盘的操作由操作系统负责。
Linux
系统默认同步周期为
30
秒。效率较高。
?
everysec
:默认策略。写操作命令写入
aof_buf
后并不直接调用
fsync()
,而是每秒调用
一次
fsync()
系统函数来完成同步。该策略兼顾到了性能与安全,是一种折中方案。
?
aof-rewrite-incremental-fsync
当
bgrewriteaof
在执行过程也是先将
rewrite
计算的结果写入到了
aof_rewrite_buf
缓存
中,然后当缓存中数据达到一定量后就会调用
fsync()
进行刷盘操作,即数据同步,将数据写
入到临时文件。该属性用于控制
fsync()
每次刷盘的数据量最大不超过
4MB
。这样可以避免由
于单次刷盘量过大而引发长时间阻塞。