likes
comments
collection
share

Redis持久化之RDB和AOF

作者站长头像
站长
· 阅读数 14

Redis是基于内存的数据库,为了保证数据的可用性Redis提供了两种数据持久化机制:RDB和AOF。这里来介绍一下。

RDB模式

RDB模式是通过快照的方式持久化,也就是每隔一段时间,把内存中的数据写入磁盘。恢复的时候,Redis会自动从工作区拿出来进行恢复。也可以把备份出来的数据直接写入另一个Redis里。

RDB模式的优势

  1. 每隔一段时间就会全量备份,而且备份出来的文件是经过压缩过的比较小,非常适合做数据的定期备份和灾难恢复
  2. 备份和恢复简单,仅仅只有一个文件,可以直接传输到任何地方
  3. 备份的时候不影响Redis的读写,备份的时候会fork一个新进程来做操作不影响主进程的IO

RDB工作原理

redis在触发RDB的时候会有两种方式:手动触发和定时触发。

手动触发有两个命令: save:在执行的时候会阻塞Redis的服务,直到RDB文件完成才会释放我们Redis进程恢复读写操作 bgsave:执行bgsave的时候会在后台fork一个进程进行RDB的生成,不影响主进程的业务操作 使用起来非常简单,用redis客户端连接进去直接敲命令就可以了。

127.0.0.1:6379> save
OK

自动触发其实就是redis根据配置定时参数调用bgsave方法(每次shutdown的时候也会调)。我们重点看一下bgsave的工作流程

Redis持久化之RDB和AOF

  1. redis执行bgsave命令,Redis判断当前存在正在进行执行的子进程,如RDB/AOF子进程,存在bgsave命令直接返回
  2. fork出子进程,fork操作中Redis父进程会阻塞
  3. fork完成返回
  4. 子进程保存redis数据到RDB文件
  5. 子进程告诉父进程处理完成

RDB配置

Redis默认的持久化方式就是RDB,打开redis.conf你可以发现RDB已经配置好了

dbfilename dump.rdb #rdb保存的文件名
dir ./ #就是存放我们RDB备份文件的目录
# Save the DB on disk:
#   save <seconds> <changes>
# 持久化频率配置,表示多少秒内更新了多少次就会触发bgsave
#   save "" 关闭RDB
save 900 1  #900秒内变更1次才触发bgsave
save 300 10
save 60 10000


# 当bgsave出错的时候是否停止redis写操作
stop-writes-on-bgsave-error yes
#开启RDB压缩
rdbcompression yes
#进行CRC64算法校验,有10%的性能损耗
rdbchecksum yes

我们一般情况下只用更改一下dir目录就可以了,我这里改的的是这个目录

dir /usr/local/redis/working

如何使用RDB文件恢复数据

首先执行config get dir命令查看一下当前redis设置的工作目录是什么

127.0.0.1:6379>  config get dir
1) "dir"
2) "/usr/local/redis/working"

然后直接把RDB备份好的文件放到dir目录就可以了,Redis在启动的时候会自动加载数据到内存,但是Redis在加载RDB过程中是阻塞的,直到加载完毕才能恢复操作。

RDB模式的缺点

  1. 发生故障时,会丢失一段时间的数据。因为是定时备份,上次备份时间到宕机时间的数据就会丢失
  2. fork出来的子进程和父进程一模一样,这样会导致内存随时膨胀两倍

AOF模式

前面讲到RDB模式会丢失最后一次备份时间到宕机的这段时间备份的数据,所以说就有了增量备份,也就是AOF。AOF持久化会把被执行的写命令写到AOF文件的末尾,记录数据的变化。Redis默认是没有开启AOF的,开启后Redis每执行一条写的操作命令都会被追加到AOF文件里(有点像mysql的binlog),这会降低Redis的性能,但大部分情况下这个影响是能够接受的。

AOF模式的优势

  • 数据更完整,安全性更高,AOF是以秒为单位进行备份的,如果发生问题只会丢失一秒的数据
  • AOF日志包含所有写操作,而且是可读的,所以它不仅可以恢复全量数据也可以恢复误操作的数据
  • AOF有日志压缩功能,可以缓解AOF文件过大的问题

AOF工作原理

开启AOF持久化功能后,服务器每执行一个写命令都会把该命令以协议格式先追加到aof_buf缓存区的末尾,而不是直接写入文件,避免每次有命令都直接写入硬盘,减少硬盘IO次数。关于aof_buf缓冲区的内容写入AOF文件中,Redis提供了多种策略

appendfsync always:每一个写操作的命令,写入到aof_buf后都同步写入磁盘 appendfsync everysec:每秒同步一次,每秒把aof_buf中所有的命令同步写入到硬盘 appendfsync no:又操作系统决定什么时候把aof_buf中的所有命令同步写入到磁盘(一般是等cpu资源比较空闲的时候)

appendfsync选项的默认配置为everysec,即每秒执行一次同步。也是我们工作中推荐的一种配置

AOF配置

AOF需要手动开启

appendonly yes  #开启AOF

appendfilename "appendonly.aof" #AOF的文件名设置

appendfsync everysec # aof同步备份的频率设置,也就是上面说的aof_buf同步机制

no-appendfsync-on-rewrite no # 重写的时候是否要同步,yes则不同步,no同步阻塞可以保证数据安全

# 重写机制(压缩机制):避免文件越来越大,将key的重复值合并,重写的时候会触发fork一个新进程来操作
# 触发条件就是下面两个都满足才触发
# 上面配置no,重写触发后会fork进程并阻塞主进程无法写入导致等待,所以两个值可以设置小点让重写快速阻塞完毕
# 1.现有的文件比上次多出100%:上次压缩完2G,现在已经4G了如果是50%就是3G
auto-aof-rewrite-percentage 100
# 2.现有的文件已经超过100mb了
auto-aof-rewrite-min-size 100mb

这三个 no-appendfsync-on-rewriteauto-aof-rewrite-percentageauto-aof-rewrite-min-size 命令需要再解释一下。

AOF有一个文件重写的功能。压缩文件的机制是会判断多个命令写的是否是同一个key,假如有set name zhangsanset name lisi 这两个命令都存在AOF文件里。它们俩写的key是一样的,如果set name lisi是最后执行的,那么name的值不管之前有多少次修改最后的结果都是lisi。AOF重写的时候就会删除文件中set name zhangsan 这个命令。

AOF在做重写操作的时候会fork一个新的进程进行操作,no-appendfsync-on-rewrite如果设置是no的话fork进程在做重写工作的时候redis主进程就不会往AOF文件写数据了。这样可以保证数据安全。auto-aof-rewrite-percentageauto-aof-rewrite-min-size两个命令是设置什么时候开始做重写操作,上面配置的是当AOF文件超过了100M并且AOF文件的体积比上一次重写后的体积大了一倍(100%)时进行重写。

如何使用AOF文件恢复数据

跟RDB一样,在redis设置的工作目录里把appendonly.aof存入进去就可以了。redis在开启AOF的时候会优先使用aof文件恢复数据。

[/usr/local/redis/working]# ls
appendonly.aof  dump.rdb

AOF的缺点

  • 对于相同的数据集,AOF文件的体积要大于RDB文件,数据恢复也会比较慢
  • 因为并不是全量更新,所以一旦AOF文件出现问题,数据就会不完整

##避免在中途开启AOF导致Redis数据丢失

这里需要非常注意的一点,一般情况下我们RDB和AOF是同时开启的。但是如果你在只开启了RDB后使用了一段时间再开启AOF可能会导致数据丢失。因为AOF文件在开启后就会自动创建一个空文件,Redis在重新启动后会优先加载AOF,这样Redis就会把AOF的空文件加载到内存中。这个时候你再执行redis操作就可能导致RDB备份的数据全部丢失。

正确的操作是先在redis客户端在线开启AOF,这样AOF就不会生成空文件了,而是把之前操作的命令都写到AOF文件中。然后再去redis.conf文件中把AOF打开,再重启redis就不会有问题了。

127.0.0.1:6379> config get appendonly
1) "appendonly"
2) "yes"

127.0.0.1:6379> config set appendonly yes
转载自:https://juejin.cn/post/7220594286361526332
评论
请登录