Redis持久化
用一句话可以将持久化概括为:将数据(如内存中的对象)保存到可永久保存的存储设备中。持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、 XML 数据文件中等等。
Redis 为什么要持久化?
Redis 中的数据类型都支持 push/pop、add/remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,Redis 支持各种不同方式的排序。与 Memcached 一样,为了保证效率,数据都是缓存在内存中。
对,数据都是缓存在内存中的,当你重启系统或者关闭系统后,缓存在内存中的数据都会消失殆尽,再也找不回来了。所以,为了让数据能够长期保存,就要将 Redis 放在缓存中的数据做持久化存储。
Redis 怎么实现持久化?
在设计之初,Redis 就已经考虑到了这个问题。官方提供了多种不同级别的数据持久化的方式:
1、RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储。
2、AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。
3、如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式。
4、你也可以同时开启两种持久化方式, 在这种情况下, 当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
如果你不知道该选择哪一个级别的持久化方式,那我们就先来了解一下 AOF 方式和 RDB 方式有什么样的区别,并且它们各自有何优劣,学习完之后,再来考虑该选择哪一种级别。
RDB 方式与 AOF 方式的优势对比
RDB 方式的优点
- RDB
是一个非常紧凑的文件,它保存了某个时间点的数据集,非常适用于数据集的备份,比如你可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集。 - RDB 是一个紧凑的单一文件,很方便传送到另一个远端数据中心,非常适用于灾难恢复。
- RDB 在保存 RDB 文件时父进程唯一需要做的就是 fork 出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他 IO
操作,所以 RDB 持久化方式可以最大化 Redis 的性能。 - 与AOF相比,在恢复大的数据集的时候,RDB 方式会更快一些。
当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:
- Redis 调用forks. 同时拥有父进程和子进程。
- 子进程将数据集写入到一个临时 RDB 文件中。
- 当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益
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 执行之前的状态。
优点对比总结
RDB 方式可以保存过去一段时间内的数据,并且保存结果是一个单一的文件,可以将文件备份到其他服务器,并且在回复大量数据的时候,RDB 方式的速度会比 AOF 方式的回复速度要快。
AOF 方式默认每秒钟备份1次,频率很高,它的操作方式是以追加的方式记录日志而不是数据,并且它的重写过程是按顺序进行追加,所以它的文件内容非常容易读懂。可以在某些需要的时候打开 AOF 文件对其编辑,增加或删除某些记录,最后再执行恢复操作。
RDB 方式与 AOF 方式的缺点对比
RDB 方式的缺点
- 如果你希望在 Redis 意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么 RDB
不适合你.虽然你可以配置不同的save时间点(例如每隔 5 分钟并且对数据集有 100 个写的操作),是 Redis要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔5分钟或者更久做一次完整的保存,万一在 Redis意外宕机,你可能会丢失几分钟的数据。 - RDB 需要经常 fork 子进程来保存数据集到硬盘上,当数据集比较大的时候, fork 的过程是非常耗时的,可能会导致 Redis在一些毫秒级内不能响应客户端的请求。如果数据集巨大并且 CPU 性能不是很好的情况下,这种情况会持续1秒, AOF 也需要 fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度。
AOF 方式的缺点
- 对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。
- 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB可以提供更有保证的最大延迟时间(latency)。
缺点对比总结
RDB 由于备份频率不高,所以在回复数据的时候有可能丢失一小段时间的数据,而且在数据集比较大的时候有可能对毫秒级的请求产生影响。
AOF 的文件提及比较大,而且由于保存频率很高,所以整体的速度会比 RDB 慢一些,但是性能依旧很高。
RDB 方式持久化的开启与配置
Redis 默认的持久化方式是 RDB ,并且默认是打开的。RDB 的保存有方式分为主动保存与被动保存。
RDB的触发机制有三种:
- save(同步) 主动 当数据量大的时候会造成阻塞
- bgsave(异步) 主动
- 自动 被动
主动保存可以在 redis-cli 中输入 save或者bgsave 即可;被动保存需要满足配置文件中设定的触发条件,目前官方默认的触发条件可以在 redis.conf 中看到:
save 900 1
save 300 10
save 60 10000
其含义为:
900秒钟改变了1条数据,自动生成RDB
300秒钟改变了10条数据,自动生成RDB
60秒钟改变了10000条数据,自动生成RDB
3条中满足任意一条,都要去做生成RDB操作,生成RDB文件策略实际上是内部执行bgsave
触发保存条件后,会在指定的目录生成一个名为 dump.rdb 的文件,等到下一次启动 Redis 时,Redis 会去读取该目录下的 dump.rdb 文件,将里面的数据恢复到 Redis。
生成的规则我们不太好控制,因为无法控制写入数据量,所以RDB不是一种很好的方式。
这个目录生成的dump.rdb文件在哪里?
我们可以在客户端中输入命令config get dir查看:
关于RDB的其他配置
dbfilename dump.rdb # rdb文件叫什么名字
dir ./ # 文件目录
stop-writes-on-bgsave-error yes # 如果你的bgsave发生了错误是否停止写入
rdbcompression yes # rdb文件是否采用压缩的格式
rdbchecksum yes # 是否对rdb文件进行一个校验检验
如何关闭rdb
rdb是默认弃用的,如果你不需要使用它,可以在配置文件中将3个配置注释掉,并新增save ""即可
保存配置文件后需要重新启动 Redis 服务才会生效
save ""
# save 900 1
# save 300 10
# save 60 10000
RDB总结
- RDB是Redis内存到硬盘的快照,用于持久化
- save通常会阻塞Redis
- bgsave不会阻塞Redis,但是会fork新进程
- save自动配置满足任一就会被执行
- 总结出RDB耗时耗性能,不可控,容易丢失数据
AOF 方式持久化的开启与配置
默认是不开启 AOF 的,如果想要启用则需要到 redis.conf 配置文件中开启,打开 redis.conf, 然后在文件中找到 appendonly 并将 no 改为 yes:
appendonly yes
AOF 还有支持几种同步方式,它们分别是:
- appendfsync always # 每次有数据修改发生时都会写入AOF文件(安全但是费时)。
- appendfsync everysec # 每秒钟同步一次,该策略为AOF的缺省策略。(默认)
- appendfsync no # 从不同步。高效但是数据不会被持久化。
三种策略比较:
AOF重写
因为 AOF 持久化是通过保存被执行的写命令来记录数据库状态的,所以随着服务器运行时间的流逝,AOF 文件中的内容会原来越多,文件的体积也会越来越大,若不加以控制,体积过大的 AOF 文件很可能对 Redis 服务器、甚至整个宿主计算机造成影响,并且其体积越大,使用 AOF 文件来进行数据还原所需要的时间就越长。
为防止 aofrewrite 过程阻塞服务器,Redis 服务器会 fork 一个子进程执行该过程,且任何时刻只能有一个子进程做这件事。
aof重写的2种方式:
- bgrewriteaof
- AOF重写配置
BGREWRITEAOF
客户端对Redis的主进程发一条bgrewriteaof命令,他会异步的执行并返回OK,当Redis接收到这个命令之后,他会fork出一个子进程,来完成一个aof的重写,注意这里的aof重写实际上就是将Redis内存当中的数据进行一次回溯,回溯成aof文件
AOF重写配置
auto-aof-rewrite-min-size 64MB # AOF文件重写需要的尺寸 当AOF文件小于64MB的时候不进行AOF重写
auto-aof-rewrite-percentage 100 # AOF文件增长率 当前AOF文件比上次AOF重写后的文件大100%的时候进行AOF重写
可以在redis.conf配置文件中添加这两个参数来自动触发AOF重写,执行bgrewriteaof命令
统计:
aof_current_size # AOF当前尺寸 (单位:字节)
aof_base_size # AOF上次启动和重写的尺寸(单位:字节)
自动触发机制
- aof_current_size>auto-aof-rewrite-min-size
- aof_current_size - aof_base_size / aof_base_size > auto-aof-rewrite-percentage
AOF重写全部配置:
appendonly yes # 打开aof持久化
appendfilename "appendonly-${port}.aof" # aof文件名
appendfsync everysesc # 每秒执行aof操作
dir /bigdiskpath # aof文件存储路径
no-appendfsync-on-rewrite yes # aof重写时是否要做aof的append操作,yes是不做这个操作,aof重写是非常消耗性能的
auto-aof-rewrite-min-size 64MB
auto-aof-rewrite-percentage 100