[TOC]
RDB和AOF
RDB (Redis DataBase)
在指定的时间间隔内将内存中的数据集快照写入磁盘
rdb文件以配置文件相关参数
配置文件redis.conf:
1 | dbfilename dump.rdb |
备份是如何执行的
Redis会单独创建(fork)一个子进程来进行持久化, 会先将数据写入到一个临时文件中, 待持久化过程都结束了, 在用这个临时文件替换上次持久化好的文件(写时复制技术), 整个过程中, 主进程是不进行任何IO操作的, 这就确保了极高的性能, 如果需要大规模的数据恢复, 且对于数据恢复的完整性不是非常敏感, 那RDB方式要比AOF方式更加的高效, RDB的缺点时最后一次持久化后的数据可能丢失.
使用RDB文件恢复数据
直接将rdb文件保存好即可, 需要恢复的时候把旧的替换了就行了.
优势
- 适合大规模的数据恢复
- 对数据库完整性和一致性要求不高更适合使用
- 节省磁盘空间
- 恢复速度快
劣势
- Fork的时候, 内存中的数据被克隆了一份, 大概2倍的膨胀需要考虑.
- 虽然使用了写时拷贝技术, 但是如果数据庞大的时候还是比较耗费性能.
- 周期性备份, 如果redis意外崩溃, 最后一次备份之后的数据会丢失.
AOF (Append Of File)
什么是AOF
以日志的形式来记录每个写操作, 不记录读操作, 只允许追加文件但不可以改写文件, redis启动之初就会读取该文件, 重新构建数据, 换言之, redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作.
AOF的持久化流程
- 客户端的请求写命令会被append追加到aof缓冲区中.
- aof缓冲区根据aof持久化策略将操作syc同步到磁盘的aof文件中.
- aof文件超过重写策略或手动重写时, 会对aof文件rewrite重写, 压缩aof文件容量.
- redis服务重启后, 重新加载aof文件.
AOF默认不开启
redis.conf:
1 | appendonly no |
AOF和RDB都开启, 听谁的?
Redis听AOF的.
没啥好说的.
如果aof损坏了, 就启动不了, 而不是转去使用rdb.
使用RDB文件恢复数据
和RDB一样, 直接把保存下来的aof文件, 直接放进指定的那个文件夹就可以了.(默认目录是启动目录, 前面有个参数写了可以改, 提醒一下), 重启生效.
异常恢复
如果在往aof文件追加时, aof坏了, 那么就要恢复它.
reids提供了一个命令:
1 | redis-check-aof --fix appendonly.aof |
AOF同步频率设置
1 | appendfsync always |
Rewrite 压缩
- 是什么?
AOF采用文件追加方式, 文件越来越大, 为了避免出现此种情况, 新增了重写机制, 当AOF文件大小超过阈值的时候, Redis就会启动AOF文件的内容压缩, 只保留可以恢复数据的最小指令集, 可以使用命令bgrewriteaof. - 如何实现?
AOF文件只需增长而过大时, 会fork出一条新进程来讲文件重写(也是先写临时文件最后再替换), redis40版本后的重写是指把rdb的快照, 以二进制的形式附在新的aof文件头部, 作为已有的历史数据, 替换掉原来的流水账操作.
比如:
把set k1 v1, set k2, v2两条命令合成set k1 v1 k2 v2.
- 触发条件
默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发.
1 | auto-aof-rewrite-percentage: 设置重写的基准值, 比例: 100% |
重写过程
- 触发重写, 判断是否有bgsave或bgwriteaof在运行, 如果有则等待它们结束后再执行.
- 主进程fork出子进程执行重写操作, 保证主进程不会阻塞.
- 子进程遍历redis内存中数据到临时文件, 客户端的写请求同时写入aof_buf缓冲区和aof_rewrite_buf重写缓冲区, 保证原aof文件完整以及新aof文件生成期间的新的数据修改动作不会丢失.
- 子进程写完新的aof文件后, 向主进程发信号, 父进程更新统计信息, 主进程把aof_rewrite_buf中的数据写入到新的aof文件.
- 使用新的aof文件替换旧的.
优势
- 备份机制更稳健, 丢失数据概率低
- 可读的日志文件, 通过操作AOF稳健, 可以处理误操作
劣势
- 相比RDB, 它不仅记录数据, 还要记录操作, 需要更多空间
- 恢复备份速度要慢
- 每次读写都同步的话, 有一定的性能压力
- 存在潜在bug, 导致一些问题
总结
用哪个好
官方推荐两个都启用.
对数据不敏感, 可以单独使用RDB
不单独使用AOF, 因为它仍有bug.
如果只是做纯内存缓存, 可以都不用.