redis系列:RDB持久化与AOF持久化
前言
什么是持久化?
持久化(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、XML数据文件中等等。
持久化是将程序数据在持久状态和瞬时状态间转换的机制。 ----摘自百度百科
Redis的数据都是存储在内存中的,所以Redis持久化也就是要把Redis存储在内存中的数据保存到硬盘。
Redis提供了两种持久化方式
- RDB持久化(快照)
- AOF持久化(只追加操作的文件 Append-only file)
先来看看RDB持久化
RDB持久化
RDB持久化是指在客户端输入save、bgsave或者达到配置文件自动保存快照条件时,将Redis 在内存中的数据生成快照保存在名字为 dump.rdb(文件名可修改)的二进制文件中。
save命令
save命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在Redis服务器阻塞期间,服务器不能处理任何命令请求。
在客户端输入save
192.168.17.101:6379> save
OK
服务端会出现下方字符
1349:M 30 Jul 17:16:48.935 * DB saved on disk
bgsave命令
bgsave命令的工作原理如下
- 服务器进程pid为1349派生出一个pid为1357的子进程,
- 子进程将数据写入到一个临时 RDB 文件中
- 当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
在客户端输入bgsave
192.168.17.101:6379> bgsave
Background saving started
服务端会出现下方字符
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文件并还原数据库的步骤如下
- 创建一个不带网络连接的伪客户端
- 从AOF文件中分析并读取出一条写命令
- 使用伪客户端执行被读出的写命令
- 一直执行步骤2、3,知道AOF文件中的所有写命令都被处理完毕为止

这时可能会出现一个问题。服务器可能在程序正在对 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
重写步骤
- 创建子进程进行AOF重写
- 将客户端的写命令追加到AOF重写缓冲区
- 子进程完成AOF重写工作后,会向父进程发送一个信号
- 父进程接收到信号后,将AOF重写缓冲区的所有内容写入到新AOF文件中
- 对新的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文件了
redis系列:RDB持久化与AOF持久化的更多相关文章
- 详解Redis RDB持久化、AOF持久化
		1.持久化 1.1 持久化简介 持久化(Persistence),持久化是将程序数据在持久状态和瞬时状态间转换的机制,即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘). 1.2 red ... 
- 《面试官之你说我听》:简明的图解Redis RDB持久化、AOF持久化
		欢迎关注文章这一系列,一起学习 <提升能力,涨薪可待篇> <面试知识,工作可待篇> <实战演练,拒绝996篇> 如果此文对你有帮助.喜欢的话,那就点个赞呗,点个关注 ... 
- Redis数据持久化—RDB持久化与AOF持久化
		目录 Redis数据持久化-RDB持久化与AOF持久化 RDB持久化 RDB文件的创建 RDB文件的载入 自动间隔性保存 检查保存条件是否满足 AOF持久化 AOF持久化的实现 AOF文件的载入与数据 ... 
- Redis数据持久化之AOF持久化
		一.RDB持久化的缺点创建RDB文件需要将服务器所有的数据库的数据都保存起来,这是一个非常耗费资源和时间的操作,所以服务器需要隔一段时间才能创建一个新的RDB文件,就也是说创建RDB文件的操作不能执行 ... 
- 《Redis设计与实现》- AOF持久化
		1. AOF持久化 Redis AOF 持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的. 2. RDB持久化与AOF持久化的区别 RDB持久化 RDB持久化通过保存数据中的键值对来记 ... 
- 9.快照持久化和AOF持久化
		持久化功能redis为了内部数据的安全考虑,会把本身的数据以文件形式保存到硬盘中一份,在服务器重启之后会把硬盘中的数据恢复到内存(redis)的里边. 数据保存到硬盘的过程就称为“持久化”效果. re ... 
- Redis的两种持久化方式-快照持久化(RDB)和AOF持久化
		Redis为了内部数据的安全考虑,会把本身的数据以文件形式保存到硬盘中一份,在服务器重启之后会自动把硬盘的数据恢复到内存(redis)的里边,数据保存到硬盘的过程就称为“持久化”效果. redis有两 ... 
- redis之RDB持久化与AOF持久化
		Redis是一个键值对数据库服务器,服务器中通常包含着任意个非空数据库,而每个非空数据库中又可以包含任意个键值对,为了方便起见,我们将服务器中的非空数据库以及它们的键值对统称为数据库状态. 因为Red ... 
- redis 笔记03    RDB 持久化、AOF持久化、事件、客户端
		RDB 持久化 1. RDB文件用于保存和还原Redis服务器所有数据库中的所有键值对数据. 2. SAVE命令由服务器进程直接执行保存操作,所以该命令会阻塞服务器. 3. BGSAVE由子进程执行保 ... 
随机推荐
- HTML入门学习笔记
			1.html文件的基本架构 <HTML> <HEAD> <TITLE> 网页的标题 </TITLE> </HEAD> <BODY> ... 
- scp的用法
			scp是有Security的文件copy,基于ssh登录.命令基本格式:scp [OPTIONS] file_source file_target OPTIONS:-v 和大多数 linux 命令中的 ... 
- CodeForces 455C Civilization(并查集+树直径)
			好久没有写过图论的东西了,居然双向边要开两倍空间都忘了,不过数组越界cf居然给我报MLE??这个题题意特别纠结,一开始一直不懂添加的边长是多长... 题意:给你一些点,然后给一些边,注意没有重边 环, ... 
- BZOJ 4199 [Noi2015]品酒大会:后缀数组 + 并查集
			题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4199 题意: 给你一个长度为n的字符串s,和一个长为n的数组v. 对于每个整数r∈[0,n ... 
- SSAS——基础
			一.Analysis Services Analysis Services是用于决策支持和BI解决方案的数据引擎.它提供报表和客户端中使用的分析数据. 它可在多用途数据模型中创建高性能查询结构,业务逻 ... 
- C 字节对齐.我的算法学习之路
			C/C++基础笔试题1.0(字节对齐) http://blog.csdn.net/dengyaolongacmblog/article/details/37559687 我的算法学习之路 http:/ ... 
- Java微信开发_Exception_01_The type org.xmlpull.v1.XmlPullParser cannot be resolved. It is indirectly referenced from required .class files
			一.源码: package com.souvc.weixin.util; import java.io.InputStream; import java.io.Writer; import java. ... 
- web.config中httpRedirect - 重定向单个页面
			例:在下面的例子中,“目录包含page1.htm,page2.htm,page3.htm和page4.htm.如下所示的web.config文件将执行以下操作/pages/page1.htm会重定向到 ... 
- 1038 Recover the Smallest Number (30)(30 分)
			Given a collection of number segments, you are supposed to recover the smallest number from them. Fo ... 
- 51Nod1766 树上的最远点对
			1766 树上的最远点对 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即你需要求出max{dis(i,j) |a<=i&l ... 
