这是我参与更文挑战的第3天,活动详情查看:更文挑战
前言
Redis的数据都存放在内存中,如果没有配置持久化,redis重启后数据就全丢失了,那肯定不能让珍贵的数据因为这种外力而丢失,所以需要开启redis的持久化功能,将数据保存到磁盘上,当redis重启后,可以从磁盘中恢复数据。
这篇文章,从三个方面给大家一个比较直观的Redis持久化
- Redis的
持久化方式有哪几种 - Redis的
数据恢复步骤有哪些? - 企业中Redis的
持久化策略应该怎么选择?
下面就从Redis持久化的方式开始吧!!!!
Redis持久化的方式
redis提供两种方式进行持久化:
- 一种是RDB持久化(将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化)
- 另外一种是AOF持久化(将Reids的操作日志以追加的方式写入文件)。
RDB快照(snapshot)
在默认的情况下,redis将内存数据库快照保存在名为dump.rdb的二进制文件中
生成dump.rdb文件的条件
自动触发
可以在redis.conf文件中设置,让它在N秒时间内至少有M个改动这一条件被满足时,自动保存一次,条件策略如下图所示:
例如:save 60 10000:意味着只要在60秒内至少有10000个操作,redis就会自动保存一次
可以添加多条策略,只要符合其中一条,redis就会自动保存一次,关闭RDB只需要将所有的save保存策略注释掉就可以了
手动执行
进入redis的客户端执行save命令或bgsave命令可以生成dump.rdb文件,每次执行都会将所有redis的内存快照到一个新的rdb文件中,并覆盖原有rdb快照文件
例如:已存的dump.rdb文件的创建时间是20:19
执行一下save命令:
发现已存的dump.rdb文件的创建时间是当前时间,说明已经覆盖
dump.rdb的路径
dump.rdb的生成路径可以自行设置,在redis.conf配置文件设置,位置如下图所示
dump.rdb的文件名
dump.rdb的文件名可以自行设置,在redis.conf配置文件设置,位置如下图所示
同步or异步的生成dump.rdb文件
像上文中的save命令在生成dump.rdb文件的过程是同步的,也就是说在生成文件的过程中,会阻塞其他的redis命令执行,如果redis的内存越大,耗时越长,所以redis提供了一个bgsave的写时复制(copy-on-write)机制,在生成快照的同时,依然可以正常处理命令。
Reids主线程fork生成的子进程,共享主进程的所有内存数据,子进程写入到文件中。
此时,如果主线程对这些数据也都是读操作,那么主线程和子进程互不影响。如果主线程对数据中有修改操作,那么这些数据会被复制一份,生成该数据的副本。然后,主线程直接修改副本,bgsave在的子进程还是基于原先共享的内存数据写入到rdb文件中。
自动生成rdb文件后台使用的是bgsave方式
save和bgsave的对比
AOF(append-only file)
rdb这种方式有很严重的缺陷:如果Redis宕机了,那么服务器将丢失最近写入,且没有保存到快照中的那些命令。所以Redis增加了另外一种持久化方式:AOF,记录操作记录,然后重放操作,但是AOF文件只会记录修改数据的命令
开启AOF
可以在redis.conf文件中设置,把appendonly no修改成 appendonly yes,如下图所示:
AOF生成的文件名
AOF的策略
AOF支持三种策略:
appendonly always:每次有新命令追加到AOF文件时就执行一次fsync,非常慢,也非常安全appendfsync everysec:每秒执行一次fsync,足够快,并且在故障时只会丢失1sappendfsync no:从不fsync,将数据交给操作系统来处理。更快,也更不安全的选择
推荐也是默认的措施是appendfsync everysec,兼容速度和安全性
测试AOF
- 第一步:在redis中随便输入几个命令
- 第二步:等待1s后观察有没有生产AOF文件
- 第三步:使用
cat命令查看AOF文件,发现命令已经追加到AOF文件中
- 第四步:分析AOF文件
Redis的协议规范是 Redis Serialization Protocol (Redis序列化协议),AOF文件遵循这个协议,我们来举个set name miludexiaoguangtou例子来初步分析一下:
*3:aof文件记录每一个命令都是以*开始,3表示这个命令有几个参数,例如:set name miludexiaoguangtou就是3个参数,set、name和miludexiaoguangtou$3:$3意思就是下方的set有3个字符$4:$4意思就是下方的name有4个字符$18:$18意思就是下方的miludexiaoguangtou有18个字符
AOF的重写
AOF的文件里面可能有太多重复的、没用的指令。所以Redis支持定期根据内存的最新数据生产AOF文件,例如:执行了如下几条指令
重写后AOF文件里,后面的4条incr命令变成:
*3
$3
SET
$2
count
$1
4
在redis.conf配置文件中还可以对AOF重写的频率配置
// aof文件自上一次重写后文件大小增长了100%则再次触发
auto-aof-rewrite-percentage 100
// aof文件至少达到64mb才会自动重写,文件太小恢复速度本来就很快,重写的意义不大
auto-aof-rewrite-min-size 64mb
AOF文件还支持手动重写,进入redis客户端,执行bgrewriteaof重写AOF
重写Redis会fork出一个子进程去做 (与bgsave命令类似),不会对正常命令处理有太多影响
RDB和AOF如何选择
| 命令 | RDB | AOF |
|---|---|---|
| 启动优先级 | 低 | 高 |
| 体积 | 低 | 大 |
| 恢复速度 | 快 | 慢 |
| 数据安全性 | 容易丢数据 | 根据策略决定 |
生产环境可以都启用,redis启动时如果既有rdb文件,又有aof文件,则优先选择aof文件恢复数据,因为aof一般来说数据更安全一点
混合持久化(Redis 4.0)
重启Redis时,很少使用RDB来恢复内存状态,因为会丢失大量的数据。通常使用AOF日志重放,但是重放AOF日志性能相对RDB来说会慢很多,这样在Redis实例很大的情况下,启动需要花费很长时间
Redis 4.0为了解决这个问题,带来了一个新的持久化方式-混合持久化
开启持久化配置(必须先开启AOF)
如果开启了混合持久化,AOF在重写时,不再是单纯的将内存数据转换为RESP命令,写入到AOF文件中,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF命令存在一起,都写入新的AOF文件中。
新的AOF文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,覆盖原有的AOF文件,完成新旧两个AOF文件的替换
所以总体上来看,在Redis启动的时候,先加载RDB格式的内存数据,然后再重放增量AOF日志就可以完全替代之前的AOF全量文件重放,因此重启的效率会大大提高
举例:混合持久化
手动执行AOF重写命令,发现已经将这一刻之前的内存做RDB快照处理,并写入到新的AOF文件中。
写入两个增量的Redis命令后,发现直接追加在AOF文件最后
混合持久化AOF文件的格式
上面是RDB的二进制格式 (那一刻的内存压缩数据),后面是AOF命令的格式 (增量的命令)
Redis的数据恢复
截止目前只讲了Redis的持久化,并且会生成RDB和AOF两种格式的文件,但是如何恢复没说,下面就开始根据案例一步步讲如何恢复Redis的数据
- 第一步:先把redis关了,
模拟宕机的情况
- 第二步:把rdb文件和aof文件命名改了,先看下
什么持久化文件都不存在的情况
- 第三步:启动redis,观察里面的数据,发现
什么key都不存在
- 第四步:由于
redis关闭的时候会自动执行一次持久化,所以我们把新生产的aof文件删了
- 第五步:把原先的aof文件和rdb的
文件命名恢复
- 第六步:重新启动redis,观察数据,发现已经aof文件中的数据
已经加载到redis中
Redis持久化的策略
- 写crontab定时调度脚本,每小时都copy一份rdb或者aof的备份到一个目录中去,仅仅保留最近48小时的备份
- 写crontab定时调度脚本,每天都保留一份当日的数据备份到一个目录中去,可以保留最近一个月的备份
- 每次copy备份的时候,可以把之前太旧的备份记录给删了
- 每天晚上将当前机器上的备份复制一份到其他机器上,以防机器损坏 (多地备份)
总结
这篇文章,从三个方面给大家一个比较直观的Redis持久化
- Redis的
持久化方式有哪几种 - Redis的
数据恢复步骤有哪些? - 企业中Redis的
持久化策略应该怎么选择?
相信现在大家对Redis的持久化都有一个比较清晰的感受,现在赶快行动,去找你们的运维聊聊,看看各自所在的企业中用的是哪种持久化策略,为什么要这么设置,有没有更好的方案?
往期推荐
从零开始学Redis系列(二)| Redis常用命令如何在企业中重拳出击
絮叨
最后,如果感到文章有哪里困惑的,请第一时间留下评论,如果各位看官觉得小沙弥我有点东西的话 求点赞👍 求关注❤️ 求分享👥 ,因为这将是我输出更多优质文章的动力,感谢!!!
如果想获取Redis相关书籍,可以关注微信公众号Java百科全书,输入Redis,即可获得
最后感谢各位看官的支持,我们下期再见!