Redis学习(七)—— 深入了解Redis持久化

9 篇文章 0 订阅
9 篇文章 0 订阅

一、什么是Redis持久化?

Redis的所有数据都保存在内存中,对数据的更新将异步保存到磁盘上。如果Redis需要恢复时,就是从硬盘再到内存的过程。
下图展示了Redis持久化把内存中的数据保存到硬盘上的过程。因为Redis本身就在内存中运行的,当突然断电或者死机之后,我们可以从硬盘中拷贝数据到内存,这是整个过程。
在这里插入图片描述

二、Redis持久化的意义?

如果Redis没有持久化的话,那么Redis只会将数据保存在内存中,如果遇到灾难性的故障(如:Redis突然间挂掉了,进程死了…)就会丢失所有数据。对于企业来说,这简直是一场噩梦。

所以如果我们将Redis持久化,并指定策略定期同步到备份服务器并或者云存储上,就可以保证数据不丢失全部,可以挽回一部分数据,最大化的减少了Redis崩溃后带来的损失。

对于企业来水Redis持久化是必不可少的。持久化主要是做灾难恢复,数据恢复。

持久化是为了让硬盘成为备份,以保证数据库数据的完整。

三、Redis持久化方式

Redis提供了两种不同的持久化方法将数据存储在硬盘上。一种方式叫快照(RDB),他可以将存在于某一时刻的所有数据都写入硬盘里面。另一种方式叫只追加文件(AOF),他会在执行命令时,将被执行的写命令复制到硬盘里面。
这两种持久化方式既可以单独使用,又可以同时使用。

1、快照(RDB)持久化

RDB是在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。
1.1、工作流程

(1)redis根据配置尝试去生成rdb快照文件

(2)fork一个子进程出来

(3)子进程尝试将数据dump到临时的rdb快照文件中

(4)完成rdb快照文件的生成之后,就替换之前的旧的快照文件

只有一个dump.rdb(二进制文件,可以直接载入,每次生成一个新的快照,会覆盖之前的老快照

1.2、创建快照的方式

1)BGSAVE 客户端可以通过向Redis发送BGSAVE命令来创建一个快照。
Redis会调用fork()来创建一个子进程,然后子进程负责将快照写入磁盘,而父进程则继续处理命令请求。

在这里插入图片描述

2)SAVE 客户端可以通过向Redis发送SAVE命令来创建一个快照。
Redis在执行完save命令创建快照之前,其他的命令都要排队

在这里插入图片描述

3)配置文件 如果用户设置了save配置选项,如save 60 10000,那么从Redis最近一次创建快照之后算起,当60s内有10000次写入条件被满足时,Redis就会自动触发BGSAVE命令。如果用户设置了多个save配置选项,那么任意一个save配置选项所设置的条件满足后,就会触发一次BGSAVE命令。

4)当Redis通过shutdown命令关闭服务器时,或者接收到标准的term信号时,会执行一个save命令,阻塞所有客户端,不再执行客户端发送的所有命令,并在save命令执行完之后关闭服务器。

5)当一个Redis服务器连接另一个Redis服务器,并向对方发送SYNC命令来开始一次复制操作的时候,如果主服务器目前没有在执行BGSAVE操作,或者主服务器并不是刚刚执行完BGSAVE操作,那么主服务器就会执行BGSAVE操作。

1.3、RDB总结

1)RDB是Redis内存到硬盘的快照,用于持久化

2)save命令通常会造成redis阻塞,影响其他客户端连接时间。

3)BGSAVE不会阻塞redis,但是会fork新的进程。

4)save自动配置满足任何一个条件就会被执行

5)有些触发机制不容忽视

2、日志(AOF)持久化

以日志的形式来记录每个写操作(读操作不记录),将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。简单的说就是,AOF持久化会将执行的写命令写到AOF文件的结尾,以此来记录数据发生的变化。
在这里插入图片描述

2.1 工作原理

1)Redis 执行fork(),开启一个子进程,现在同时拥有子进程和父进程

2)子进程开始将新AOF文件的内容写入到临时文件中

3)对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有AOF文件的末尾,这样即使在重写中途发生停机,现有的AOF文件也还是安全的。

4)当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。

5)搞定!现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。

2.2 重写机制

就是把过期的,重复的,没有用的,都丢掉,只留了有用的。减少磁盘的占用量,加速恢复速度。

AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集.可以使用命令bgrewriteaof

AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename),遍历新进程的内存中数据,每条记录有一条的Set语句。重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。

2.3 AOF三种策略及重写的触发

AOF的三种策略分别是always、everysec和no。

always : 每个Redis写命令都会被写入到硬盘,这样可以保证每条命令都不丢失,从而将发生系统崩溃时出现的数据丢失降低到最少。不过这种策略需要对硬盘进行大量的写入操作,所以Redis处理命令的速度会受到硬盘性能的限制

everysec: 每秒策略。每一秒的缓冲区的数据都会刷新到硬盘中。Redis可以保证,即使出现系统崩溃,用户最多也是会丢失一秒之内产生的数据。当硬盘忙于执行写入操作的时候,Redis还会优雅的放慢自己的速度,以便适应硬盘的最大写入速度。

no: Redis不会对AOF文件执行任何显式的同步操作,而由操作系统来决定应该在何时对AOF文件进行同步。

命令alwayseverysecno
同步频率每个redis写命令都要同步写入硬盘每秒执行一次同步让操作系统决定何时进行同步
优点不丢失数据每秒一次同步,丢一秒数据不需要管
缺点IO开销大会丢失一秒数据不可控制

Rewrite触发机制:

Redis提供了两种命令,bgrewriteaof和AOF重写配置。bgrewriteaof 类似 RDB 中的 bgsave 命令,它还是 fork() 子进程,然后完成 AOF 的过程。

AOF重写配置命令:

配置名含义
auto-aof-rewrite-min-sizeAOF 文件重写最小的尺寸
auto-aof-rewrite-percentageAOF 文件增长率

auto-aof-rewrite-min-size 表示配置最小尺寸,超过这个尺寸就进行重写。
auto-aof-rewrite-percentage ,这里说的是 AOF 文件增长比例,指当前 AOF 文件比上次重写的增长比例大小。AOF 重写即 AOF 文件在一定大小之后,重新将整个内存写到 AOF 文件当中,以反映最新的状态(相当于 bgsave)。这样就避免了 AOF 文件过大而实际内存数据小的问题(频繁修改数据问题)。

AOF日志膨胀:
redis中的数据有限,很多数据或自动过期,或被用户删除,或被redis用缓存清除的算法清理掉。

redis中的数据会不断淘汰掉旧的,就一部分常用的数据会被自动保留在redis内存中

所以可能很多之前的已经被清理掉的数据,对应的写日志还停留在AOF中,AOF日志文件就一个,会不断的膨胀

解决:
bgrewriteaof 命令发出后,Redis 会在父进程中 fork 一个子进程,同时父进程会分别对旧的 AOF 文件和新的 AOF 文件发出 aof_buf 和 aof_rewrite_buf 命令,同时子进程写入新的 AOF 文件,并通知父进程,最后 Redis 使用 aof_rewrite_buf 命令写入新的 AOF 文件
在这里插入图片描述

配置文件

appendonly yes // appendonly 
 默认是 no
appendfilename "append only - ${port}.aof" //设置 AOF 名字
appendfsync everysec // 每秒同步
dir /diskpath // 新建一个目录
no-appendfsync-on-rewrite yes // 为了减少磁盘压力,AOF 性能上需要权衡。默认是 no,不会丢失数据,但是延迟会比较高。为了减低延迟,一般我们设置成 yes,这样可能丢数据

四、RDB与AOF优缺点对比

RDB 优点

1)RDB 是一个非常紧凑的文件,它保存了某个时间点的数据集,非常适用于数据集的备份。比如你可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集。

2)RDB会生成多个数据文件,每个数据文件都代表了某一时刻中redis的数据,这种多个数据文件的方式,适合做冷备,可以将这种完整的数据文件发送到一些远程的安全存储上去,如Amazon的S3云服务,阿里云的ODPS分布式存储上,以预定好的备份策略来定期备份redis中的数据

关于冷备:

RDB可以做冷备,生成多个文件,每个文件都代表了某一个时刻的完整的数据快照

RDB做冷备,优势在由redis去控制固定时长生成快照文件的事情,比较方便; ,在最坏的情况下,提供数据恢复的时候,速度比AOF快

3)RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能

4)与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.

为什么恢复的时候RDB比AOF快?

AOF,存放的指令日志,做数据恢复的时候,其实是要回放和执行所有的指令日志,来恢复出来内存中的所有数据的;
RDB,就是一份数据文件,恢复的时候,直接加载到内存中即可;
RDB的时候,Redis主进程只需要fork一个子进程,让子进程执行磁盘IO操作来进行RDB持久化即可;

RDB 缺点

1) 如果你希望在redis意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么RDB不适合你.虽然你可以配置不同的save时间点(例如每隔5分钟并且对数据集有100个写的操作),是Redis要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔5分钟或者更久做一次完整的保存,万一在Redis意外宕机,你可能会丢失几分钟的数据

2)RDB 需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求.如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒,AOF也需要fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度.

一般不要让RDB的间隔太长,否则每次生成的RDB文件太大了,对Redis本身的性能可能会有影响的;

3)RDB无法实现实时或者秒级持久化

总结: RDB特别适合做冷备份

AOF 优点

1)更好的保护数据,丢失数据少。 使用AOF 会让你的Redis更加耐久: 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据.

2)AOF日志文件以append-only模式写入,写入性能比较高
AOF日志文件以append-only模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修;可使用redis-check-aof工具修复这些问题.

3)Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写,不会影响客户端的读写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。

4) 适合做灾难性的误删除紧急恢复
AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。

AOF 缺点

1)对于相同的数据集来说, AOF 文件的体积通常要大于 RDB 文件的体积

2) 根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。

(3)以前AOF发生过bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来
所以说,类似AOF这种较为复杂的基于命令日志/merge/回放的方式,比基于RDB每次持久化一份完整的数据快照文件的方式,更加脆弱一些,容易有bug。不过AOF就是为了避免rewrite过程导致的bug,因此每次rewrite并不是基于旧的指令日志进行merge的,而是基于当时内存中的数据进行指令的重新构建,这样健壮性会好很多。

唯一的比较大的缺点,其实就是做数据恢复的时候,会比较慢,还有做冷备,定期的备份,不太方便,可能要自己手写复杂的脚本去做,做冷备不太合适

五、两种持久化方式如何去选择?

一般来说, 如果想达到足以媲美 PostgreSQL 的数据安全性, 你应该同时使用两种持久化功能。
用RDB来做不同程度的冷备,在AOF文件都丢失或损坏不可用的时候,还可以使用RDB来进行快速的数据恢复;

如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。

有很多用户都只使用 AOF 持久化, 但我们并不推荐这种方式: 因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快, 除此之外, 使用 RDB 还可以避免之前提到的 AOF 程序的 bug 。

【参考资料】
《Redis实战》
https://blog.csdn.net/qq_34190023/article/details/82715705
http://www.redis.cn/topics/persistence.html
https://blog.csdn.net/xlgen157387/article/details/89208221
GitChat – Redis入门到分布式实践

不断学习,不断总结才会进步。如有总结不当,有问题,错误的地方请大家予以指正,共同学习,共同进步

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值