共计 5380 个字符,预计需要花费 14 分钟才能阅读完成。
Redis 中数据存储模式有 2 种:cache-only,persistence;
- cache-only 即只做为“缓存”服务,不持久数据,数据在服务终止后将消失,此模式下也将不存在“数据恢复”的手段,是一种安全性低 / 效率高 / 容易扩展的方式;
- persistence 即为内存中的数据持久备份到磁盘文件,在服务重启后可以恢复,此模式下数据相对安全。
对于 persistence 持久化存储,Redis 提供了两种持久化方法:
- Redis DataBase(简称 RDB)
- Append-only file (简称 AOF)
除了这两种方法,Redis 在早起的版本还存在虚拟内存的方法,现在已经被废弃。
一、RDB 概述
RDB 是在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。
优点:使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis 的高性能
缺点:RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候
这里说的这个执行数据写入到临时文件的时间点是可以通过配置来自己确定的,通过配置 redis 在 n 秒内如果超过 m 个 key 被修改 这执行一次 RDB 操作。这个操作就类似于在这个时间点来保存一次 Redis 的所有数据,一次快照数据。所有这个持久化方法也通常叫做 snapshots。
RDB 默认开启,redis.conf 中的具体配置参数如下;
#dbfilename:持久化数据存储在本地的文件
dbfilename dump.rdb
#dir:持久化数据存储在本地的路径,如果是在 /redis/redis-3.0.6/src 下启动的 redis-cli,则数据会存储在当前 src 目录下
dir ./
##snapshot 触发的时机,save <seconds> <changes>
## 如下为 900 秒后,至少有一个变更操作,才会 snapshot
## 对于此值的设置,需要谨慎,评估系统的变更操作密集程度
## 可以通过“save“””来关闭 snapshot 功能
#save 时间,以下分别表示更改了 1 个 key 时间隔 900s 进行持久化存储;更改了 10 个 key300s 进行存储;更改 10000 个 key60s 进行存储。
save 900 1
save 300 10
save 60 10000
## 当 snapshot 时出现错误无法继续时,是否阻塞客户端“变更操作”,“错误”可能因为磁盘已满 / 磁盘故障 /OS 级别异常等
stop-writes-on-bgsave-error yes
## 是否启用 rdb 文件压缩,默认为“yes”,压缩往往意味着“额外的 cpu 消耗”,同时也意味这较小的文件尺寸以及较短的网络传输时间
rdbcompression yes
snapshot 触发的时机,是有“间隔时间”和“变更次数”共同决定,同时符合 2 个条件才会触发 snapshot, 否则“变更次数”会被继续累加到下一个“间隔时间”上。snapshot 过程中并不阻塞客户端请求。snapshot 首先将数据写入临时文件,当成功结束后,将临时文件重名为 dump.rdb。
使用 RDB 恢复数据:
自动的持久化数据存储到 dump.rdb 后。实际只要重启 redis 服务即可完成(启动 redis 的 server 时会从 dump.rdb 中先同步数据)
客户端使用命令进行持久化 save 存储:
./redis-cli -h ip -p port save
./redis-cli -h ip -p port bgsave
一个是在前台进行存储,一个是在后台进行存储。我的 client 就在 server 这台服务器上,所以不需要连其他机器,直接./redis-cli bgsave。由于 redis 是用一个主线程来处理所有 client 的请求,这种方式会阻塞所有 client 请求。所以不推荐使用。另一点需要注意的是,每次快照持久化都是将内存数据完整写入到磁盘一次,并不是增量的只同步脏数据。如果数据量大的话,而且写操作比较多,必然会引起大量的磁盘 io 操作,可能会严重影响性能。
二、AOF 概述
Append-only file,将“操作 + 数据”以格式化指令的方式追加到操作日志文件的尾部,在 append 操作返回后 (已经写入到文件或者即将写入),才进行实际的数据变更,“日志文件”保存了历史所有的操作过程;当 server 需要数据恢复时,可以直接 replay 此日志文件,即可还原所有的操作过程。AOF 相对可靠,它和 MySQL 中 bin.log、apache.log、zookeeper 中 txn-log 简直异曲同工。AOF 文件内容是字符串,非常容易阅读和解析。
优点:可以保持更高的数据完整性,如果设置追加 file 的时间是 1s,如果 redis 发生故障,最多会丢失 1s 的数据;且如果日志写入不完整支持 redis-check-aof 来进行日志修复;AOF 文件没被 rewrite 之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的 flushall)。
缺点:AOF 文件比 RDB 文件大,且恢复速度慢。
我们可以简单的认为 AOF 就是日志文件,此文件只会记录“变更操作”(例如:set/del 等),如果 server 中持续的大量变更操作,将会导致 AOF 文件非常的庞大,意味着 server 失效后,数据恢复的过程将会很长;事实上,一条数据经过多次变更,将会产生多条 AOF 记录,其实只要保存当前的状态,历史的操作记录是可以抛弃的;因为 AOF 持久化模式还伴生了“AOF rewrite”。
AOF 的特性决定了它相对比较安全,如果你期望数据更少的丢失,那么可以采用 AOF 模式。如果 AOF 文件正在被写入时突然 server 失效,有可能导致文件的最后一次记录是不完整,你可以通过手工或者程序的方式去检测并修正不完整的记录,以便通过 aof 文件恢复能够正常;同时需要提醒,如果你的 redis 持久化手段中有 aof,那么在 server 故障失效后再次启动前,需要检测 aof 文件的完整性。
AOF 默认关闭,开启方法,修改配置文件 reds.conf:appendonly yes
## 此选项为 aof 功能的开关,默认为“no”,可以通过“yes”来开启 aof 功能
## 只有在“yes”下,aof 重写 / 文件同步等特性才会生效
appendonly yes
## 指定 aof 文件名称
appendfilename appendonly.aof
## 指定 aof 操作中文件同步策略,有三个合法值:always everysec no, 默认为 everysec
appendfsync everysec
## 在 aof-rewrite 期间,appendfsync 是否暂缓文件同步,"no" 表示“不暂缓”,“yes”表示“暂缓”,默认为“no”
no-appendfsync-on-rewrite no
##aof 文件 rewrite 触发的最小文件尺寸(mb,gb), 只有大于此 aof 文件大于此尺寸是才会触发 rewrite,默认“64mb”,建议“512mb”
auto-aof-rewrite-min-size 64mb
## 相对于“上一次”rewrite,本次 rewrite 触发时 aof 文件应该增长的百分比。
## 每一次 rewrite 之后,redis 都会记录下此时“新 aof”文件的大小 (例如 A),那么当 aof 文件增长到 A *(1 + p) 之后
## 触发下一次 rewrite,每一次 aof 记录的添加,都会检测当前 aof 文件的尺寸。
auto-aof-rewrite-percentage 100
AOF 是文件操作,对于变更操作比较密集的 server,那么必将造成磁盘 IO 的负荷加重;此外 linux 对文件操作采取了“延迟写入”手段,即并非每次 write 操作都会触发实际磁盘操作,而是进入了 buffer 中,当 buffer 数据达到阀值时触发实际写入(也有其他时机),这是 linux 对文件系统的优化,但是这却有可能带来隐患,如果 buffer 没有刷新到磁盘,此时物理机器失效(比如断电),那么有可能导致最后一条或者多条 aof 记录的丢失。通过上述配置文件,可以得知 redis 提供了 3 中 aof 记录同步选项:
- always:每一条 aof 记录都立即同步到文件,这是最安全的方式,也以为更多的磁盘操作和阻塞延迟,是 IO 开支较大。
- everysec:每秒同步一次,性能和安全都比较中庸的方式,也是 redis 推荐的方式。如果遇到物理服务器故障,有可能导致最近一秒内 aof 记录丢失(可能为部分丢失)。
- no:redis 并不直接调用文件同步,而是交给操作系统来处理,操作系统可以根据 buffer 填充情况 / 通道空闲时间等择机触发同步;这是一种普通的文件操作方式。性能较好,在物理服务器故障时,数据丢失量会因 OS 配置有关。
其实,我们可以选择的太少,everysec 是最佳的选择。如果你非常在意每个数据都极其可靠,建议你选择一款“关系性数据库”吧。
AOF 文件会不断增大,它的大小直接影响“故障恢复”的时间, 而且 AOF 文件中历史操作是可以丢弃的。AOF rewrite 操作就是“压缩”AOF 文件的过程,当然 redis 并没有采用“基于原 aof 文件”来重写的方式,而是采取了类似 snapshot 的方式:基于 copy-on-write,全量遍历内存中数据,然后逐个序列到 aof 文件中。因此 AOF rewrite 能够正确反应当前内存数据的状态,这正是我们所需要的;*rewrite 过程中,对于新的变更操作将仍然被写入到原 AOF 文件中,同时这些新的变更操作也会被 redis 收集起来 (buffer,copy-on-write 方式下,最极端的可能是所有的 key 都在此期间被修改,将会耗费 2 倍内存),当内存数据被全部写入到新的 aof 文件之后,收集的新的变更操作也将会一并追加到新的 aof���件中,此后将会重命名新的 aof 文件为 appendonly.aof, 此后所有的操作都将被写入新的 aof 文件。 如果在 rewrite 过程中,出现故障,将不会影响原 AOF 文件的正常工作,只有当 rewrite 完成之后才会切换文件,因为 rewrite 过程是比较可靠的。*
触发 rewrite 的时机可以通过配置文件来声明,同时 redis 中可以通过 bgrewriteaof 指令人工干预。
redis-cli -h ip -p port bgrewriteaof
因为 rewrite 操作 /aof 记录同步 /snapshot 都消耗磁盘 IO,redis 采取了“schedule”策略:无论是“人工干预”还是系统触发,snapshot 和 rewrite 需要逐个被执行。
AOF rewrite 过程并不阻塞客户端请求。系统会开启一个子进程来完成。
三. 总结:
AOF 和 RDB 各有优缺点,这是有它们各自的特点所决定:
- 1) AOF 更加安全,可以将数据更加及时的同步到文件中,但是 AOF 需要较多的磁盘 IO 开支,AOF 文件尺寸较大,文件内容恢复数度相对较慢。
*2) snapshot,安全性较差,它是“正常时期”数据备份以及 master-slave 数据同步的最佳手段,文件尺寸较小,恢复数度较快。
可以通过配置文件来指定它们中的一种,或者同时使用它们(不建议同时使用),或者全部禁用,在架构良好的环境中,master 通常使用 AOF,slave 使用 snapshot,主要原因是 master 需要首先确保数据完整性,它作为数据备份的第一选择;slave 提供只读服务(目前 slave 只能提供读取服务),它的主要目的就是快速响应客户端 read 请求;但是如果你的 redis 运行在网络稳定性差 / 物理环境糟糕情况下,建议你 master 和 slave 均采取 AOF,这个在 master 和 slave 角色切换时,可以减少“人工数据备份”/“人工引导数据恢复”的时间成本;如果你的环境一切非常良好,且服务需要接收密集性的 write 操作,那么建议 master 采取 snapshot,而 slave 采用 AOF。
下面关于 Redis 的文章您也可能喜欢,不妨参考下:
Ubuntu 14.04 下 Redis 安装及简单测试 http://www.linuxidc.com/Linux/2014-05/101544.htm
Redis 主从复制基本配置 http://www.linuxidc.com/Linux/2015-03/115610.htm
Redis 集群明细文档 http://www.linuxidc.com/Linux/2013-09/90118.htm
Redis 系列 - 安装部署维护篇 http://www.linuxidc.com/Linux/2012-12/75627.htm
CentOS 6.3 安装 Redis http://www.linuxidc.com/Linux/2012-12/75314.htm
Redis 安装部署学习笔记 http://www.linuxidc.com/Linux/2014-07/104306.htm
Redis 配置文件 redis.conf 详解 http://www.linuxidc.com/Linux/2013-11/92524.htm
Redis 的详细介绍:请点这里
Redis 的下载地址:请点这里
本文永久更新链接地址:http://www.linuxidc.com/Linux/2016-10/136352.htm