本文将简单介绍redis持久化的两种方式
redis提供了两种不同级别的持久化方式:
- RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储.
- AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大.
在简单了解了以上两种持久化方式的不同点后,我们开始一个一个的进行了解。
RDB持久化:
RDB方式的优缺点:
优点:
- RDB是一个非常紧凑的文件,它保存了某个时间点得数据集,非常适用于数据集的备份。比如你可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集。
- RDB是一个紧凑的单一文件,很方便传送到另一个远端数据中心,非常适用于灾难恢复。
- RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.
- 与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.
通过以上RDB持久化的工作方式,我们也可以很快的感觉到它的一些缺点
缺点:
- 如果redis意外停止工作,你希望丢失最少的数据,那么RDB很明显就不合适了,因为它是时间段的进行持久化的,哪怕你是五分钟持久化一次也难免会丢失几分钟的数据。
- RDB 需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求.如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒。
RDB持久化触发方式:
1、手动触发
主要有两种方式:save命令以及bgsava命令
save命令阻塞当前Redis服务器,知道RDB过程完成为止,对于内存比较大的实例会造成长时间阻塞,线上环境不建议使用
bgsave命令Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,时间很短
因此在使用中我们基本上使用bgsave的方式进行RDB,其工作流程主要为:
- Redis父进程判断当前是否存在正在执行的子进程,如果有则直接返回
- 如果没有则父进程执行fork操作新建一个子进程,在fork的过程中父进程会短暂阻塞,创建子进程成功,则解除父进程的阻塞,子进程进行后续的持久化操作。
- 进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换
- 进程发送信号给父进程衣示完成,父进程更新统计信息
在项目中我们如果使用RDB持久化方式,我们根据项目实际需求来执行多长时间去持久化,既调用以下方法
jedis.bgsave();
2、自动触发
在redis.windows.conf配置文件中我们打开可以看到默认的触发机制,如sava 60 10000 表示如果60秒内有1000个键被改变则进行持久化操作
save 900 1
save 300 10
save 60 10000
RDB文件处理
在redis.windows.conf配置文件中我们通过查看dbfilename以及dir可以看到RDB文件的名字以及存储路径,在redis重启启动时如果没有配置AOF持久化方式那么就会读取dump.rdb文件,如果rdb文件损坏,则可以使用redis-check-dump进行修复,再重新加载。
AOF持久化:
AOF方式优点
- 使用AOF 会让你的Redis更加耐久: 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据.
- AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题.
- Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
- AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。
AOF方式缺点
- 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
- 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。
使用方式:
使用前我们需要配置:appendonly yes 开启AOF,默认时不开启的,文件名则是通过appendfilename 设置,路径则和RDB一致。
在我们执行set方法时,:
如下:
set fd 222
会对应的在appendonly.aof中生成对应的命令
*2 $6 SELECT $1 0 *3 $3 set $2 fd $3 222
然后会按照我们所配的aof同步策略进行同步硬盘,在redis重启的时候会加载AOF文件进行数据恢复
同步策略
Redis提供了多种AOF缓冲区同步文件策略,由参数appendfsync控制
- 配置为always时,每次写入都要同步AOF文
- 配置为no,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,由操作系统自动调度刷磁盘
- 当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘
日志重写
因为 AOF 的运作方式是不断地将命令追加到文件的末尾, 所以随着写入命令的不断增加, AOF 文件的体积也会变得越来越大。举个例子, 如果你对一个计数器调用了 100 次 INCR , 那么仅仅是为了保存这个计数器的当前值, AOF 文件就需要使用 100 条记录(entry)。然而在实际上, 只使用一条 SET 命令已经足以保存计数器的当前值了, 其余 99 条记录实际上都是多余的。
为了处理这种情况, Redis 支持一种有趣的特性: 可以在不打断服务客户端的情况下, 对 AOF 文件进行重建(rebuild)。执行 BGREWRITEAOF 命令, Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令。Redis 2.2 需要自己手动执行 BGREWRITEAOF 命令; Redis 2.4 则可以自动触发 AOF 重写
//java重写命令
jedis.bgrewriteaof();
原理:
- Redis 执行 fork() ,现在同时拥有父进程和子进程。
- 子进程开始将新 AOF 文件的内容写入到临时文件。
- 对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾,这样样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。
- 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。
- 搞定!现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。
注:RDB和AOF的具体使用还是看业务的具体需求,可单独使用也可搭配使用
当 Redis 启动时, 如果 RDB 持久化和 AOF 持久化都被打开了, 那么程序会优先使用 AOF 文件来恢复数据集, 因为 AOF 文件所保存的数据通常是最完整的。