什么是持久化?redis
持久化(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、XML数据文件中等等。 持久化是将程序数据在持久状态和瞬时状态间转换的机制。 ----摘自百度百科数据库
Redis的数据都是存储在内存中的,因此Redis持久化也就是要把Redis存储在内存中的数据保存到硬盘。
Redis提供了两种持久化方式缓存
先来看看RDB持久化bash
RDB持久化是指在客户端输入save
、bgsave
或者达到配置文件自动保存快照条件时,将Redis 在内存中的数据生成快照保存在名字为 dump.rdb(文件名可修改)的二进制文件中。服务器
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性能
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 ./
复制代码
翻译来自http://www.redis.cn
AOF持久化是经过保存Redis服务器所执行的写命令来记录数据库状态,也就是每当 Redis 执行一个改变数据集的命令时(好比 SET), 这个命令就会被追加到 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 文件进行写入时停机,形成了 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文件进行任何读取、分析和写入操做。
############################## 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
复制代码
RDB和AOF都是在启动时加载的,AOF开启时,会优先从AOF文件从恢复数据 ,AOF关闭时才会从RDB文件恢复数据。
注:不知从什么版本开始,开启AOF功能时AOF文件不存在也不会加载RDB文件了