浅谈Redis的两种持久化机制

前言

众所周知,redis是一个内存数据库,既然是将数据保存在内存中,上下线之后数据自然就会丢失,在我们的业务中,这种情况当然是不允许发生的,所以这时候就需要涉及到redis的持久化机制

redis可以手动开启持久化,来让内存中的数据持久化到磁盘上,redis提供了以下两种持久化方案:

  • RDB快照
  • AOF日志

接下来我们就要针对这两种方式来做一个讲解

RDB快照

rdb快照的原理是对redis中的数据进行周期性的持久化,也可以理解为redis每隔一段时间就把当前内存数据的状态持久化到磁盘中

这个具体的操作并不是由工作进程来完成的,redis会调用fork函数来创建一个子进程,父进程会正常执行客户端发来的请求操作,而子进程会把当前的数据库快照写入到临时文件中,最后替换原有的文件(默认为dump.rdb)

由于操作系统的copy-on-write机制,父子进程是共享物理页面的,当父进程处理写请求时,操作系统为父进程要修改的页面创建一个副本,所以子进程地址空间的数据只是当前时刻整个数据库的一个快照,也这就是把这种方式叫做rdb快照的原因

这种方式的优点很明显:

  • RDB模式下会不断产生快照文件,均代表某一时刻redis中的数据,可以用作冷备份
  • 采用子进程来执行磁盘IO,写入快照的时候对redis的影响非常小,可以保持redis的高性能
  • 重启和恢复redis数据的速度很快

但是其也有缺点:

  • 如果在两次快照之间发生宕机,则其间写入的数据会丢失
  • 每次fork的时候,如果数据很大,则会产生一定时间的服务暂停

redis是默认开启这种持久化方式的,可以打开redis.conf文件,如果是window系统就打开redis.window.conf(redis.windows-service.conf文件是作为系统服务启动时加载的配置文件,如果你设置redis为系统服务,就打开这一个),会发现下面这些配置:

save 900 1
save 300 10
save 60 10000

我们拿save 900 1这条配置来举例,其含义就是在900秒内,如果至少有1个key值发生了变化,就进行内存快照,我们查看默认的这些配置也可以发现,这些save语句是可以同时出现的,所以你可以配置很多这样的rdb快照设置

AOF日志

看名字应该能猜得出,这种持久化模式是采用日志来进行的,aof模式通过把每条指令追加到日志文件中(默认为appendonly.aof文件),当redis重启后,通过回放aof日志文件中的操作来实现数据集的恢复

开启了aof持久化模式后,redis会将所有收到的修改命令通过write函数追加到日志文件中,具体的执行可以设置以下3种:

  • always:每次有修改操作就强制写入
  • everysec:每秒钟强制写入(推荐使用)
  • no:不主动进行持久化,将数据存放在操作系统中,一般linux每30分钟刷新一次数据

这三种模式分别对应配置文件中的appendfsync alwaysappendfsync everysec,和appendfsync no

接着我们可以看一下aof日志的内容,这里截取了一小段我测试的aof文件:

set
$3
bbb
$3
aaa
*3
$3
set
$3
aaa
$3
ccc
*2
$3
del
$3
aaa

可以看出,所有的修改命令都是通过命令符-数据库名-key值这样的顺序来保存的,可读性也很高

但是aof日志依然有一个问题,如果我们反复地执行set操作,那么aof日志中就会重复地保存这些不必要的操作,因为这些命令最终的执行结果和一个set命令的执行结果没有任何区别,那怎么解决这种数据冗余问题呢?

其实这一点redis开发人员也想到了,redis提供了bgrewriteaof命令,收到此命令的redis服务器会自动fork出一个子进程,这个子进程会根据内存中的数据快照,来创建一个用于恢复当期数据的最小日志文件,当写入完成后,子进程会向父进程发送信号,然后父进程把缓存中的修改命令也写入这个临时文件中,并用这个临时文件来替换原aof文件

这份生成的aof文件你会发现几乎都是set操作,而且基本不会出现对一个值重复的set命令,所以恢复起来也相当迅速

aof模式的优点如下:

  • 可读性非常高,如果发生了误操作,可以在rewrite操作之前拷贝一份aof日志文件,将其中的误操作删去,然后替换原有文件即可,不影响redis的恢复读取,可以用来作为紧急恢复
  • 丢失数据的几率很低,即使丢失也不会有太大影响(如果设置了每秒备份,则最多会丢失1s内写入的数据)

但是也依然有缺点:

  • aof文件一般大于rbd文件
  • 根据选择的fsync策略的不同,aof的速度可能会慢于rdb
  • 在写入负载很大的情况下,aof不能提供最大延迟的保证,而rbd可以
  • 有几率发生不能完全恢复redis数据的bug

使用场景

在平常使用时,我们不能说哪种就是最好的,而要根据实际情况来选择,这里我提供一些选择的建议:

  • 如果你可以允许当发生宕机时有几分钟的数据丢失,那么就使用RDB快照模式,它可以让你更快地重启redis
  • 其余情况均推荐采用RDB+AOF的模式

没错,在使用时可以同时配置rdb和aof两种模式,redis官方也推荐我们这么做,aof为主,rdb为辅,aof记录日志,rdb做数据库备份,以及aof引擎失效后的替代

总结

持久化的讲解到这里基本就结束了,这里仅仅是带大家简要了解了一下redis持久化的内容,本文一部分是个人的理解、总结与实践,一部分是参考Redis Persistence – Redis这篇官方文档,如有什么错误欢迎指正


 

猜你喜欢

转载自blog.csdn.net/qq_36860032/article/details/90717336