Redis持久化

概要

Redis是在内存中储存数据,服务器重启时,内存中的数据将丢失,为了保证数据安全,Redis提供将数据持久化到磁盘中。Redis提供两种数据持久化方式:RDB(Redis Database)和AOF(Append Only File)。

准备

  • 安装Redis5.0(演示版本5.0,其他版本也可以)

RDB

RDB是Redis默认的持久化方案。但触发Redis保存规则,Redis会将内存的数据保存到硬盘中,会在指定目录下生成一个xxx.rdb文件,服务重启会加载该文件来恢复数据。 

配置

# 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
# save <seconds> <changes>
# Redis默认配置文件中提供了三个条件:分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。
# 如果不行使用RDB,设置 save "" ,关闭或去掉其他save设置。
save 900 1
save 300 10
save 60 10000

# 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大
rdbcompression yes

# 指定本地数据库文件名,默认值为dump.rdb
dbfilename dump.rdb

# 指定本地数据库存放目录
dir /usr/local/redis/var/

操作

[root@one /]# systemctl start redis-server.service # 启动redis服务
[root@one /]# redis-cli # 启动客户端
127.0.0.1:6379> MSET name Lewis age 27 # 批量设置
OK
127.0.0.1:6379> SHUTDOWN # 关闭客户端,SHUTDOWN会触发save操作,Redis会将内存数据保存本地,生成一个dump.rdb文件
not connected> QUIT # 退出
[root@one /]# cd /usr/local/redis/var/ # 文件目录
[root@one var]# ls
dump.rdb  redis.log
[root@one var]# cp dump.rdb dump.rdb.bak # 备份数据dump.rdb
[root@one var]# redis-cli 
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> FLUSHALL # 清空所有数据库,FLUSHALL会触发save操作,Redis会将内存数据保存本地,生成一个dump.rdb文件
OK
127.0.0.1:6379> keys * # 内存已无数据
(empty list or set)
127.0.0.1:6379> QUIT
[root@one var]# systemctl stop redis-server.service # 关闭服务端
[root@one var]# cp dump.rdb.bak dump.rdb # 恢复dump.rdb
cp: overwrite ‘dump.rdb’? y
[root@one var]# systemctl start redis-server.service  # 重启Redis服务
[root@one var]# redis-cli # 打开客户端
127.0.0.1:6379> keys * # 查看恢复数据
1) "name"
2) "age"
127.0.0.1:6379> 

RDB修复

# 当服务器意外情况下可能数据保存不完整,可以通过自带修复工具进行修复
[root@one var]# redis-check-rdb dump.rdb

触发机制

  • 自动触发:通过配置save策略,制动触发
  • 手动触发:执行save或者bgsave;save是Redis主线程同步转储,bgsave则是在后台执行转储;因为save会阻塞Redis服务器,所以不要在生产环境中使用;执行bgsave命令,Redis的主线程将继续处理收到的命令,同时会通过fork()系统调用创建一个子进程将转储数据保存一个名为temp-<bgsave-pid>.rdb的零时文件中,当转储结束后,这个临时文件会被重命名dbfilename定义的名字覆盖由参数dir指定的本地目录中的旧转储文件

AOF

以日志的方式记录每次写入命令,重启服务执行AOF文件中命令达到恢复数据的目的。

配置

# 开启AOF,默认no
appendonly yes

# AOF文件名
appendfilename "appendonly.aof"

# 指定更新日志条件,共有3个可选值:no:不要同步,只让操作系统在需要的时候刷新数据(快);always:每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)everysec:表示每秒同步一次(折中,默认值)
# appendfsync always
appendfsync everysec
# appendfsync no

# AOF重写规则。文件大小比例增加100%,且大小增加至少64mb则执行文件重写策略;Redis会fork出一条新进程,读取内存中的数据,并重新写到一个临时文件中,最后替代元AOF文件;如果参数设置0,表示不进行AOF重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

操作

[root@one ~]# systemctl restart redis-server.service 
[root@one ~]# redis-cli 
127.0.0.1:6379> set name "小新"
OK
127.0.0.1:6379> set age 5
OK
127.0.0.1:6379> QUIT
[root@one ~]# cd /usr/local/redis/var/
[root@one var]# ll
total 8
-rw-r--r-- 1 redis redis   87 Jul 18 18:37 appendonly.aof
-rw-r--r-- 1 redis redis 1860 Jul 18 18:36 redis.log
[root@one var]# cp appendonly.aof appendonly.aof.bak
[root@one var]# redis-cli 
127.0.0.1:6379> FLUSHALL
OK
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> QUIT
[root@one var]# systemctl stop redis-server.service 
[root@one var]# cp appendonly.aof.bak appendonly.aof
cp: overwrite ‘appendonly.aof’? y
[root@one var]# systemctl start redis-server.service 
[root@one var]# redis-cli 
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> 

AOF文件说明

[root@one var]# cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$4
name
$6
小新
*3
$3
set
$3
age
$1
5

*2 :该指令包含2个语句
$6 :该语句包含6个字节(一个汉字3个字节)
默认选择database 0

原理

AOF功能启动之后,Redis会在数据目录创建AOF文件。AOF文件默认文件名是appendonly.aof,也可通过配置文件中appendfilename参数进行修改。同时,Redis还会将当前内存数据复制到AOF文件。、

每当Redis服务器收到一个会实际修改内存数据的写入命令时,Redis会将该命令追加AOF文件中。但事实上是操作系统维护一个缓冲区,Redis命令首先会被写入到这个缓冲区中。而缓冲区的数据必须被刷新到磁盘中才能被永久保存。这个过程需要Linux调用fsync()完成,这是一个阻塞调用,只有磁盘设备报告缓冲区中的数据写入完成才会返回。

在将命令追加AOF文件时,我们可以通过Redis的配置参数appendfsync来调整fsync()的频率。该参数提供三个选项:

  • always:对每个写入命令都调用fsync()。这个选项可以确保在发生意外(服务器奔溃或硬件故障等),只会丢失一条命令。但是,由于fsync()是一个阻塞调用,Redis性能会受到物理磁盘写入的限制。将appendfsync设置为always是不明智的,应为服务器性能会显著下降。
  • everysec:每秒调用一次fsync(),在发生意外故障时,会丢失一秒的数据。建议采用此选项,已达到数据安全和性能一个这种。
  • no:永远不调用fsync(),采用该选项时,将由操作系统决定何时将数据从缓冲区写入到磁盘。在大多数Linux系统中,这个频率是没30秒。

当Redis服务器关闭时,fsync()会被显式调用,以确保写入缓冲区中的所有数据都会被刷新到磁盘中。

AOF修复

# 当服务器意外情况下可能数据保存不完整,可以通过自带修复工具进行修复
[root@one var]# redis-check-aof --fix appendonly.aof

AOF重写

  • 执行bgwriteaof命令,如果当前进程正在执行AOF重写,那么直接返回;如果有进程正在执行bgsave,那么等待bgsave执行完毕再执行AOF重写
  • Redis主进程会fork一个子进程执行AOF重写
  • AOF重写过程中,主进程收到写操作还会将命令写到aof_buf以及同步aof_buf中数据到AOF文件中;此外,主进程收到命令还会写入aof_rewrite_buf中
  • 由于AOF重写过程中原AOF还在陆续写入数据,所以AOF重写只会拿到fork子进程时AOF文件进行重写,并生成一个临时的AOF文件
  • 子进程完成AOF重写会向主进程发送消息,主进程会将aof_rewrite_buf数据写入新AOF文件,并将新AOF文件替换旧AOF文件

重载持久化文件顺序

  • Redis重启优先加载AOF文件,如果AOF文件不存在再去加载RDB文件
  • 如果AOF和RDB文件都不存在,那么直接启动
  • 不论加载AOF文件还是RDB文件,只要发送错误,就会启动失败

AOF触发机制

  • 自动触发:通过上述配置 auto-aof-rewrite-percentage 100 和 auto-aof-rewrite-min-size 64mb 同时满足触发
  • 手动触发:执行bgrewriteaof,bgrewriteaof 命令用于异步执行一个 AOF(AppendOnly File) 文件重写操作。重写会创建一个当前 AOF 文件的体积优化版本。即使 Bgrewriteaof 执行失败,也不会有任何数据丢失,因为旧的 AOF 文件在 Bgrewriteaof 成功之前不会被修改。

总结

  • RDB持久化基于内存快照存储二进制文件,AOF持久化基于写命令存储文本文件
  • RDB采取了压缩算法,比较小;AOF文件随着命令叠加会越来越大,Redis提供AOF重写来减小文件和减少文件恢复时间
  • 恢复RDB文件速度比AOF文件快很多
  • RDB持久化方式实时性不好,所以AOF持久化更主流
  • AOF启动优先级高于RDB

 

参考

《Redis 4.x Cookbook中文版》

《深入Redis的RDB和AOF两种持久化方式以及AOF重写机制的分析》

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值