redis持久化
一、概要
Redis主要提供了两种持久化机制,主要用于宕机或者重启后,redis的恢复工作
- RDB
- AOF
如果你没有数据持久化的需求,也可以完全关闭RDB和AOF方式,提高性能
二、RDB
1、概念
Redis DataBase 默认开启,会按照配置的指定时间将内存中的数据快照到磁盘中,创建一个dump.rdb文件,redis启动时再恢复到内存中。
2、工作过程
- redis会单独创建fork()一个子进程,
- 将当前父进程的数据库数据复制到子进程的内存中
- 然后由子进程将数据先写入临时文件
- 写入成功后,再替换之前的文件,
- 用二进制压缩存储。
- 然后子进程退出,内存释放
3、注意事项
- 每次快照持久化都会将主进程的数据库数据复制一遍,导致内存开销加倍
- 若此时内存不足,则会阻塞服务器运行,直到复制结束释放内存;
- 都会将内存数据完整写入磁盘一次,所以如果数据量大的话,
- 而且写操作频繁,必然会引起大量的磁盘I/O操作,严重影响性能,
- 并且最后一次持久化后的数据可能会丢失;
5、缺点
- 持久化粒度比较大,如果save, shutdown, slave 之前宕机或者重启了,则中间的操作没办法恢复
- fork的需要考虑内存的消耗
- fork过程比较耗时,可能会影响客服端访问
5、配置相关
redis.conf
save [seconds] [changes]
# 如果要禁用功能则使用:
save ""
# 如果在900秒内有1次改动(增删改),则保存到硬盘中
save 900 1
# 如果在300秒内有10次改动(增删改),则保存到硬盘中
save 300 10
save 60 10000
# 如果在60秒内有10000次改动(增删改),则保存到硬盘中
# 多个策略可以并用,可以配置多个save...
压缩配置
# 默认是开启 会造成cpu压力,不建议关闭
rdbcompression yes
自定义本地数据库文件
dbfilename dump.rdb
指定本地数据库存放目录
# 上面这个./是个变动的值,启动的命令在哪个路径,那么就是在哪个路径
dir ./
6、保存命令
# 当写入数据到硬盘出错,则停止保存到硬盘
stop-writes-on-bgsave-error yes
# 存储快照后,进行数据校验
rdchecksum yes
手动保存命令
# 阻塞操作,其他操作不能执行 因为redis是单线程 开发中不建议使用
save
# 后台异步执行保存快照操作
bgsave
查看快照命令
# 查看最后一次成功执行快照的时间
lastsave
三、AOF
1、概念
Append Only File,即只允许追加不允许改写的文件
将redis执行过的所有写指令记录在日志中,在下次redis重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了
2、AOF持久化策略
-
**AOF_FSYNC_NO **
每次都会把aof_buf中的内容写入到磁盘,但是不会调用fsync函数;
-
AOF_FSYNC_ALWAYS
每次都会把aof_buf中的内容写入到磁盘,同时调用fsync函数;
-
AOF_FSYNC_EVERYSEC
定期(至少1s)去调用fsync,并且该操作是放到一个异步队列中(线程)去执行,因此不会阻塞主进程
会丢失 1 秒钟的数据
说明
- AOF_FSYNC_ALWAYS 每次都写入文件都会调用fsync,所以这种flush策略可以保证数据的完整性,缺点就是性能太差(因为fysnc是个同步调用,会阻塞主进程对客户端请求的处理)
- AOF_FSYNC_NO 由于依赖于操作系统自动sync,因此不能保证数据的完整性
- AOF_FSYNC_EVERYSEC 折中方案 既能不过分降低系统的性能,又能最大程度上的保证数据的完整性
3、AOF重写
AOF 的工作过程是不断地将命令追加到文件的末尾, 但随着写入命令的不断增加, AOF 文件的体积也会变得越来越大。例如对商品的库存递减的操作时,可能恢复的时候我只需要最终的结果,但Redis会将递减的过程的命令也会记录下来 ,为了解决这种问题,redis提供了一种解决方法 **重建(rebuild) **。
执行 BGREWRITEAOF 命令, Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令
触发机制是当aof文件大小是上次重写后大小的一倍且文件大于64M时触发
4、工作过程
- 开始重写,redis会创建(fork)一个重写子进程,这个子进程会首先读取现有的AOF文件,并将其包含的指令进行分析压缩并写入到一个临时文件中。
- 与此同时,主工作进程会将新接收到的写指令一边累积到内存缓冲区中,一边继续写入到原有的AOF文件中,这样做是保证原有的AOF文件的可用性,避免在重写过程中出现意外。
- 当重写子进程完成重写工作后,它会给父进程发一个信号,父进程收到信号后就会将内存中缓存的写指令追加到新AOF文件中。
- 当追加结束后,redis就会用新AOF文件来代替旧AOF文件,之后再有新的写指令,就都会追加到新的AOF文件中了。
5、AOF文件出现了被写坏的情况
- 备份被写坏的AOF文件
- 运行redis-check-aof –fix进行修复
- 用diff -u来看下两个文件的差异,确认问题点
- 重启redis,加载修复后的AOF文件
四、两种方式的优缺点
-
RDB需要定时持久化,风险是可能会丢两次持久之间的数据,量可能很大。
-
AOF每秒fsync一次指令硬盘,如果硬盘IO慢,会阻塞父进程;风险是会丢失1秒多的数据;在Rewrite过程中,主进程把指令存到mem-buffer中,最后写盘时会阻塞主进程。
五、如何选择
没有最优的方案,只有合不合适 具体根据实际工作情况来定
- 一般来说,如果想尽可能的保证数据安全性, 你应该同时使用两种持久化功能并且官方也推荐我们这么做。
- 如果可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。
- AOF每秒fsync一次指令硬盘,如果硬盘IO慢,会阻塞父进程;风险是会丢失1秒多的数据;在Rewrite过程中,主进程把指令存到mem-buffer中,最后写盘时会阻塞主进程
六、备份与恢复
redis的备份和还原,可以借助第三方的工具redis-dump
1、备份
导出
# 导出命令
redis-dump –u 127.0.0.1:6379 > back_20191116.json
# 导出指定数据库数据
redis-dump -u 127.0.0.1:6379 -d 15 > back_20191116.json
# 如果redis设有密码
redis-dump –u :password@127.0.0.1:6379 > back_20191116.json
导入
< back_20191116.json redis-load
# 如果redis设有密码
< back_20191116.json redis-load -u :password@127.0.0.1:6379
2、恢复过程
当两种方式同时开启时
- 数据恢复redis会优先选择AOF恢复。
- 一般情况下,只要使用默认开启的RDB即可,因为相对于AOF,RDB便于进行数据库备份,并且恢复数据集的速度也要快很多