Redis持久化

Posted 峰峰仔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis持久化相关的知识,希望对你有一定的参考价值。

Redis持久化

  • RDB持久化(以时间间隔做数据集的快照)
  • AOF持久化(记录服务接收到的每个写操作,当服务启动的时候,会再次执行这些写操作,是为了构造原来的数据集。当AOF文件变得很大时,Redis会以后端进程重写log)
  • 你也可以禁止持久化,如果你希望你的数据仅仅服务运行的时候存在
  • 你也可以在同一个实例中结合AOF和RDB,在这种情况下,当Redis重启的时候,AOF文件主要用来构造原来的数据集,因为AOF保证数据的完整性

RDB和AOF的对比

RDB的优点:

  • RDB是一个数据集的快照。RDB非常适合备份。例如,你想每个小时备份RDB文件。在这种情况下,当灾难发生时,你可以恢复数据集的不同版本
  • RDB非常适合灾难恢复
  • RDB最大化Redis性能,当需要持久化的时候,是父进程启动一个子进程,剩下的事情由子进程来说。
  • RDB对比AOF来说,伴随着大数据来说,能更快启动

RDB缺点:

  • 当Redis停止工作的时候,为了最小化数据的丢失,RDB并不是很好。通常你会设置每五分钟创建快照,当Redis非正常关闭的时候,这样你最多丢失五分钟的数据。
  • RDB为了持久化,需要fork(),但是如果数据集比较大的话,Fork()是消耗时间的。会导致Redis大概几百毫秒不能接收客户端的请求

AOF优点:

  • 使用AOF,Redis会更耐用,你可以选择不同的fsync策略:no fsync,  fsync every second, fsync at every  query。默认的策略是fsync every second,写性能也非常好,并且你最多丢失一秒的写数据。
  • 有可能AOF文件中包含写一半的命令,会导致Redis启动不起来,你可以使用redis-check-aof工具来解决这个问题
  • 当AOF文件变大的时候,Redis会自动重写AOF文件。并且重写也是非常安全的
  • AOF文件以一种容易理解好解析的格式的存储所有的操作。你可以导出AOF文件

AOF缺点:

  • 相同数据集来说,AOF比RDB更大
  • 如果选择精确的fsync策略,AOF比RDB更慢。通常设置为fsync every second的策略有很高的性能。如果禁止fsync,在高负载下,和RDB一样的快
  • 有一些操作,可能会导致不能恢复成原始数据,但是这种情况非常罕见。

我们应该选择哪一个?

通常,如果你想要更深度的数据安全,你应该同时使用这两种方法

如果你更多的关注数据,但是同时能够忍受几分钟数据的丢失,你可以仅仅使用RDB

但是有许多用户仅仅使用AOF,但是我们并不鼓励这样,因为RDB快照能够很好的做数据库备份,能够快速重启,能够避免AOF引擎的一些bugs

快照

默认Redis保存数据集的快照到磁盘上,以名叫dump.rdb的文件名保存。它是一个二进制文件,例如,如果每60秒,至少有1000个keys改变,那么让Redis自动执行快照

save 60 1000

工作流程:

当Redis需要做快照的时候,Redis forks,会有一个子进程和父进程。子进程开始写数据集到一个临时的RDB文件。当子进程完成后,新的文件会替换老的文件

Append-only file

快照并不是很耐用,如果你的计算机停止Redis运行或者你kill -9实例,最新写到Redis的数据会丢失。对一些应用来说,这并不是理想的选择。为了更好的耐用,你可以选择append-only file,在配置文件中

appendonly yes

当设置完成后,每一次修改数据集的操作将会添加到AOF中,当你重启Redis的时候,会重新应用AOF来构建数据集

Log重写

AOF会越来越大,例如,你修改一个key的值100次,你的数据集会存储最终的值,但是在AOF中会有100条记录,99条记录对于重构数据集是不需要的。

Redis支持一个特性:Redis会以守护进程重新构建AOF,而且并不会影响客户端的服务。当你执行BGREWRITEAOF,Redis会写最简短的命令,来构建数据集。如果Redis版本是2.2,你需要时常运行BGREWRITEAOF命令。Redis 2.4会自动触发log重写

append only file怎么耐用

你可以配置Redis同步数据到磁盘的频率,有3个不同的选择

  • fsync(每次都添加新的命令到AOF中,是非常慢的,但是非常安全)
  • fsync evry second(非常快,如果有灾难发生,你仅仅丢失一秒的数据)
  • Never fsync(仅仅放你的数据到内存,是非常快的,但是不安全)

推荐的策略是fsync every second,这也是默认的策略。因为它是相当快并且安全。always策略在实践中是非常慢的。

如果我的AOF文件损害了,我应该做什么?

当写AOF文件的时候,服务崩溃。这样使得Redis无法加载AOF文件。当这个发生的时候,你可以使用下面的流程来解决问题

  • 做一下你的AOF文件的备份
  • 使用redis-check-aof --fix来解决AOF文件的损害
  • 可选,使用diff -u来对比两个AOF文件的不同
  • 用修复后的AOF文件来启动服务

Log重写的工作流程

Log重写使用和快照一样的copy-on-write方式,下面是工作流程

  • Redis forks,我们会有子进程和父进程
  • 子进程会以临时文件的形式写新的AOF文件
  • 父进程积累新的改变到内存缓存中,但是同时一会添加新的改变到老的AOF文件中,如果我们重写失败了,那么我们是安全的。
  • 当子进程完成重写文件后,父进程得到通知,添加内存缓存中的内容到新的AOF文件中
  • Redis会命令命名老的AOF名字到新的文件名字,开始添加新的数据到新的文件

如果现在在使用dump.rdb快照,怎么切换成AOF?

Redis >= 2.2

  • 备份下最新的dump.rdb文件
  • 传输这个备份文件到安全的地方
  • 执行下面的命令
    redis-cli config set appendonly yes
    redis-cli config set save ""

Redis2.0

  • 备份下最新的dump.rdb文件
  • 传输备份文件到安全的地方
  • 停止所有对数据库的写操作
  • 执行redis-cli bgewriteaof命令,会创建一个appendonly文件
  • 当Redis完成AOF dump,停止redis服务。
  • 编辑redis.conf文件,开启append only file持久化
  • 重启Redis服务

AOF和RDB持久化的互动

Redis>2.4会避免当RDB快照正在执行的过程中,来触发AOF重写。当AOF重写正在执行的过程中,来执行BGSAVE。这样做是为了避免两个守护进程带来高强度的磁盘IO

当快照正在执行过程中,用户明确使用BGREWRITEAOF命令来请求log重写操作,服务会返回OK,但是只有当快照执行完成后,才开始执行log重写

当AOF和RDB持久化都开启的时候,Redis重启的时候,AOF文件用来构造数据集,来保证数据的完整性。

备份Redis数据

如果数据不备份,会导致数据的丢失。Redis有非常友好的数据备份。当数据库在运行的时候,你可以复制RDB文件。RDB文件只要生成,并不会修改了。这样意味着复制RDB文件是安全的。下面是我的建议:

  • 创建定时任务,在一个目录做每小时的快照,在另一个目录中做每天的快照
  • 当cron脚本在运行的时候,使用find命令确保老的快照已被删除。
  • 至少保证每天传输RDB快照到数据中心之外护着其他的物理主机

灾难恢复

类似于数据备份,通过传输RDB快照到其他的机器上,然后通过一些验证方法来验证数据的正确性。当数据丢失了,可以使用这些备份文件恢复。

 



以上是关于Redis持久化的主要内容,如果未能解决你的问题,请参考以下文章

Redis高级(持久化--redis主从架构--redis哨兵模式--redis分片集群)

Redis持久化

redis 之redis持久化rdb与aof

redis学习系列——redis持久化

Redis学习-4-2 Redis持久化

redis 的持久化策略有几种