redis
作为我们经常使用的工具之一,熟悉它的特性还是很有必要的,这次写这篇文章也是在这方面吃了点亏, 我在参加某计算机考试时,有道题询问了这方面知识,原题我也记不大清楚了,我当时答的不是很好,感觉这种题丢分很不应该,所以写下文章,方便自我反省。
首先就是在开发中这个缓存应该是十分常用的,但是作为开发可能对于一些细节并没有很多的了解,毕竟业务压身,身不由己,有时候过来看看还是因为要面试,实在是惭愧,这篇文章我们先对 AOF
RDB
做了一个回顾,然后从几个方面进行说明对比,分析他们的优缺点,选择合适的持久化方式。
从前两篇文章我们知道了 AOF
和 RDB
持久化的一些细节,忘了的可以再去看看哦!我们再来对比一下,什么环境选择什么持久化方式比较好?首先我们对两种持久化方式的过程进行回顾
AOF
持久化是类似 Mysql
的 binlog
日志,记录所有的修改操作,所有客户端发送的命令都以 Redis命令协议
格式进行追加保存, 为了保证文件大小的适当, Redis
还在后台对 AOF
文件进行子进程创建重写,使得 AOF
文件体积不会超出保存数据集状态所需的实际大写,并在服务器启动时,通过执行这些命令来还原数据集,要注意, Redis会优先使用 AOF
文件来还原数据, 因为 AOF
文本保存的数据集一般比 RDB
所保存的数据集更完整,并且 存储的文件一般也比 RDB
的文件大。
RDB
持久化是在指定的时间间隔内生成数据集的时间点快照,当满足配置文件里面的条件时,父进程在保存 RDB
文件时唯一要做的就是 fork 出一个子进程, 然后子进程就会处理接下来所有的工作父进程无须执行任何磁盘 I/O
操作,在保存 Redis
里面的数据集时,它会利用 lzf算法 进行字符压缩,来保证文件大小适当,RDB
在恢复大数据集时的速度比 AOF
的恢复速度要快,它不需要一条一条指令执行。
在 RDB
和 AOF
的写入上就有不同的特点,一个是追加写入,一个是保存整个数据集,从这两个操作的数据量上面就可以看出, RDB
在进行写入的时候不能太频繁了,要控制好频率,还有一个就是每次 fork
一个子进程,同时也阻塞命令的执行,虽然 fork
创建的子进程不需要拷贝父进程的物理内存空间,但是会复制父进程的空间内存页表。例如对于 10GB
的 Redis
进程,需要复制大约 20MB
的内存页表,因此 fork
操作耗时跟进程总内存量息息相关。对于高流量的 Redis
实例 OPS
可达5万以上,如果 fork
操作耗时在秒级别将拖慢 Redis
几万条命令执行,对线上应用延迟影响非常明显。正常情况下 fork
耗时应该是每 GB
消耗 20毫秒
左右。可以在info stats
统计中查 latest_fork_usec
指标获取最近一次 fork
操作耗时,单位微秒。
RDB
是一个紧凑压缩的二进制文件,代表 Redis
在某个时间点上的数据快照。非常适用于备份,全量复制等场景。比如每6小时执行 bgsave
备份,并把RDB
文件拷贝到远程机器或者文件系统中(如hdfs),用于灾难恢复。Redis
加载RDB
恢复数据远远快于AOF
的方式。RDB
方式数据没办法做到实时持久化/秒级持久化。因为 bgsave
每次运行都要执行 fork
操作创建子进程,属于重量级操作,频繁执行成本过高。RDB
文件使用特定二进制格式保存, Redis
版本演进过程中有多个格式的RDB
版本,存在老版本 Redis
服务无法兼容新版RDB
格式的问题。RDB
不适合实时持久化的问题, Redis
提供了AOF
持久化方式来解决。fsync
策略,可以较好地保证数据的完整性flushall
命令,只要 AOF
文件没有被重写,移除尾部 flushall
命令,重启就可以恢复之前的状态fsync
策略会降低性能(这属于一个权衡点)RBD
稍大如果 redis
里面存储的数据比较重要,你应该同时使用两种持久化功能。如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB
持久化。
有很多用户都只使用 AOF
持久化, 但我们并不推荐这种方式: 因为定时生成 RDB
快照(snapshot)
非常便于进行数据库备份, 并且 RDB
恢复数据集的速度也要比 AOF
恢复的速度要快, 除此之外,可还可以避免一些 AOF
的 BUG
。