Redis 提供了 RDB 和 AOF 两种持久化方案:html
RDB:生成指定时间间隔内的 Redis 内存中数据快照,是一个二进制文件 dumpr.rdbredis
AOF:记录 Redis 除了查询之外的全部写命令,并在Redis 服务启动时,经过从新执行这些命令来还原数据。数据库
默认 Redis 会以 RDB 快照的形式将一段时间内的数据持久化到硬盘,保存成一个 dumpr.rdb
二进制 文件。缓存
工做原理简单介绍一下:安全
当 Redis 须要作持久化时,Redis 会 fork 一个子进程,子进程将数据写到磁盘上一个临时 RDB 文件中。当子进程完成写临时文件后,将原来的 RDB 替换掉,这样的好处就是能够 copy-on-write
。服务器
固然咱们也能够手动执行 save
或者 bgsave
(异步)生成 RDB 文件。app
redis.conf 默认配置异步
save 900 1 save 300 10 save 60 10000
在默认状况下, Redis 将数据库快照保存在名字为 dump.rdb 的二进制文件中。函数
你能够对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被知足时, 自动保存一次数据集。工具
你也能够经过调用 SAVE
或者 BGSAVE
, 手动让 Redis 进行数据集保存操做。
好比说, 如下设置会让 Redis 在知足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动保存一次数据集:
save 60 1000
这种持久化方式被称为快照(snapshot)。
当 Redis 须要保存 dump.rdb 文件时, 服务器执行如下操做:
这种工做方式使得 Redis 能够从写时复制(copy-on-write)机制中获益。
RDB 是一个比较紧凑的文件,它保存了 Redis 在某个时间点的数据,这种数据比较适合作备份和用于灾难恢复。
好比说,你能够在最近的 24 小时内,每小时备份一次 RDB 文件,而且在每月的每一天,也备份一个 RDB 文件。 这样的话,即便赶上问题,也能够随时将数据集还原到不一样的版本。
若是你须要尽可能避免在服务器故障时丢失数据,那么 RDB 不适合你。 虽然 Redis 容许你设置不一样的保存点来控制保存 RDB 文件的频率, 可是, 由于 RDB 文件须要保存整个数据集的状态, 因此它并非一个轻松的操做。 所以你可能会至少 5 分钟才保存一次 RDB 文件。 在这种状况下, 一旦发生故障停机, 你就可能会丢失好几分钟的数据。
使用 AOF 作持久化,每个写命令都经过 write
函数追加到 appendonly.aof
文件中。
AOF 就能够作到全程持久化,只须要在配置文件中开启(默认是 no ),appendfsync yes
开启 AOF 以后,Redis 每执行一个修改数据的命令,都会把它添加到 AOF 文件中,当 Redis 重启时,将会读取 AOF 文件进行“重放”以恢复到 Redis 关闭前的最后时刻。
你能够配置 Redis 多久才将数据 fsync 到磁盘一次。
redis.conf 默认配置
appendfsync yes appendfsync always #每次有数据修改发生时都会写入AOF文件。 appendfsync everysec #每秒钟同步一次,该策略为AOF的缺省策略。
有三个选项:
1,每次有新命令追加到 AOF 文件时就执行一次 fsync :很是慢,也很是安全。
2,每秒 fsync 一次:足够快(和使用 RDB 持久化差很少),而且在故障时只会丢失 1 秒钟的数据。
3,从不 fsync :将数据交给操做系统来处理。更快,也更不安全的选择。
推荐(而且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略能够兼顾速度和安全性。
AOF 重写和 RDB 建立快照同样,都巧妙地利用了写时复制机制。
如下是 AOF 重写的执行步骤:
Redis 执行 fork() ,如今同时拥有父进程和子进程。
子进程开始将新 AOF 文件的内容写入到临时文件。
对于全部新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾: 这样即便在重写的中途发生停机,现有的 AOF 文件也仍是安全的。
当子进程完成重写工做时,它给父进程发送一个信号,父进程在接收到信号以后,将内存缓存中的全部数据追加到新 AOF 文件的末尾。
搞定!如今 Redis 原子地用新文件替换旧文件,以后全部命令都会直接追加到新 AOF 文件的末尾。
1,使用 AOF 作持久化,能够设置不一样的 fsync 策略,好比无 fsync ,每秒钟一次 fsync ,或者每次执行写入命令时 fsync 。
AOF 的默认策略为每秒钟 fsync 一次,在这种配置下,Redis 仍然能够保持良好的性能,而且就算发生故障停机,也最多只会丢失一秒钟的数据。
fsync 会在后台线程执行,因此主线程能够继续努力地处理命令请求。
2,AOF 文件是一个只进行追加操做的日志文件,不是生成新的以后替换掉那种,即便日志由于某些缘由而包含了未写入完整的命令(好比写入时磁盘已满,写入中途停机,等等), redis-check-aof 工具也能够轻易地修复这种问题。
3,Redis 能够在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。
整个重写操做是绝对安全的,由于 Redis 重写是建立新 AOF 文件,重写的过程当中会继续将命令追加到现有旧的 AOF 文件里面,即便重写过程当中发生停机,现有旧的 AOF 文件也不会丢失。 而一旦新 AOF 文件建立完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操做。
4,AOF 文件有序地保存了对数据库执行的全部写入操做, 这些写入操做以 Redis 协议的格式保存, 所以 AOF 文件的内容很是容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也很是简单: 举个例子, 若是你不当心执行了 _FLUSH ALL_(清空整个 Redis 服务器的数据(删除全部数据库的全部 key )。) 命令, 但只要 AOF 文件未被重写, 那么只要中止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就能够将数据集恢复到 FLUSHALL 执行以前的状态。
对于相同的数据集来讲,AOF 文件的体积一般要大于 RDB 文件的体积。
根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB。 在通常状况下, 每秒 fsync 的性能依然很是高, 而关闭 fsync 可让 AOF 的速度和 RDB 同样快, 即便在高负荷之下也是如此。
不过在处理巨大的写入载入时,RDB 能够提供更有保证的最大延迟时间(latency)。
RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操做过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换以前的文件,用二进制压缩存储。
AOF持久化以日志的形式记录服务器所处理的每个写、删除操做,查询操做不会记录,以文本的方式追加记录,能够打开文件看到详细的操做记录。
若是你很是关心你的数据,但仍然能够承受数分钟之内的数据丢失,那么你能够只使用 RDB 持久。
AOF 将 Redis 执行的每一条命令追加到磁盘中,处理巨大的写入会下降 Redis 的性能,不知道你是否能够接受。
数据库备份和灾难恢复:
定时生成 RDB 快照(snapshot)很是便于进行数据库备份, 而且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快。
Redis 支持同时开启 RDB 和 AOF,系统重启后,Redis 会优先使用 AOF 来恢复数据,这样丢失的数据会最少。
由于 AOF 的运做方式是不断地将命令追加到文件的末尾, 因此随着写入命令的不断增长, AOF 文件的体积也会变得愈来愈大。
举个例子
若是你对一个计数器调用了 100 次 INCR , 那么仅仅是为了保存这个计数器的当前值, AOF 文件就须要使用 100 条记录(entry)。
然而在实际上, 只使用一条 SET 命令已经足以保存计数器的当前值了, 其他 99 条记录实际上都是多余的。
为了处理这种状况, Redis 支持一种有趣的特性: 能够在不打断服务客户端的状况下, 对 AOF 文件进行重建(rebuild)。
执行 BG REWRITE AOF
命令, Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令。
Redis 2.2 须要本身手动执行 BGREWRITEAOF
命令; Redis 2.4 则能够自动触发 AOF 重写, 具体信息请查看 2.4 的示例配置文件。
磁盘故障, 节点失效, 诸如此类的问题均可能让你的数据消失不见, 不进行备份是很是危险的。
Redis 对于数据备份是很是友好的, 由于你能够在服务器运行的时候对 RDB 文件进行复制: RDB 文件一旦被建立, 就不会进行任何修改。 当服务器要建立一个新的 RDB 文件时, 它先将文件的内容保存在一个临时文件里面, 当临时文件写入完毕时, 程序才使用 rename(2) 原子地用临时文件替换原来的 RDB 文件。
这也就是说, 不管什么时候, 复制 RDB 文件都是绝对安全的。
如下是咱们的建议:
1,建立一个按期任务(cron job), 每小时将一个 RDB 文件备份到一个文件夹, 而且天天将一个 RDB 文件备份到另外一个文件夹。
2,确保快照的备份都带有相应的日期和时间信息, 每次执行按期任务脚本时, 使用 find 命令来删除过时的快照: 好比说, 你能够保留最近 48 小时内的每小时快照, 还能够保留最近一两个月的每日快照。
3,至少天天一次, 将 RDB 备份到你的数据中心以外, 或者至少是备份到你运行 Redis 服务器的物理机器以外。