Redis的持久化方式

redis的持久化

RDB

全程redis database backip file(Redis数据备份文件),也被叫做redis数据快照,简单来说就是把内存中所有数据都记录到磁盘中,

当redis实例故障重启后,从磁盘读取快照文件,恢复数据.

快照文件称为RDB文件,默认是保存在当前运行目录

  • save命令 有redis的主进程来执行RDB,会阻塞所有命令
  • bgsave开启子进程执行RDB,避免主进程受到影响

RDB的配置:

redis内部有触发RDB的机制,可以在redis.conf文件中找到,格式如下:

save 900 1 如果900秒内,如果至少一个key被修改,则执行bgsave,如果是save "" 则表示禁用redis

RDB的其它配置也可以在redis.conf文件中设置:

rdbcompression yes 是否压缩,建议不开启,压缩也会消耗cpu,磁盘的话不值钱

defilename dump.rdb rdb文件名称

dir ./ 文件保存的路径目录

AOF

AOF全称为APPend Only file(追加文件).redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件

AOF配置

AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF

appendonly yes

appendfilename "appendonly.aof"

AOF的命令记录的频率也是可以通过redis.conf文件来配

appendfsync always 表示每执行一次写命令,立刻记录到AOF文件

appednfsync everysec 写命令执行完先放入到AOF缓存区,然后表示每隔1m将缓冲区数据写到AOF文件,是默认方案

appednfsync no 写命令执行完先放入AOF缓存区,由操作系统决定何时将缓冲区内容写回磁盘

因为是记录命令,AOF文件会比RDB文件大的多,而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义,

通过执行bgrewriteaof命令,可以让AOF执行重写功能,用最少的命令达到相同的效果

不知道大家注意到没有,Redis 是先执行写操作命令后,才将该命令记录到 AOF 日志里的,这么做其实有两个好处。

第一个好处,避免额外的检查开销。

因为如果先将写操作命令记录到 AOF 日志里,再执行该命令的话,如果当前的命令语法有问题,那么如果不进行命令语法检查,该错误的命令记录到 AOF 日志里后,Redis 在使用日志恢复数据时,就可能会出错。

而如果先执行写操作命令再记录日志的话,只有在该命令执行成功后,才将命令记录到 AOF 日志里,这样就不用额外的检查开销,保证记录在 AOF 日志里的命令都是可执行并且正确的。

第二个好处,不会阻塞当前写操作命令的执行,因为当写操作命令执行成功后,才会将命令记录到 AOF 日志。

当然,AOF 持久化功能也不是没有潜在风险。

第一个风险,执行写操作命令和记录日志是两个过程,那当 Redis 在还没来得及将命令写入到硬盘时,服务器发生宕机了,这个数据就会有丢失的风险

第二个风险,前面说道,由于写操作命令执行成功后才记录到 AOF 日志,所以不会阻塞当前写操作命令的执行,但是可能会给「下一个」命令带来阻塞风险

AOF重写机制

如果当 AOF 日志文件过大就会带来性能问题,比如重启 Redis 后,需要读 AOF 文件的内容以恢复数据,如果文件过大,整个恢复的过程就会很慢。

所以,Redis 为了避免 AOF 文件越写越大,提供了 AOF 重写机制,当 AOF 文件的大小超过所设定的阈值后,Redis 就会启用 AOF 重写机制,来压缩 AOF 文件。

AOF 重写机制是在重写时,读取当前数据库中的所有键值对,然后将每一个键值对用一条命令记录到「新的 AOF 文件」,等到全部记录完后,就将新的 AOF 文件替换掉现有的 AOF 文件。

重写 AOF 的时候,不直接复用现有的 AOF 文件,而是先写到新的 AOF 文件再覆盖过去。

因为如果 AOF 重写过程中失败了,现有的 AOF 文件就会造成污染,可能无法用于恢复使用。

所以 AOF 重写过程,先重写到新的 AOF 文件,重写失败的话,就直接删除这个文件就好,不会对现有的 AOF 文件造成影响。

Redis 的重写 AOF 过程是由后台子进程 bgrewriteaof\来完成的,这么做可以达到两个好处:

  • 子进程进行 AOF 重写期间,主进程可以继续处理命令请求,从而避免阻塞主进程;
  • 子进程带有主进程的数据副本(数据副本怎么产生的后面会说),这里使用子进程而不是线程,因为如果是使用线程,多线程之间会共享内存,那么在修改共享内存数据的时候,需要通过加锁来保证数据的安全,而这样就会降低性能。而使用子进程,创建子进程时,父子进程是共享内存数据的,不过这个共享的内存只能以只读的方式,而当父子进程任意一方修改了该共享内存,就会发生「写时复制」,于是父子进程就有了独立的数据副本,就不用加锁来保证数据安全。

在重写工程中有两个地方会造成父进程阻塞

  • 创建子进程的途中,由于要复制父进程的页表等数据结构,阻塞的时间跟页表的大小有关,页表越大,阻塞的时间也越长;

  • 创建完子进程后,如果子进程或者父进程修改了共享数据,就会发生写时复制,这期间会拷贝物理内存,如果内存越大,自然阻塞的时间也越长;

AOF和RDB对比
相关推荐
BergerLee34 分钟前
对不经常变动的数据集合添加Redis缓存
数据库·redis·缓存
huapiaoy1 小时前
Redis中数据类型的使用(hash和list)
redis·算法·哈希算法
小徐敲java1 小时前
通用mybatis-plus查询封装(QueryGenerator)
mybatis
【D'accumulation】2 小时前
令牌主动失效机制范例(利用redis)注释分析
java·spring boot·redis·后端
Cikiss2 小时前
微服务实战——SpringCache 整合 Redis
java·redis·后端·微服务
wxin_VXbishe2 小时前
springboot合肥师范学院实习实训管理系统-计算机毕业设计源码31290
java·spring boot·python·spring·servlet·django·php
OEC小胖胖2 小时前
Spring Boot + MyBatis 项目中常用注解详解(万字长篇解读)
java·spring boot·后端·spring·mybatis·web
计算机学姐3 小时前
基于SpringBoot+Vue的在线投票系统
java·vue.js·spring boot·后端·学习·intellij-idea·mybatis
一休哥助手3 小时前
Redis 五种数据类型及底层数据结构详解
数据结构·数据库·redis
落落落sss3 小时前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis