Redis系列(五)Redis持久化机制

Redis持久化

为什么需要持久化

Redis的数据是存放在内存的,如果每次关闭或者机器断电,那么我们的数据就丢失了。

解决这个问题的方式就是持久化,把redis内存的数据同步到磁盘。然后我们Redis启动的时候,由于一开始内存中没有数据,需要从磁盘中加载数据,然后基于内存去操作。

这样就既能满足基于内存的操作,保证性能,同时,也能尽可能的防止数据丢失。

  • 持久化方式:
    • RDB
    • AOF
    • RDB+AOF

RDB

概念

  • RDB(Redis DataBase,快照):在某个时间段,把当前内存的所有数据写入磁盘,生成一个磁盘文件。是redis默认的持久化方案。

  • 其中生成的磁盘文件的路径和文件名都是可配置的,配置项如下。

//生成的快照文件名
dbfilename dump.rdb
//快照文件保存的路径
dir ./

//开启数据压缩(默认开启),如果关闭,会导致.rdb文件变得很大
rdbcompression yes

触发条件(什么时候触发?)

自动触发
  1. 配置触发
# save ""
save 900 1		//900s检查一次,如果有一个key被修改,就会触发
save 300 10		//300s检查一次,如果有10个key被修改,就会触发
save 60 10000	//60s检查一次,如果有1000key被修改,就会触发

如果不想用RDB,可以把 save “” 的注释打开,下面三个注释。

  1. shutdown,服务正常关闭。redis关闭的时候,关闭之前肯定是要保存当前数据快照的。

  2. flushall,指令触发

flushall:清空数据的指令,执行的时候redis会生成一个空的RDB文件。

手动触发
  1. save 主线程去进行备份,阻塞其他指令。之所以阻塞其他指令,是为了保证数据一致性。
  2. bgsave 子线程去进行备份,不会阻塞其他指令。所以数据可能不是最新的。

通过RDB文件恢复数据

将dump.rdb 文件拷贝到redis的安装目录的bin目录下,重启redis服务即可。在实际开发中,一般会考虑到物理机硬盘损坏情况,选择备份dump.rdb 。

优势

  1. 生成的rdb文件是一个非常紧凑的文件,所以很适合远程传输、备份和灾难恢复。
  2. RDB最大限度地提升了redis的性能,redis父进程只需要fork一个子进程去执行rdb,父进程可以正常执行业务指令,不会产生磁盘
    IO或者类似的操作。
  3. 相比于AOF,RDB的重启速度更快。

简单总结一句话,RDB恢复与备份都非常的快。

不足

  1. 安全性很低,可能会有数据丢失。假如每5分钟备份一次,断电宕机后会有5分钟的数据丢失。
  2. 经常fork子进程,所以比较耗CPU,对CPU不是很友好(对CPU要求高)。

AOF

概念

AOF(Append Only File):采用日志的形式记录redis的每一个写操作,并追加到日志文件中。默认是关闭的,如果开启了的话,在数据恢复时,会用AOF做数据恢复。redis会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

配置文件

appendonly no
//追加的文件名
appendfilename "appendonly.aof"

同步机制

这里有个问题:如果每次指令都需要追加的话,那每次指令都需要和磁盘做IO,这样redis的性能会很低。为了解决这个问题,redis提供了更新日志的条件:

# appendfsync always	//每次指令操作都将新指令附加到AOF中,非常非常慢,非常安全。
appendfsync everysec	//1s异步同步数据,可能会丢失1s的数据
# appendfsync no		//不同步数据,由操作系统同步,更快,更不安全。linux一般是30s

重写机制

AOF有个问题:随着时间的推移,写入的命令越来越多,相应的aof的日志文件越来越大,文件中冗余内容会越来越多。如果redis再重启或做数据恢复,加载数据会很慢。

为了解决上述问题,redis新增了重写机制。当AOF文件的大小超过所设定的阈值时,Redis就会对AOF文件的内容压缩。

重写过程
  1. redis会fork出一个子进程,从内存数据库中读取当前的键和值,然后用一条命令去记录键值对,代替之前记录该键值对的多个命令。

  2. 创建一个新的AOF文件,将记录键值对的命令写入。这里会进行大量的写操作,直接用主进程执行的话会造成长时间的阻塞。所以这个操作是子进程在后台执行的。这样的好处是:

    • 子进程进行AOF重写期间,主进程可以继续处理命令请求。
  3. 子进程进行AOF重写的时候,服务器进程还要继续处理命令请求,而新的命令可能对现有的数据进行修改,这会让当前数据库的数据和重写后的AOF文件中的数据不一致。

    • 为了解决这个问题,Redis增加了一个AOF重写缓存,这个缓存在fork出子进程之后开始启用,Redis服务器主进程在执行完写命令之后,会同时将这个写命令追加到AOF缓冲区AOF重写缓冲区
    • 此时,子进程在执行AOF重写时,主进程需要执行以下三个工作:
      • 执行client发来的命令请求;
      • 将写命令追加到现有的AOF缓冲区中,然后定期同步到现有的AOF文件中;
      • 将写命令追加到AOF重写缓冲区中。
  4. 当子进程完成对AOF文件重写之后,它会向父进程发送一个完成信号,父进程接到该完成信号之后,执行如下操作:

    • 将AOF重写缓冲区的内容全部写入到新的AOF文件中,此时新的AOF文件中的数据状态和当前redis数据库的状态一致。
    • 对新的AOF文件进行改名,原子的覆盖原有的AOF文件;完成新旧两个AOF文件的替换。
重写触发条件(什么时候重写?)

重写触发条件由如下参数配置。

auto-aof-rewrite-percentage 100		//下次重写必须是上次重写后大小的2倍
auto-aof-rewrite-min-size 64mb		//文件达到64M后重写

aof文件大于64mb并且文件大小是上次重写后的2倍的时候触发重写。举个例子:

  • aof 文件小于64mb的时候不进行重写,当到达64mb的时候,就重写一次。
  • 假如重写后的 aof 文件是40mb,那要aof 文件到了80mb的时候,才会进行下一次重写。

优势

  1. 安全性很高,默认情况下,最多只会导致1s的数据丢失
  2. AOF日志文件可读性高。
  3. 如果失败,能修复。

不足

  1. 数据集一般比RDB的大,所以数据恢复比较慢,但在4.0以后,这个问题缓解了很多。
  2. 占用更多的内存。因为在重写的时候,新的指令会分别放在aof缓冲区和aof重写缓冲区,会导致消耗大量的内存。
  3. 重写期间,新进的指令会跟磁盘进行2次IO,一个是写入老的AOF文件,一个是写入新的AOF文件。

实际应用

实际使用中,RDB和AOF是同时开启的。

参考资料

  • 《咕泡云课堂》

  • 官网

https://redis.io/docs/manual/persistence/

  • redis持久化

https://www.cnblogs.com/itdragon/p/7906481.html

  • aof重写机制

https://blog.csdn.net/hezhiqiang1314/article/details/69396887

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值