Redis持久化 | 黑马Redis高级篇

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录

RDB持久化

1、介绍

2、命令

3、配置

4、bgsave的fork底层原理

5、总结

AOF持久化

1、介绍

2、开启

3、三种写回策略

4、AOF后台重写

混合持久化

总结


Redisd的持久化有两种方式分别是RDBAOF

RDB持久化

1、介绍

RDBRedis数据备份文件也叫Redis数据快照。就是把内存中的所有数据都记录到磁盘中当redis实例故障重启后从磁盘读取快照文件恢复数据。

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

2、命令

Redis 提供了两个命令来生成 RDB 文件分别是 save 和 bgsave他们的区别就在于是否在「主线程」里执行

  • 执行了 save 命令就会在主线程生成 RDB 文件由于和执行操作命令在同一个线程所以如果写入 RDB 文件的时间太长会阻塞主线程
  • 执行了 bgsave 命令会创建一个子进程来生成 RDB 文件这样可以避免主线程的阻塞

Redis停机时会执行一次RDB

RDB 文件的加载工作是在服务器启动时自动执行的Redis 并没有提供专门用于加载 RDB 文件的命令。

3、配置

Redis 还可以通过配置文件的选项来实现每隔一段时间自动执行一次 bgsave 命令默认会提供以下配置

save 900 1
save 300 10
save 60 10000

别看选项名叫 save实际上执行的是 bgsave 命令也就是会创建子进程来生成 RDB 快照文件。

4、bgsave的fork底层原理

bgsave开始时会fork主进程得到子进程紫金锤共享主进程的内存数据。完成fork后读取内存数据并写入RDB文件fork采用的是copy-on-wirte技术

执行 bgsave 命令的时候会通过 fork() 创建子进程此时子进程和父进程是共享同一片内存数据的因为创建子进程的时候会复制父进程的页表但是页表指向的物理内存还是一个。

当主进程执行读操作访问共享内存

当主进程执行写操作则会拷贝一份数据执行写操作只有在发生修改内存数据的情况时物理内存才会被复制一份。

图片

但是如果主线程父进程要修改共享数据里的某一块数据比如键值对 A时就会发生写时复制于是这块数据的物理内存就会被复制一份键值对 A'然后主线程在这个数据副本键值对 A'进行修改操作。与此同时bgsave 子进程可以继续把原来的数据键值对 A写入到 RDB 文件

发生了写时复制后RDB 快照保存的是原本的内存数据

注意

在 Redis 执行 RDB 持久化期间刚 fork 时主进程和子进程共享同一物理内存但是途中主进程处理了写操作修改了共享内存于是当前被修改的数据的物理内存就会被复制一份。

那么极端情况下如果所有的共享内存都被修改则此时的内存占用是原先的 2 倍。

所以针对写操作多的场景我们要留意下快照过程中内存的变化防止内存被占满了。

5、总结

这里提一点Redis 的快照是全量快照也就是说每次执行快照都是把内存中的「所有数据」都记录到磁盘中。

所以可以认为执行快照是一个比较重的操作如果频率太频繁可能会对 Redis 性能产生影响。如果频率太低服务器故障时丢失的数据会更多。

通常可能设置至少 5 分钟才保存一次快照这时如果 Redis 出现宕机等情况则意味着最多可能丢失 5 分钟数据。

这就是 RDB 快照的缺点在服务器发生故障时丢失的数据会比 AOF 持久化的方式更多因为 RDB 快照是全量快照的方式因此执行的频率不能太频繁否则会影响 Redis 性能而 AOF 日志可以以秒级的方式记录操作命令所以丢失的数据就相对更少。

AOF持久化

1、介绍

AOF称为追加文件redis处理的每个写命令都会记录在AOF文件可以看做是命令日志文件。

注意只会记录写操作命令读操作命令是不会被记录的

2、开启

默认是开启RDB快照方式我们要用AOF需手动开启

3、三种写回策略

  • Always这个单词的意思是「总是」所以它的意思是每次写操作命令执行完后同步将 AOF 日志数据写回硬盘
  • Everysec这个单词的意思是「每秒」所以它的意思是每次写操作命令执行完后先将命令写入到 AOF 文件的内核缓冲区然后每隔一秒将缓冲区里的内容写回到硬盘默认
  • No意味着不由 Redis 控制写回硬盘的时机转交给操作系统控制写回的时机也就是每次写操作命令执行完后先将命令写入到 AOF 文件的内核缓冲区再由操作系统决定何时将缓冲区内容写回硬盘。

三种的选择

  • Always 策略的话可以最大程度保证数据不丢失但是由于它每执行一条写操作命令就同步将 AOF 内容写回硬盘所以是不可避免会影响主进程的性能
  • No 策略的话是交由操作系统来决定何时将 AOF 日志内容写回硬盘相比于 Always 策略性能较好但是操作系统写回硬盘的时机是不可预知的如果 AOF 日志内容没有写回硬盘一旦服务器宕机就会丢失不定数量的数据。
  • Everysec 策略的话是折中的一种方式避免了 Always 策略的性能开销也比 No 策略更能避免数据丢失当然如果上一秒的写操作命令日志没有写回到硬盘发生了宕机这一秒内的数据自然也会丢失。

4、AOF重写机制

因为是记录命令AOF文件会比RDB文件大很多而且AOF会记录对同一个key的多次修改最后在删除全部都是白记录通过执行bgrewriteaof命令可以让AOF文件执行重写功能用最少的命令达到相同的效果。

Redis也可以在触发阈值时自动重写AOF文件阈值在redis.conf中配置

但是在触发 AOF 重写时比如当 AOF 文件大于 64M 时就会对 AOF 文件进行重写这时是需要读取所有缓存的键值对数据并为每个键值对生成一条命令然后将其写入到新的 AOF 文件重写完后就把现在的 AOF 文件替换掉。

这个过程其实是很耗时的所以重写的操作不能放在主进程里。

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

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

混合持久化

将 RDB 和 AOF 合体使用这个方法是在 Redis 4.0 提出的该方法叫混合使用 AOF 日志和内存快照也叫混合持久化。

如果想要开启混合持久化功能可以在 Redis 配置文件将下面这个配置项设置成 yes

aof-use-rdb-preamble yes

混合持久化工作在 AOF 日志重写过程

当开启了混合持久化时在 AOF 重写日志时fork 出来的重写子进程会先将与主线程共享的内存数据以 RDB 方式写入到 AOF 文件然后主线程处理的操作命令会被记录在重写缓冲区里重写缓冲区里的增量命令会以 AOF 方式写入到 AOF 文件写入完成后通知主进程将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的 AOF 文件。

也就是说使用了混合持久化AOF 文件的前半部分是 RDB 格式的全量数据后半部分是 AOF 格式的增量数据

图片

这样的好处在于重启 Redis 加载数据的时候由于前半部分是 RDB 内容这样加载的时候速度会很快

加载完 RDB 的内容后才会加载后半部分的 AOF 内容这里的内容是 Redis 后台子进程重写 AOF 期间主线程处理的操作命令可以使得数据更少的丢失

总结

他们各有优缺点如果对数据库安全性要求较高在实际开发中往往两者结合使用

 

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: redis

“Redis持久化 | 黑马Redis高级篇” 的相关文章