redis系列:RDB持久化与AOF持久化

前言

什么是持久化?redis

持久化(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、XML数据文件中等等。 持久化是将程序数据在持久状态和瞬时状态间转换的机制。 ----摘自百度百科数据库

Redis的数据都是存储在内存中的,因此Redis持久化也就是要把Redis存储在内存中的数据保存到硬盘。
Redis提供了两种持久化方式缓存

  1. RDB持久化(快照)
  2. AOF持久化(只追加操做的文件 Append-only file)

先来看看RDB持久化bash

RDB持久化

RDB持久化是指在客户端输入savebgsave或者达到配置文件自动保存快照条件时,将Redis 在内存中的数据生成快照保存在名字为 dump.rdb(文件名可修改)的二进制文件中。服务器

save命令

save命令会阻塞Redis服务器进程,直到RDB文件建立完毕为止,在Redis服务器阻塞期间,服务器不能处理任何命令请求。 在客户端输入save网络

192.168.17.101:6379> save
OK
复制代码

服务端会出现下方字符app

1349:M 30 Jul 17:16:48.935 * DB saved on disk
复制代码

bgsave命令

bgsave命令的工做原理以下函数

  1. 服务器进程pid为1349派生出一个pid为1357的子进程,
  2. 子进程将数据写入到一个临时 RDB 文件中
  3. 当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。

在客户端输入bgsave性能

192.168.17.101:6379> bgsave
Background saving started
复制代码

服务端会出现下方字符ui

1349:M 30 Jul 17:14:42.991 * Background saving started by pid 1357
1357:C 30 Jul 17:14:42.993 * DB saved on disk
1357:C 30 Jul 17:14:42.993 * RDB: 4 MB of memory used by copy-on-write
1349:M 30 Jul 17:14:43.066 * Background saving terminated with success
复制代码

:bgsave命令执行期间 SAVE命令会被拒绝 不能同时执行两个BGSAVE命令 不能同时执行BGREWRITEAOF和BGSAVE命令

自动保存

这个须要在配置文件redis.conf中修改,默认的保存策略以下

save 900 1    # 900 秒内有至少有 1 个键被改动
save 300 10   # 300 秒内有至少有 10 个键被改动
save 60 10000 # 60 秒内有至少有 1000 个键被改动
复制代码

接下来看看RBD的配置有哪些

配置

################################ SNAPSHOTTING ################################
# 触发自动保存快照
# save <seconds> <changes>
# save <秒> <修改的次数>
save 900 1    
save 300 10   
save 60 10000 

# 设置在保存快照出错时,是否中止redis命令的写入
stop-writes-on-bgsave-error yes

# 是否在导出.rdb数据库文件的时候采用LZF压缩
rdbcompression yes

# 是否开启CRC64校验
rdbchecksum yes

# 导出数据库的文件名称
dbfilename dump.rdb

# 导出的数据库所在的目录
dir ./

复制代码

优势

  • RDB是一个很是紧凑(有压缩)的文件,它保存了某个时间点的数据,很是适用于数据的备份。
  • RDB做为一个很是紧凑(有压缩)的文件,能够很方便传送到另外一个远端数据中心 ,很是适用于灾难恢复.
  • RDB在保存RDB文件时父进程惟一须要作的就是fork出一个子进程,接下来的工做所有由子进程来作,父进程不须要再作其余IO操做,因此RDB持久化方式能够最大化redis的性能.
  • 与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.

翻译来自http://www.redis.cn

缺点

  • Redis意外宕机 时,会丢失部分数据
  • 当Redis数据量比较大时,fork的过程是很是耗时的,fork子进程时是会阻塞的,在这期间Redis 是不能响应客户端的请求的。

AOF持久化

AOF持久化是经过保存Redis服务器所执行的写命令来记录数据库状态,也就是每当 Redis 执行一个改变数据集的命令时(好比 SET), 这个命令就会被追加到 AOF 文件的末尾。

那么咱们如何开启AOF持久化功能呢?

开启AOF持久化

修改redis.conf配置文件,默认是appendonly no(关闭状态),将no改成yes便可

appendonly yes
复制代码

在客户端输入以下命令也可,可是Redis服务器重启后会失效

192.168.17.101:6379> config set appendonly yes
OK
复制代码

接下来看看AOF持久化功能的实现

实现

AOF持久化功能的实现能够分为命令追加(append)、文件写入和文件同步(sync)三个步骤。下面就是三个步骤的整个过程。

在Redis客户端输入以下命令

192.168.17.101:6379> set learnRedis testAOF
OK
复制代码

appendonly.aof文件会增长以下内容

*2
$6
SELECT
$1
0
*3
$3
set
$10
learnRedis
$7
testAOF

复制代码

命令追加

AOF持久化功能开启时,服务器在执行完一个写命令以后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾。此时缓冲区的记录尚未写入到appendonly.aof文件中。

文件的写入和同步

为何将文件写入和文件同步合在一块讲呢?由于配置文件中提供了一个appendfsync参数,这个参数控制着文件写入和同步的行为。

关于文件的写入和同步的资料以下

由于为了提升文件的写入效率,在现代操做系统中,当用户调用write函数,将一些数据写入到文件的时候,os一般会将写入数据暂时保存在一个内存缓冲区里面(例如,unix系统实如今内核中设有缓冲区高速缓存或页高速缓存,当咱们向文件写入数据时,内核一般先将数据复制到缓冲区中,而后排入队列,晚些时候再写入磁盘),这种方式称为延迟写,等到缓冲区的空间被填满,或者超过了指定的时限,或者内核须要重用缓冲区存放其它磁盘块数据时,才会真正将缓冲区中的全部数据写入到磁盘里面。

简单来讲就是

文件写入:只是写入到了内存缓冲区,可能尚未写到文件所拥有的磁盘数据块上
文件同步:将缓冲区中的内容冲洗到磁盘上

appendfsync参数

appendfsync选项的值 效果
always 每次有新命令时,就将缓冲区数据写入并同步到 AOF 文件
everysec(默认) 每秒将缓冲区的数据写入并同步到 AOF 文件
no 将缓冲区数据写入AOF 文件,可是同步操做到交给操做系统来处理

载入与数据还原

读取AOF文件并还原数据库的步骤以下

  1. 建立一个不带网络链接的伪客户端
  2. 从AOF文件中分析并读取出一条写命令
  3. 使用伪客户端执行被读出的写命令
  4. 一直执行步骤二、3,知道AOF文件中的全部写命令都被处理完毕为止

图片来自Redis设计与实现

这时可能会出现一个问题。服务器可能在程序正在对 AOF 文件进行写入时停机,形成了 AOF 文件出错,那么 Redis 在重启时会拒绝载入这个 AOF 文件,从而确保数据的一致性不会被破坏 当发生这种状况时, 能够用如下方法来修复出错的 AOF 文件:

  • 为现有的 AOF 文件建立一个备份。
  • 使用 Redis 附带的 redis-check-aof 程序,对原来的 AOF 文件进行修复: redis-check-aof –fix
  • (可选)使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不一样之处。
  • 重启 Redis 服务器,等待服务器载入修复后的 AOF 文件,并进行数据恢复。

另外redis.conf配置文件中还提供了一个参数来控制是否忽略最后一条可能存在问题的指令,以下

aof-load-truncated yes
复制代码

重写

因为AOF 持久化是经过不断地将命令追加到文件的末尾来记录数据库状态的, 因此随着写入命令的不断增长, AOF 文件的体积也会变得愈来愈大。 且有些命令是改变同一数据,是能够合并成一条命令的。就比如对一个计数器调用了 100 次 INCR,AOF就会存入100 条记录,其实存入一条数据就能够了。

因此为了处理这种状况,Redis提供了AOF重写机制。

AOF重写机制的触发有两种机制,一个是经过调用命令BGREWRITEAOF

192.168.17.101:6379> BGREWRITEAOF
Background append only file rewriting started
复制代码

另外一种是根据配置文件中的参数触发,参数以下

auto-aof-rewrite-percentage 100 #当前AOF文件大小和上一次重写时AOF文件大小的比值
auto-aof-rewrite-min-size 64mb  #文件的最小体积
复制代码

服务端会出现以下信息

1349:M 30 Jul 17:19:25.311 * Background append only file rewriting started by pid 1392
1349:M 30 Jul 17:19:25.379 * AOF rewrite child asks to stop sending diffs.
1392:C 30 Jul 17:19:25.379 * Parent agreed to stop sending diffs. Finalizing AOF...
1392:C 30 Jul 17:19:25.380 * Concatenating 0.00 MB of AOF diff received from parent.
1392:C 30 Jul 17:19:25.380 * SYNC append only file rewrite performed
1392:C 30 Jul 17:19:25.381 * AOF rewrite: 4 MB of memory used by copy-on-write
1349:M 30 Jul 17:19:25.466 * Background AOF rewrite terminated with success
1349:M 30 Jul 17:19:25.467 * Residual parent diff successfully flushed to the rewritten AOF (0.00 MB)
1349:M 30 Jul 17:19:25.467 * Background AOF rewrite finished successfully
复制代码

重写步骤

  1. 建立子进程进行AOF重写
  2. 将客户端的写命令追加到AOF重写缓冲区
  3. 子进程完成AOF重写工做后,会向父进程发送一个信号
  4. 父进程接收到信号后,将AOF重写缓冲区的全部内容写入到新AOF文件中
  5. 对新的AOF文件进行更名,原子的覆盖现有的AOF文件

:AOF重写不须要对现有的AOF文件进行任何读取、分析和写入操做。

配置

############################## APPEND ONLY MODE ###############################

# 是否开启AOF功能
appendonly no

# AOF文件件名称
appendfilename "appendonly.aof"

# 写入AOF文件的三种方式
# appendfsync always
appendfsync everysec
# appendfsync no

# 重写AOF时,是否继续写AOF文件
no-appendfsync-on-rewrite no

# 自动重写AOF文件的条件
auto-aof-rewrite-percentage 100 #百分比
auto-aof-rewrite-min-size 64mb #大小

# 是否忽略最后一条可能存在问题的指令
aof-load-truncated yes

复制代码

优势

  • 使用AOF 会让你的Redis更加持久化
  • AOF文件是一个只进行追加的日志文件,不须要在写入时读取文件。
  • Redis 能够在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写 。
  • AOF文件可读性高,分析容易

缺点

  • 对于相同的数据来讲,AOF 文件大小一般要大于 RDB 文件
  • 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB

数据载入

RDB和AOF都是在启动时加载的,AOF开启时,会优先从AOF文件从恢复数据 ,AOF关闭时才会从RDB文件恢复数据。

注:不知从什么版本开始,开启AOF功能时AOF文件不存在也不会加载RDB文件了

相关文章
相关标签/搜索