闲聊Redis的持久化

前言

Redis4.0之前,持久化的方式分为两种,即为rdbaof,在4.0之后对于持久化方式进行了优化,可以将两种方式混合使用,即混合持久化方式


提示:以下是本篇文章正文内容,如有过错望指出,一起学习

一、RDB快照

在默认情况下, Redis 将内存数据库快照保存在名字为 dump.rdb 的二进制文件中。 你可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次 数据集。 比如说, 以下设置会让 Redis 在满足“ 900秒内有至少有 1 个键被改动”这一条件时, 自动保存一次

#save 900 1 //关闭RDB只需要将所有的save保存策略注释掉即可或者在最后加上save " "

还可以手动执行命令生成RDB快照,进入redis客户端执行命令SAVE或BGSAVE可以生成dump.rdb文件, 每次命令执行都会将所有redis内存快照到一个新的rdb文件里,并覆盖原有rdb快照文件。

我们先看下RDB常用的相关的配置

# save [seconds] [changes] 表示在[seconds]秒内有[changes]个键值的变化则进行持久化。可同时配置多个,满足一个条件则触发。
save 900 1				#在900秒内有1次键值变化则进行持久化。
save 300 10				#在300秒内有10次键值变化则进行持久化。
save 60 10000			#在60秒内有10000次键值变化则进行持久化。

stop-writes-on-bgsave-error yes		#当持久化出现错误时,是否停止数据写入,默认停止数据写入。可配置为no,当持久化出现错误时,仍然能继续写入缓存数据。正常情况下只有磁盘空间不足,写入权限不够或者说fork子进程的时候内存不够才会出现持久化错误

rdbcompression yes		#是否压缩数据,默认压缩。可配置为no,不压缩。rdb文件默认为压缩的二进制的文件

rdbchecksum yes			#对持久化rdb文件是否进行校验,默认校验。可配置为no,不校验。

dbfilename dump.rdb		#指定rdb保存到本地的文件名。

dir ./					#指定rdb保存的目录,默认在本目录下,即redis的安装目录。

RDB持久化的两种方法

  1. SAVE:是同步操作,在持久化的过程中会阻塞redis的其他命令导致服务器无法处理客户端发来的命令请求,此命令正常不会使用

  2. BGSAVE:采用写时复制(cow,即Copy-On-Write)的机制,在生成快照的同时,依然可以处理客户端的请求。简单来说就是,主进程fork一个子进程,共享主进程的所有内存数据。然后读取主进程的内存数据并写入RDB文件

RDB的缺点:

  • RDB模式持久化时是保存的整个数据集的快照,如果频率太频繁会对Redis的性能造成影响(fork子进程时其实主进程会阻塞的,因为时间很短所以没有什么感知,如果太频繁而且数据集很多则会影响体验)。如果设置的时间太长,把在持久化被触发之前宕机就会丢失未持久化的数据
  • RDB默认的持久化是BGSAVE方式,此方法如果主进程对这些数据也是读操作,那么主进程和fork的子进程互不影响。但是如果子进程在持久化的时候,主进程对数据进行了修改,那么这块数据就会被复制一份,生成该数据的副本,然后子进程会把这个副本数据写入 RDB 文 件。极端情况下所有的数据都要修改,那么所有数据都要复制一份,内存达到以前的两倍,非常消耗资源

RDB的优点:

  • RDB文件是进行压缩后的二进制文件,保存的是某个时间点的数据集,很适合用于备份,手动时间点备份后可以随时还原回不同的版本
  • RDB持久化时只需要fork一个子进程,不影响主进程的任何I/O操作,所以性能很高
  • RDB文件保存的都是二进制数据集,恢复速度比AOF快

二、AOF同步

Redis会将所有的写操作的命令记录到appendonly.aof文件中,先追加写操作到aof缓冲区(aof_buf),然后根据持久化策略写入操作系统的页缓存(page cache),最后再落盘(fsync / fdatasync),即分为命令追加、文件写入、文件同步三个步骤。

看下AOF常用的配置

appendonly no			#是否开起AOF持久化,默认关闭,yes打开。

appendfilename "appendonly.aof"			#AOF持久化数据的文件名。

appendfsync everysec		#执行AOF持久化的频率,默认“每秒执行一次同步”。还有“always”选项,表示每个redis命令都要同步写入硬盘,但是这样会严重减低redis的速度。还有“no”选项,此时持久化的时机将有操作系统决定。redis建议如果你不知道怎么做,就使用“everysec”配置。

no-appendfsync-on-rewrite no		#默认不重写AOF文件。不开启文件会原来越大占用很多磁盘空间

#下面这两个配置是用于AOF“重写”触发条件。当AOF文件的体积大于64m,且AOF文件的体积比上一次重写之后的体积至少打了一倍(100%)则执行重新命令。
auto-aof-rewrite-percentage 100		
auto-aof-rewrite-min-size 64mb	

aof-load-truncated yes			#指redis在恢复时,会忽略最后一条可能存在问题的指令,默认值yes。

为什么需要进行AOF重写?

由于AOF文件记录的是写操作的命令,所以这个文件随着时间会越来越到导致磁盘大量浪费导致空间不足,所以需要在不打断客户端的情况下对于文件进行重新的构建。

AOF重写

Redis 生成新的 AOF 文件来代替旧 AOF 文件,这个新的 AOF 文件包含重建当前数据集所需的最少命令。具体过程是遍历所有数据库的所有键,从数据库读取键现在的值,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令。比如先前的文件中有一个key进行了100次INCR操作,那么重建的文件只需通过set命令保存当前值即可,数据一致但是省了很多空间。

重写规则由下面两个参数指定。
当AOF文件的体积大于64m,且AOF文件的体积比上一次重写之后的体积至少打了一倍(100%)则执行重新命令。可自行修改
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

触发AOF的方法也是两种,REWRITEAOF和BGREWRITEAOF,区别和上面的RDB类似,这里就不细说了。

Redis如何解决重写过程中主线程继续修改数据可能会导致数据不一致的问题的?

Redis引入了AOF重写缓冲区(aof_rewrite_buf_blocks),当进行重写时fork了子进程之后,每当服务器接收到写命令之后就会将这个命令同时添加到AOF缓冲区和AOF重写缓冲区。这样即便在重写过程中发生宕机等问题,也不影响现有的AOF文件。当子进程完成AOF重写之后,父进程会将AOF重写缓冲区的内容写入到新的AOF文件中,写完之后会重新命名并且原子的对原文件进行替换。注意:AOF重写缓冲区的内容写入到新的AOF文件由于是主进程写入的,所以如果内容过多的话会产生阻塞,影响性能。所以Redis对这部分也进行了优化,在进行AOF后台重写时,Redis会创建一组用于父子进程间通信的管道,同时会新增一个文件事件,该文件事件会将写入 AOF 重写缓冲区的内容通过该管道发送到子进程。在重写结束后,子进程会通过该管道尽量从父进程读取更多的数据,每次等待可读取事件1ms,如果一直能读取到数据,则这个过程最多执行1000次,也就是1秒。如果连续20次没有读取到数据,则结束这个过程。

AOF的缺点:

  • 对于相同的数据集,AOF 文件的大小一般会比 RDB 文件大。数据量大的时候恢复的速度也比RDB慢
  • 正常使用中推荐每秒保存一次,所以说性能比不上RDB

AOF的优点:

  • 对于发生事故的时候,对于数据的完成性的保存要比RDB安全的多
  • AOF文件保存的是命令集合,所以文件能看懂

三、RDB和AOF混合持久化

重启 Redis 时,我们很少使用 RDB来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF日志性能相对RDB来说要慢很多,这样在Redis实例很大的情况下,启动需要花费很长的时间。Redis4.0为了解决这个问题,带来了一个新的持久化选项——混合持久化。混合持久化并不是一种全新的持久化方式,而是对已有方式的优化。混合持久化只发生于 AOF 重写过程。使用了混合持久化,重写后的新 AOF 文件前半段是 RDB 格式的全量数据,后半段是 AOF 格式的增量数据。

使用时需要先开启AOF持久化然后再开启如下配置:

aof‐use‐rdb‐preamble yes

在进行重写时,fork的子进程先将当前这一刻的数据进行RDB快照放进AOF文件,然后再进行AOF方式的命令追加,所以文件的前半段是压缩的二进制数据,后半段才是能看懂的命令。

我们看下具体的文件变化

先设置一个key的值

在这里插入图片描述

然后查看AOF文件

在这里插入图片描述

注:AOF文件内容的说明
这是一种resp协议格式数据,*后面的数字代表命令有多少个参数,$号后面的数字代表这个参数有几个字符

如果是执行带过期时间的set命令,比如set yueyue 24 ex 1000,他其实是分成了两部分,先设置key,然后再通过PEXPIREAT设置过期时间

我们通过命令让AOF文件进行重写然后再设置新的key

在这里插入图片描述


再次查看文件内容,可以看到前半段内容已经看不懂,只能看懂后半段了

在这里插入图片描述


总结

以上即为简单的对于Redis的持久化的理解,个人水平有限,若有不足之处请指出一起探索,感谢阅读~

相关文章

学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习...
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面...
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生...
Can’t connect to local MySQL server through socket \'/v...
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 ...
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服...