Redis—持久化

持久化

首先明确为什么需要持久化?

  1. Redis 是一个基于内存的服务器。服务一旦宕机,内存中的数据将全部丢失,通常解决办法是把后端的数据库中恢复这些数据,给数据库造成巨大的压力
  2. 数据库的性能不如Redis。导致程序响应慢。所以对于Redis来说,实现数据的持久化,避免从后端数据库中恢复数据是非常重要的

RDB

Redis DataBase的缩写,中文名为快照/内存快照,RDB持久化就是把当前进程数据生成快照保存到磁盘上的过程,那么快照的值要早于内存中的值

触发方式

1、 手动触发:

  • save命令:阻塞当前Redis服务器,直到RDB过程完成为止,对于内存比较大的实例会造成长时间的阻塞,线上环境不建议使用
  • bgsave命令:Redis进程执行fork操作创建子进程,持久化过程由子进程负责,完成后自动结束,时间很短

具体流程:redis客户端执行命令 -> 主进程判断是否存在当前进行的子进程,如果存在就返回 -> 如果不存在正在执行的,那么就fork一个新的子进程进行持久化数据,fork进程是阻塞的,fork操作完成后主进程即可执行其他操作 ->子进程先将数据写入到临时的rdb文件中,待快照写入完成后再替换旧的数据 -> 同时发送信号给主线程,通知主线程rdb完成,主线程更新相关的统计信息

2、自动触发:

  • redis.conf中配置save m n,即在m秒内有n次修改时,自动触发bgsave生成rdb文件
  • 默认情况下,执行shutdown命令时,如果没有开启aof持久化,也会触发bgsave命令
  • 执行debug reload命令重新加载redis时也会触发bgsave命令
  • 主从复制时,从节点要从主节点进行全量复制时也会触发bgsave操作,生成当时的快照发送到从节点

RDB优缺点

  • 优点:
    • RDB文件是某个时间节点的快照,默认使用LZF算法进行压缩,压缩后的文件体积远远小于内存体积,适用于备份、全量复制等场景
    • Redis加载RDB文件恢复数据 远远快于 AOF方式
  • 缺点:
    • RDB方式实时性不够,无法做到秒级的持久化 (最主要)
    • 每次调用bgsave命令都要需要fork子进程,频繁执行成本较高
    • RDB文件是二进制的,没有可读性,还有版本兼容问题

AOF

Append-Only Filed的缩写,代表追加日志,Redis先执行命令,把数据写入内存,然后才记录日志。日志里记录的是Redis收到的每一条命令,这些命令大多数以文本方式保存 注:redis是写后日志,mysql等其他常见数据库是写前日志,通过写前日志和两阶段提交实现数据逻辑一致性

这里有个问题:为什么mysql是写后日志,redis是写前日志?因为不同数据库的侧重特性不同,mysql侧重持久化和一致性,redis强调高性能和低延迟的写入

写后日志的好处:

  • 避免额外的检查开销:Redis在向AOF里面写入记录日志的时候,并不会先去对这些命令进行语法检查。所以,如果先记日记在执行命令,日志中很可能有错误的命令,Redis使用日志恢复的时候还需要检查
  • 不会阻塞当前的操作

潜在风险:

  • 命令执行完,写日志之前宕机,会丢失数据
  • 主线程写磁盘压力大,导致写盘慢,阻塞后续操作

如果重写日志时,有新数据写入咋办?

当主线程正在执行 AOF 日志的写入操作时,如果有新的请求到达,Redis 会将这些新请求添加到一个待处理的请求队列中,等待主线程完成当前的写操作后再进行处理。

当有AOF重写期间,有新的数据写入时,Redis会将这些操作记录添加到AOF缓冲区,如果该数据被修改多次,则只会保留最后的修改记录。待AOF重写完成后,缓冲区的数据会按照固定的顺序执行追加到AOF文件中,保证了文件的一致性和完整性。

写缓冲区的动作是主线程,后续重写日志动作是主线程fork的线程完成

混合版本:

Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法。简单来说,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。

这样一来,快照不用很频繁地执行,这就避免了频繁 fork 对主线程的影响。而且,AOF 日志也只用记录两次快照间的操作,也就是说,不需要记录所有操作了,因此,就不会出现文件过大的情况了,也可以避免重写开销。

用 AOF 日志记录,等到第二次做全量快照时,就可以清空 AOF 日志,因为此时的修改都已经记录到快照中了,恢复时就不再用日志了

这个方法既能享受到 RDB 文件快速恢复的好处,又能享受到 AOF 只记录操作命令的简单优势, 实际环境中用的很多

恢复数据的过程:

  • 先判断是否开启aof,如果开启就优先加载aof文件;
  • 如果aof存在,那么就去aof文件失败,那么会打印日志表示失败,此时可以去修复aof文件后重新启动
  • 若aof文件不存在,那么redis就会转去加载rdb文件,如果rdb文件存在就加载进来,加载失败也会提示启动失败,如加载成功,那么redis启动成功,如果没有rbd文件,也会启动redis启动成功

那么为什么会优先加载AOF呢?因为AOF保存的数据更完整,通过上面的分析我们知道AOF基本上最多损失1s的数据

相关推荐
【D'accumulation】3 分钟前
令牌主动失效机制范例(利用redis)注释分析
java·spring boot·redis·后端
Cikiss21 分钟前
微服务实战——SpringCache 整合 Redis
java·redis·后端·微服务
一休哥助手1 小时前
Redis 五种数据类型及底层数据结构详解
数据结构·数据库·redis
盒马盒马2 小时前
Redis:zset类型
数据库·redis
Jay_fearless4 小时前
Redis SpringBoot项目学习
spring boot·redis
Wang's Blog4 小时前
Redis: 集群环境搭建,集群状态检查,分析主从日志,查看集群信息
数据库·redis
wclass-zhengge10 小时前
Redis篇(最佳实践)(持续更新迭代)
redis·缓存·bootstrap
Dylanioucn10 小时前
【分布式微服务云原生】探索Redis:数据结构的艺术与科学
数据结构·redis·分布式·缓存·中间件
Code成立10 小时前
1、深入理解Redis线程模型
数据库·redis·bootstrap
千年死缓20 小时前
go+redis基于tcp实现聊天室
redis·tcp/ip·golang