redis 持久化之 rdb & aof

作者:haobinghui 时间:2019-07-31 浏览:1062 次

持久化: 即把数据存储于断电后不会丢失的设备中,通常是硬盘. 


常见的持久化方式: 

  • 主从:通过从服务器保存和持久化,如mongoDB的replication sets配置 

  • 日志:操作生成相关日志,并通过日志来恢复数据 

  • couchDB对于数据内容,不修改,只追加,则文件本身就是日志,不会丢失数据.


redis持久化的方式

  1. rdb快照

  2. aof日志


redis-之rdb快照持久化


rdb的工作原理: 

图片.png


rdb 有 redis-server 的主进程,和专用来负责 rdb dump 的子进程,在运行中一旦达到了触发条件,redis-server 会调用 rdb dump 子进程进行 rdb 快照

图片.png


每隔N分钟或N次写操作后,

从内存dump数据形成rdb文件,

压缩

放在备份目录

注:红色部分可通过参数来配置


rdb快照相关参数


在配置文件中可以看到下面的相关配置参数:redis.conf

save 900 1        #刷新快照到硬盘中,必须满足两者要求才会触发,即900秒之后至少1个关键字发生变化。

save 300 10      #必须是300秒之后至少10个关键字发生变化。

save 60 10000  #必须是60秒之后至少10000个关键字发生变化。

(3个选项都屏蔽,rdb禁用)


stop-writes-on-bgsave-error yes    #后台存储错误停止写。

rdbcompression yes    #使用LZF压缩rdb文件。

rdbchecksum yes        #导入rbd恢复时数据时,要不要检验rdb的完整性

dbfilename dump.rdb    #设置rdb文件名。

dir ./    #设置工作目录,rdb文件会写入该目录。


rdb的缺陷:

刷新快照到硬盘中,必须满足上面的三种条件,那么如果我们将数据写入到 redis 之后,在还没有满足刷新快照到硬盘中的条件时突然断电了……将会丢失这两个保存点之间的数据

图片.png


我们更改一下刷新快照到硬盘中的条件配置:

save 900 1

save 300 10

save 60 3000


杀掉redis进程并重新启动:以使用新的配置文件

root@hao:/usr/local/redis# pkill -9 redis
root@hao:/usr/local/redis# ./bin/redis-server ./redis.conf


然后通过性能测试工具 redis-benchmark 命令进行执行很多次命令,以达到刷新快照到磁盘的条件:

root@hao:/usr/local/redis# ./bin/redis-benchmark -n 10000


59523.81 requests per second(可见 redis 单机并发很高的)


此时已经有了 dump.rdb 文件

图片.png


此时重点来了!!!

上面的 redis 已经生成了 rdb 快照,那么我再次进行添加值

图片.png


此时还没达到生成了 rdb 快照的条件,但是 redis 服务断电了!!!

root@hao:/usr/local/redis# pkill -9 redis


重新启动 redis 服务之后,发现 name 并没有值,因为没有达到快照的保存条件。

图片.png


丢失数据在实际项目中是不能够接受的!!!

出于对持久化的更精细要求,redis 增添了 aof(append only file) 方式确保数据不丢失,二者配合使用,效果更好。


rdb的优势:

因为 rdb 导出的内存的一整块映像,它的恢复速度相当快,比如当 redis 断电关闭后重启,redis 可以从磁盘的 dump.rdb 印象文件中快速恢复。


redis-之aof日志持久化(2.4版本之后)


aof日志相关参数


appendonly yes    #是否打开 aof 日志功能


appendfilename "appendonly.aof"    #aof 日志文件存放名称及路径


appendfsync no        # 写入工作交给操作系统,由操作系统判断缓冲区大小,统一写入到aof,同步频率低,速度快 

appendfsync always    # 每1个命令,都立即同步到 aof,安全丢失数据少,速度慢

appendfsync everysec    #折中方案,每秒写1次 


no-appendfsync-on-rewrite yes     #正在导出rdb快照的过程中,要不要停止同步aof


auto-AOF-rewrite-percentage 100    #aof文件大小比起上次重写时的大小,增长率100%时,重写 

auto-AOF-rewrite-min-size 64mb    #aof文件,至少超过64M时,重写


注: 在dump rdb过程中,aof如果停止同步,会不会丢失?

答: 不会,所有的操作缓存在内存的队列里, dump完成后,统一操作.


问: 如果rdb文件,和aof文件都存在,优先用谁来恢复数据?

答: aof


实际场景:开启 aof 并配置相关配置后,关闭 redis 后重启,redis 服务器中没有任何内容,我们上节课不是配置了 rdb 了吗?咋没发挥作用呢?

答:rdb(有内容),开启 aof 选项,重启 redis 后,产生了一个空的 aof 文件。 此时 rdb 和 aof 都有,以 aof (空文件)来恢复,所以空了……


问: 2种是否可以同时用?

答: 可以,而且推荐这么做


问: 恢复时rdb和aof哪个恢复的快

答: rdb快,因为其是数据的内存映射,直接载入到内存,而aof是命令,需要逐条执行


aof 相关实验


修改相关参数后,重启 redis 服务:

发现此时会生成一个 appendonly.aof 文件,此时 aof 文件中是空的。

图片.png


再看一下,为什么 redis 服务器空了?上节课不是配置了 rdb 了吗?咋没发挥作用呢?

127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379>


此时我添加值:

127.0.0.1:6379> set site haobinghui.com
OK
127.0.0.1:6379> set name hao
OK
127.0.0.1:6379>


再查看 appendonly.aof 文件

root@hao:/usr/local/redis# more appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$4
site
$14
haobinghui.com
*3
$3
set
$4
name
$3
hao
root@hao:/usr/local/redis#


此时数据已经可以记录到 aof 日志文件中,并且是以秒级为单位的,那么这样数据就安全多了。即使再次发生断电情况,也能够保持数据一致。


如何解决 aof 文件过大的问题?


比如对应一个 key 进行上百次操作,那么在 aof 日志中就会重复上百次的日志记录。但是这个 key 在内存中最终的值是一个固定的。


1:每个命令重写一次aof?

2:某key操作100次,产生100行记录,aof文件会很大,怎么解决?


注: aof重写是指什么?

答: aof重写是指把内存中的数据,逆化成命令,写入到.aof日志里.

以解决 aof日志过大的问题.


aof 重写实验(借助系统测试工具 redis-benchmark


为了更快使 aof 日志重写,我们将大小改为 32M

auto-AOF-rewrite-percentage 100

auto-AOF-rewrite-min-size 32mb


然后通过性能测试工具 redis-benchmark 命令进行执行很多次命令,以达到刷新快照到磁盘的条件:

root@hao:/usr/local/redis# ./bin/redis-benchmark -n 60000


51282.05 requests per second(此次运行速度要比没有开启 aof 之前慢,见上一次实验数据对比)

图片.png


我们可以看到,当 aof 日志文件大于 34M 后,下一次变成了 4.9M,可见 aof 重写能够大大缩小 aof 日志文件大小。


bgrewriteaof    # 后台进程重写AOF

bgsave             # 后台保存 rdb 快照

save                 # 保存rdb快照

lastsave            # 上次保存时间

图片.png

图片.png


有问题欢迎在本站留言交流,互相学习。

标签: redis