Redis是现在最流行的内存数据库和缓存系统性能很高被广泛用于缓存会话存储消息队列排行榜等等场景。

但是,因为Redis的数据存在内存里一旦进程退出或服务器宕机数据就会丢失这对于把Redis当数据库用的场景是不可接受的。所以Redis提供了持久化机制能把内存中的数据保存到磁盘上重启后能恢复数据。

我在工作中大量使用Redis踩了很多持久化的坑也积累了一些经验。

今天想总结一下Redis持久化的最佳实践包括RDBAOF混合持久化的原理优缺点配置以及,常见的坑和注意事项帮大家更好地使用Redis持久化保证数据安全。

一、Redis持久化简介

在讲最佳实践之前,先简单介绍一下Redis的持久化机制。

Redis提供了三种持久化方式:

  1. RDB(Redis Database):快照方式在指定的时候,间间隔把内存中的数据生成快照保存到磁盘上文件后缀是.rdb。
  2. AOF(Append Only File):追加日志方式把每个写命令追加到AOF文件末尾重启的时候,重新执行AOF文件里的命令恢复数据文件后缀是.aof。
  3. 混合持久化:Redis 4.0以后支持混合持久化结合了RDB和AOF的优点AOF重写的时候,把当前数据以RDB格式保存到AOF文件开头后续的写命令还是以AOF格式追加重启的时候,先加载RDB部分再执行AOF部分恢复数据更快更安全。

这三种方式各有优缺点需要根据实际场景选择。

二、RDB持久化

先详细说说RDB持久化。

原理

RDB是快照方式在指定的条件下Redis会fork一个子进程子进程把内存中的数据写入临时RDB文件写完后替换旧的RDB文件完成一次快照。

RDB文件是压缩的二进制格式体积小保存了某个时间点的完整数据。

触发方式

RDB有两种触发方式:

  1. 自动触发:在redis.conf里配置save规则,比如save 900 1表示900秒内有1个key变化就触发RDB快照。能配置多条规则满足任意一条就触发。
  2. 手动触发:执行savebgsave命令手动触发RDB快照。save是阻塞的会阻塞Redis主进程直到快照完成不建议在生产环境用。bgsave是后台执行fork子进程做快照不阻塞主进程推荐用。

优点

  1. 文件体积小:RDB文件是压缩的二进制格式体积小适合备份和传输。
  2. 恢复速度快:RDB是数据快照恢复的时候,直接加载RDB文件就能恢复数据速度很快比AOF快很多。
  3. 对性能影响小:RDB用fork子进程做快照主进程只需要fork不用做磁盘IO对性能影响小。
  4. 适合备份:RDB文件体积小适合定时备份,比如每小时备份一次能恢复到不,同时间点的数据。

缺点

  1. 数据丢失风险大:RDB是间隔触发的,如果Redis在两次快照之间,宕机就会丢失这期间的所有数据。比如配置5分钟一次快照宕机前4分钟的数据就丢了。
  2. fork耗时:RDB需要fork子进程,如果数据量大fork的时候,会耗时可能导致Redis短暂阻塞特别是内存大的时候fork可能需要几百毫秒甚至几秒影响性能。
  3. 数据量大时恢复慢:虽然RDB恢复比AOF快,但是,如果数据量很大几个G甚至几十G恢复也需要一定的时间不是秒级。

配置建议

# RDB自动触发规则根据实际场景调整
save 900 1
save 300 10
save 60 10000

# RDB文件名
dbfilename dump.rdb

# RDB文件保存目录
dir /data/redis

# 是否压缩RDB文件建议开启节省磁盘空间
rdbcompression yes

# 是否校验RDB文件建议开启防止文件损坏
rdbchecksum yes

# bgsave出错时是否停止写建议yes防止数据不一致
stop-writes-on-bgsave-error yes

三、AOF持久化

再说说AOF持久化。

原理

AOF是追加日志方式Redis执行每个写命令后把命令追加到AOF缓冲区,然后根据配置的刷盘策略把缓冲区的内容刷到AOF文件末尾。

重启的时候Redis重新执行AOF文件里的所有写命令恢复数据。

因为AOF文件会越来越大,所以Redis提供了AOF重写机制能压缩AOF文件去掉无用的命令,比如对同一个key的多次写只保留最后一次减少文件体积。

刷盘策略

AOF有三种刷盘策略用appendfsync配置:

  1. always:每个写命令都立即刷到磁盘最安全,但是性能最差,因为每个命令都要做磁盘IO。
  2. everysec:每秒刷一次盘平衡安全和,性能最多丢失1秒的数据是默认配置推荐用。
  3. no:不主动刷盘由操作系统决定什么时候刷盘性能最好,但是最不安全可能丢失较多数据。

AOF重写

AOF重写能压缩AOF文件有两种触发方式:

  1. 自动触发:配置auto-aof-rewrite-percentageauto-aof-rewrite-min-size当AOF文件大小比上次重写后增长了指定的百分比且超过最小大小就自动触发重写。
  2. 手动触发:执行bgrewriteaof命令手动触发AOF重写。

AOF重写也是fork子进程做不阻塞主进程子进程把当前内存中的数据生成写命令写入新的AOF文件写完后替换旧的AOF文件。

优点

  1. 数据安全:AOF能做到最多丢失1秒的数据(everysec策略)甚至不丢失(always策略)比RDB安全很多。
  2. 文件可读性好:AOF文件是文本格式保存的是Redis命令能直接打开查看和修改,比如误删了数据能修改AOF文件去掉删的命令恢复数据。
  3. 自动重写:AOF能自动重写压缩文件体积不会无限增长。
  4. 恢复可靠:AOF是命令日志恢复的时候,重新执行命令不容易出错比RDB更可靠RDB如果文件损坏可能整个都恢复不了。

缺点

  1. 文件体积大:AOF文件是文本格式保存的是命令比RDB的二进制压缩格式体积大很多。
  2. 恢复速度慢:AOF恢复需要重新执行所有命令数据量大的时候,恢复很慢比RDB慢很多。
  3. 性能影响大:AOF需要把每个写命令追加到文件刷盘对性能有一定的影响特别是,always策略性能下降明显。
  4. 可能有bug:AOF是记录命令可能会有一些命令记录不全或错误导致恢复的数据不一致,虽然很少见,但是有风险。

配置建议

# 开启AOF
appendonly yes

# AOF文件名
appendfilename "appendonly.aof"

# 刷盘策略推荐everysec平衡安全和性能
appendfsync everysec

# AOF重写期间是否停止刷盘建议no保证数据安全
no-appendfsync-on-rewrite no

# 自动重写触发百分比AOF文件比上次重写后增长100%触发
auto-aof-rewrite-percentage 100

# 自动重写最小大小AOF文件超过64mb才触发重写
auto-aof-rewrite-min-size 64mb

# AOF文件损坏时是否加载建议yes加载尽可能多的数据
aof-load-truncated yes

# 是否开启混合持久化Redis 4.0+支持建议开启
aof-use-rdb-preamble yes

四、混合持久化

混合持久化是Redis 4.0以后新增的功能结合了RDB和,AOF的优点推荐开启。

原理

开启混合持久化后AOF重写的时候,不再把所有数据都生成写命令而是把重写之前,的数据以RDB格式保存到AOF文件开头重写之后,的写命令还是以AOF格式追加到文件末尾。

所以AOF文件前半部分是RDB格式的快照后半部分是AOF格式的增量命令。

重启的时候Redis先识别AOF文件开头是不是RDB格式,如果是先加载RDB部分快速恢复大部分数据,然后再执行后半部分的AOF命令恢复增量数据。

优点

  1. 恢复速度快:前半部分是RDB格式加载快后半部分是,增量命令量少执行快整体恢复速度比纯AOF快很多接近RDB。
  2. 数据安全:后半部分是AOF增量命令能保证数据安全最多丢失1秒的数据比纯RDB安全。
  3. 文件体积小:前半部分是RDB压缩格式体积小后半部分是,增量命令量少整体文件体积比纯AOF小。

缺点

  1. 兼容性差:混合持久化的AOF文件前半部分是,RDB格式不能直接用文本编辑器查看可读性比纯AOF差。
  2. 需要Redis 4.0+:混合持久化是Redis 4.0以后才支持的老版本不支持。

配置建议

# 开启混合持久化
aof-use-rdb-preamble yes

只要开启了AOF和这个配置就能用混合持久化推荐Redis 4.0+都开启。

五、如何选择持久化方式

说了这么多到底该怎么选择持久化方式呢?

根据不同的场景有不同的建议:

场景1:纯缓存允许数据丢失

如果Redis只是当缓存用数据都是从数据库加载的丢了也能从数据库恢复,那么可以不用持久化,或者只用RDB做备份就行不用AOF性能最好。

建议:关闭持久化或只开RDB不用AOF。

场景2:缓存但希望快速恢复

如果Redis当缓存用,但是希望重启后能快速恢复缓存避免缓存击穿,那么用RDB就行RDB恢复快体积小适合这种场景。

建议:只用RDB不用AOF配置合适的save规则。

场景3:数据库要求数据安全

如果把Redis当数据库用数据很重要不能丢失,那么必须用AOF保证数据安全建议用混合持久化兼顾安全和恢复速度。

建议:开启AOF + 混合持久化appendfsync everysec。

场景4:数据库要求极高数据安全

如果数据非常重要一点都不能丢,那么用AOFalways策略每个命令都刷盘最安全,但是性能会下降需要评估性能是否能接受。

建议:开启AOFappendfsync always同时也开RDB做备份。

通用建议

大部分场景推荐RDB + AOF + 混合持久化一起用RDB做冷备份AOF保证数据安全混合持久化提高恢复速度兼顾各方面。

虽然,同时开RDB和AOF会有一定的性能开销,但是对于大部分场景这点开销是值得的能保证数据安全也能快速恢复。

六、常见的坑和注意事项

在使用Redis持久化的过程中我踩了很多坑总结一下常见的坑和注意事项。

坑1:fork导致的阻塞

RDB和AOF重写都需要fork子进程,如果Redis数据量大内存占用高fork的时候,会耗时可能导致Redis短暂阻塞几百毫秒甚至几秒这期间Redis不能处理请求会影响业务。

特别是在虚拟机或容器里fork可能更慢,因为内存管理的问题。

避免方法:

  1. 合理配置RDB和AOF重写的触发时机不要太频繁也不要在业务高峰触发。
  2. 控制Redis的内存大小不要太大一般建议单实例不超过20-30G太大的话fork慢恢复也慢。
  3. 开启disable-thp关闭透明大页能减少fork的耗时。
  4. 用物理机或配置好的虚拟机避免在超售严重的虚拟机里跑大内存Redis。

坑2:AOF文件越来越大

如果AOF重写配置不合理AOF文件可能会越来越大占用大量磁盘空间也会导致恢复慢。

避免方法:

  1. 合理配置auto-aof-rewrite-percentageauto-aof-rewrite-min-size让AOF能及时重写压缩。
  2. 定期检查AOF文件大小过大的话,手动执行bgrewriteaof触发重写。
  3. 开启混合持久化能减小AOF文件体积。

坑3:持久化文件损坏

如果Redis宕机的时候,正好在写RDB或AOF文件可能会导致文件损坏重启的时候,加载失败数据恢复不了。

避免方法:

  1. 开启rdbchecksum校验RDB文件能发现损坏。
  2. 开启aof-load-truncatedAOF文件损坏的时候,加载尽可能多的数据不要整个都不加载。
  3. 定期备份RDB和AOF文件到其他服务器或对象存储万一本地文件损坏能用备份恢复。
  4. 用主从复制主节点挂了能切换到从节点数据不丢。

坑4:磁盘IO瓶颈

持久化需要大量的磁盘IO特别是AOF刷盘和RDB写文件,如果磁盘性能差会导致Redis性能下降甚至阻塞。

避免方法:

  1. 用性能好的磁盘,比如SSD不要用机械硬盘跑高写入的Redis。
  2. 把RDB和AOF文件保存到独立的磁盘不要和系统或其他高IO应用共用磁盘。
  3. 合理配置持久化策略不要太频繁减少磁盘IO。
  4. 监控磁盘IO使用率和延迟发现瓶颈及时处理。

坑5:主从切换后持久化配置不一致

主从复制的场景主节点挂了切换到从节点后,如果从节点的持久化配置和主节点不一致可能会导致数据丢失或恢复问题。

避免方法:

  1. 主从节点的持久化配置保持一致都开RDB和AOF。
  2. 从节点也要做持久化不要只主节点做,否则主节点挂了从节点没有持久化文件重启数据就丢了。
  3. 切换后检查新主节点的持久化是否正常工作。

坑6:恢复时没有关闭持久化

恢复大数据量的Redis的时候,如果开着AOF恢复过程中会不断写AOF文件影响恢复速度也占用磁盘空间。

避免方法:

  1. 恢复的时候,先关闭AOF用RDB恢复数据恢复完成后再开启AOF触发一次重写生成新的AOF文件。
  2. 或者用混合持久化恢复速度也比较快。

七、备份和恢复策略

除了持久化还要有完善的备份和恢复策略保证数据安全。

备份策略

  1. 定时备份RDB文件:每天或每小时备份RDB文件到其他服务器或对象存储,比如S3OSS等等保留多个版本能恢复到不,同时间点。
  2. 备份AOF文件:如果用AOF也要定期备份AOF文件,但是AOF文件大变化快可以用增量备份或只备份重写后的AOF文件。
  3. 跨机房备份:重要的数据要跨机房备份防止一个机房出问题数据全丢。
  4. 加密备份:备份文件要加密防止数据泄露。
  5. 定期验证备份:定期用备份文件恢复测试确保备份文件是好的能正常恢复不要等到需要恢复的时候,才发现备份坏了。

恢复策略

  1. 优先用AOF恢复:如果有AOF文件优先用AOF恢复数据更完整更安全。
  2. AOF损坏用RDB恢复:如果AOF文件损坏加载失败用RDB文件恢复,虽然可能丢一些数据,但是能恢复大部分。
  3. 用备份恢复:如果本地的RDB和AOF都损坏用备份的文件恢复。
  4. 恢复后验证:恢复完成后要验证数据是否正确,比如检查key的数量重要的key的值等等确保数据完整。
  5. 恢复后开启持久化:恢复完成后要开启RDB和,AOF持久化保证后续数据安全。

八、监控和运维

持久化的监控和运维也很重要要及时发现问题处理。

监控指标

  1. rdblastsave_time:上次RDB保存时间判断RDB是否正常工作。
  2. rdblastbgsave_status:上次bgsave状态ok还是err失败的话,要及时处理。
  3. rdblastbgsavetimesec:上次bgsave耗时判断fork和写文件是否正常。
  4. aof_enabled:AOF是否开启。
  5. aoflastwrite_status:AOF上次写状态ok还是err。
  6. aoflastbgrewrite_status:AOF上次重写状态。
  7. aofcurrentsize:当前AOF文件大小判断是否过大需要重写。
  8. aofbufferlength:AOF缓冲区大小判断刷盘是否正常。
  9. fork耗时:监控fork的耗时判断是否有阻塞风险。
  10. 磁盘IO:监控磁盘使用率和延迟判断是否有IO瓶颈。

运维建议

  1. 定期检查持久化文件:每天检查RDB和,AOF文件是否正常生成大小是否合理。
  2. 定期做恢复演练:每季度或每半年做一次恢复演练用备份文件恢复测试确保能正常恢复。
  3. 升级Redis版本:及时升级Redis版本新版本会修复持久化相关的bug提高稳定性。
  4. 配置合理的内存策略:配置maxmemorymaxmemory-policy防止Redis内存用满导致OOM影响持久化。
  5. 主从+哨兵/集群:重要的业务用主从+哨兵或集群保证高可用主节点挂了能自动切换数据不丢。

九、写在最后

以上就是Redis持久化的最佳实践和经验总结。

Redis的持久化是保证数据安全的重要机制,但是也不是万能的需要根据实际场景选择合适的持久化方式合理配置还要有完善的备份和恢复策略监控和运维才能真正保证数据安全。

大部分场景推荐RDB + AOF + 混合持久化一起用兼顾数据安全恢复速度和,性能是比较通用的最佳实践。

当然具体的配置还要根据自己的业务场景数据量性能要求等等调整没有万能的配置,只有最适合自己的配置。

希望我的经验能帮大家更好地使用Redis持久化少踩坑保证数据安全。

如果有什么问题,或者更好的经验欢迎在评论区留言我们一起交流。

最后用一句话结束这篇文章:"持久化不是万能的,但是没有持久化是万万不能的。"

愿大家的Redis都能稳定运行数据安全不丢。