首页 > 数据库 >Redis持久化机制

Redis持久化机制

时间:2023-04-24 16:01:07浏览次数:45  
标签:AOF 快照 主线 Redis RDB 持久 日志 化机制

Redis是内存数据库,但一旦服务器宕机,内存中的数据将全部丢失。作为缓存,虽然可以从慢速数据库重新读取数据,但是也会增加慢速数据库压力。

所以选择数据持久化方式,避免从后端数据库中进行恢复

3 种持久化方式

  • AOF:只追加文件(Append-Only File)
  • RDB:快照(snapshotting)
  • RDB 和 AOF 的混合持久化(Redis 4.0 新增)

AOF

img

好处

  • 写后日志。先执行命令,把数据写入内存,然后才记录日志。对比写前日志(Write Ahead Log, WAL),写后日志通过先执行命令避免出现记录错误命令的情况。
  • 不会阻塞当前的写操作。

风险

  • 刚执行完一个命令,还没有来得及记日志就宕机。无法通过日志进行恢复
  • 避免了对当前命令的阻塞,但可能会给下一个操作带来阻塞风险。AOF 日志也是在主线程中执行的,如果在把日志文件写入磁盘时,磁盘写压力大,就会导致写盘很慢,进而导致后续的操作也无法执行了。

AOF三种日志写回策略

解决AOP风险的关键是控制一个写命令执行完后 AOF 日志写回磁盘的时机。在避免主线程阻塞和减少数据丢失寻找一个平衡。

appendfsync配置项

  • Always,同步写回:每个写命令执行完,立马同步地将日志写回磁盘;
    • 基本不丢数据,但会影响主线程性能
  • Everysec,每秒写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘;
    • 最多丢失上1秒内的数据,主线程性能得到较好释放
  • No,操作系统控制的写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
    • 主线程性能很高,但回写不由Redis控制,较可能数据丢失
img

如何选择

根据系统对高性能和高可靠性的要求,来选择使用哪种写回策略

  • 想要获得高性能,就选择 No 策略
  • 如果想要得到高可靠性保证,就选择 Always 策略
  • 如果允许数据有一点丢失,又希望性能别受太大影响的话,那么就选择 Everysec 策略

日志文件过大问题

日志文件过大带来性能问题

  • 文件系统本身对文件大小有限制,无法保存过大的文件
  • 文件太大,之后再往里面追加命令记录的话,效率也会变低
  • 发生宕机,AOF 中记录的命令要一个个被重新执行,用于故障恢复,如果日志文件太大,整个恢复过程就会非常缓慢,这就会影响到 Redis 的正常使用

AOF 重写机制

  • 在重写时,Redis 根据数据库的现状创建一个新的 AOF 文件。读取数据库中的所有键值对,然后对每一个键值对用一条命令记录它的写入。
  • 具有“多变一”功能,旧日志文件中的多条命令,在重写后的新日志中变成了一条命令。
img

一个拷贝,两处日志

虽然 AOF 重写后,日志文件会缩小,但是,要把整个数据库的最新数据的操作日志都写回磁盘,仍然是一个非常耗时的过程。

和 AOF 日志由主线程写回不同,重写过程是由后台子进程 bgrewriteaof 来完成的,这也是为了避免阻塞主线程,导致数据库性能下降

  • 一个拷贝:每次执行重写时,主线程 fork 出后台的 bgrewriteaof 子进程。此时,fork 会把主线程的内存拷贝一份给 bgrewriteaof 子进程,这里面就包含了数据库的最新数据。然后,bgrewriteaof 子进程就可以在不影响主线程的情况下,逐一把拷贝的数据写成操作,记入重写日志。
  • 第一处日志:因为主线程未阻塞,仍然可以处理新来的操作。此时,如果有写操作,第一处日志就是指正在使用的 AOF 日志,Redis 会把这个操作写到它的缓冲区。这样一来,即使宕机了,这个 AOF 日志的操作仍然是齐全的,可以用于恢复。
  • 第二处日志:指新的 AOF 重写日志。这个操作也会被写到重写日志的缓冲区。这样,重写日志也不会丢失最新的操作。等到拷贝数据的所有操作记录重写完成后,重写日志记录的这些最新操作也会写入新的 AOF 文件,以保证数据库最新状态的记录。此时,我们就可以用新的 AOF 文件替代旧文件了。

AOF非阻塞的重写过程

  • 每次 AOF 重写时,Redis 会先执行一个内存拷贝,用于重写;然后,使用两个日志保证在重写过程中,新写入的数据不会丢失。而且,因为 Redis 采用额外的线程进行数据重写,所以,这个过程并不会阻塞主线程。
img

AOF小结

  • AOF通过逐一记录操作命令,在恢复时再逐一执行命令的方式,保证了数据的可靠性。
  • 考虑到对 Redis 性能的影响,它提供了 AOF 日志的三种写回策略,分别是 Always、Everysec 和 No,这三种策略在可靠性上是从高到低,而在性能上则是从低到高。三种写回策略体现了系统设计中的一个重要原则 ,即 trade-off,或者称为“取舍”,指的就是在性能和可靠性保证之间做取舍。
  • 避免日志文件过大,Redis 还提供了 AOF 重写机制,直接根据数据库里数据的最新状态,生成这些数据的插入命令,作为新日志。就是一个拷贝,两处日志。
  • 落盘时机和重写机制都是在“记日志”这一过程中发挥作用。落盘时机的选择可以避免记日志时阻塞主线程,重写可以避免日志文件过大。
  • AOF的问题在于当使用AOF日志进行故障恢复时,Redis 的单线程设计使得命令操作只能一条一条按顺序执行,这个“重放”的过程就会很慢。

RDB

  • 内存快照,就是把某一时刻的状态以文件的形式写到磁盘上,即使宕机,快照文件也不会丢失,数据的可靠性也就得到了保证。这个快照文件就称为 RDB 文件,其中,RDB 就是 Redis DataBase 的缩写。

两个问题

  • 如何取景?也就是说,我们打算把哪些人、哪些物拍到照片中;对应问题是对哪些数据做快照,这关系到快照的执行效率问题;
  • 在按快门前,要记着提醒朋友不要乱动,否则拍出来的照片就模糊了。对应问题是做快照时,数据还能被增删改吗?这关系到 Redis 是否被阻塞,能否同时正常处理请求。

给哪些内存数据做快照?

数据越多,RDB 文件就越大,往磁盘上写数据的时间开销就越大。RDB 文件的生成是否会阻塞主线程,这就关系到是否会降低 Redis 的性能。

两个命令来生成 RDB 文件

  • save:在主线程中执行,会导致阻塞;
  • bgsave:创建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞,这也是 Redis RDB 文件生成的默认配置。

快照时数据能修改吗?

  • 避免阻塞和正常处理写操作并不是一回事。为了快照而暂停写操作,肯定是不能接受的
  • COW(Copy-On-Write):写时复制技术。在执行快照的同时,正常处理写操作

Copy-On-Write

  • bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据
  • bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。

如果主线程对这些数据也都是读操作(例如图中的键值对 A),那么,主线程和 bgsave 子进程相互不影响。但是,如果主线程要修改一块数据(例如图中的键值对 C),那么,这块数据就会被复制一份,生成该数据的副本(键值对 C’)。然后,主线程在这个数据副本上进行修改。同时,bgsave 子进程可以继续把原来的数据(键值对 C)写入 RDB 文件

img

可以每秒做一次快照吗?

快照间隔时间可以决定宕机时丢失数据的多少。

一方面,频繁的执行全量快照,会给磁盘带来很大压力,多个快照竞争有限的磁盘带宽,前一个快照还没有做完,后一个又开始做了,容易造成恶性循环。

另一方面,bgsave 子进程需要通过 fork 操作从主线程创建出来。虽然,子进程在创建后不会再阻塞主线程,但是,fork 这个创建过程本身会阻塞主线程,而且主线程的内存越大,阻塞时间越长。如果频繁 fork 出 bgsave 子进程,这就会频繁阻塞主线程了(所以,在 Redis 中如果有一个 bgsave 在运行,就不会再启动第二个 bgsave 子进程)。

通过增量快照来解决问题

增量快照

  • 做了一次全量快照后,后续的快照只对修改的数据进行快照记录,这样可以避免每次全量快照的开销。
img

混合使用 AOF 日志和RDB内存快照

  • 内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。快照不用很频繁地执行,这就避免了频繁 fork 对主线程的影响。AOF 日志也只用记录两次快照间的操作,也就是说,不需要记录所有操作了,因此,就不会出现文件过大的情况了,也可以避免重写开销。
img

AOF 和 RDB 的选择

  • 数据不能丢失时,内存快照和 AOF 的混合使用是一个很好的选择;
  • 如果允许分钟级别的数据丢失,可以只使用 RDB;
  • 如果只用 AOF,优先使用 everysec 的配置选项,因为它在可靠性和性能之间取了一个平衡。

总结

  • AOF日志通过写后日志,带来的好处是尽可能的纪录操作,减少数据丢失。带来的问题就是AOF日志文件过大,对主线程造成压力和损耗
  • AOF重写日志通过合并命令,解决了AOF日志文件过大的问题。带来的问题就是当故障恢复时,因为Redis的单线程处理,重放的过程较慢
  • RDB快照通过生成RDB文件直接读入内存,解决了AOF日志文件重放慢的问题。带来的问题就是RDB文件的生成频率太慢会丢失数据,生成频率太快给磁盘带来很大压力,同时fork出bgsave子进程也会对主线程造成阻塞。
  • 增量快照通过只对修改的数据进行快照记录,这样可以避免每次全量快照的开销。借助AOF日志来记录增量。
  • 混合使用 AOF 日志和RDB内存快照,既能享受到 RDB 文件快速恢复的好处,又能享受到 AOF 只记录操作命令的简单优势

参考

04 AOF日志:宕机了,Redis如何避免数据丢失?

05 内存快照:宕机后,Redis如何实现快速恢复?

Redis持久化机制详解

标签:AOF,快照,主线,Redis,RDB,持久,日志,化机制
From: https://www.cnblogs.com/wftop1/p/17349772.html

相关文章

  • springboot集成redis时总报错Connection refused: no further information: localhost
    nacos上配置的关于redis的key值不是springboot需要的固定写法如:sping.redis.host=spring.redis.port=sping.redis.password=spring.redis.database=我写的是一个自定义的key如com.dream.redis.host改为springboot认识的即可其他和springboot集成的组件类似,切记......
  • Redis高频面试题 - 2 一般有用 看1
     1、Redis持久化机制Redis是一个支持持久化的内存数据库,通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。实现:单独创建fork()一个子进程,将当前父进程的数据库数据复制到子进程的内存......
  • redis实现分布式锁
    分布式锁是由共享存储系统维护的变量,多个客户端可以向共享存储系统发送命令进行加锁或释放锁操作。Redis作为一个共享存储系统,可以用来实现分布式锁。在基于单个Redis实例实现分布式锁时,对于加锁操作,我们需要满足三个条件。1.加锁包括了读取锁变量、检查锁变量值和设置锁变量......
  • 吃透Redis面试八股文
    Redis连环40问,绝对够全!Redis是什么?Redis(RemoteDictionaryServer)是一个使用C语言编写的,高性能非关系型的键值对数据库。与传统数据库不同的是,Redis的数据是存在内存中的,所以读写速度非常快,被广泛应用于缓存方向。Redis可以将数据写入磁盘中,保证了数据的安全不丢失,而且Redis......
  • A stop job is running for LSB:start and stop redis_6379
     修改/etc/init.d/redis_6379(stop下红框中内容,格式:$CLIEXEC-a"password" -p$REDISPORTshutdown)  ......
  • redis之哈希类型-列表类型-集合类型-有序集合-慢查询-pipeline-发布订阅-Bitmap位图-H
    目录redis之哈希类型-列表类型-集合类型-有序集合-慢查询-pipeline-发布订阅-Bitmap位图-HyperLogLog-GEO地理位置昨日内容回顾今日内容详细1哈希类型2列表类型3集合类型4有序集合5慢查询6pipeline与事务7发布订阅8Bitmap位图9HyperLogLog10GEO地理位置redis之哈希类型......
  • redis应用场景及三种集群方式
    1.正文1.redis应用场景2.redis得持久化方式3.redis得集群4.java连接redis服务器2.redis应用场景1、热点数据的缓存----由于redis访问速度块、支持的数据类型比较丰富,所以redis很适合用来存储热点数据,另外结合expire,我们可以设置过期时间然后再进行缓存更新操作,这......
  • redis 做分布式限流
    参看来源:https://blog.51cto.com/u_15708799/5703440 测试有效代码:我们要做的是:当并发请求超出了限定阈值时,要延迟请求,而不是直接丢弃 。当然也可以把结果给业务端,看业务端是提醒用户下次,还是延迟处理,还是丢弃。 @TestpublicvoidtestLimitWait()throwsInterru......
  • redis安装及常用命令
    1.正文--redis[重点]1.什么是NOSQL2.NOSQL和RDBMS的区别3.NOSQL的产品4.介绍Redis5.安装Redis6.redis支持的数据类型2.什么是NOSQLNOSQL(notonlysql)不仅是sql,它是所有非关系数据库的一种统称。3.NOSQL和RDBMS的区别RDBMS--关系型数据库高度组织化结构......
  • redis-哨兵
    1.哨兵高可用主从存在的问题:主从复制,主节点发生鼓掌,可以手动转移,让其中一个slave变成master,这就是哨兵主从复制,只能是主来写数据,所以写的能力和存储能力有限,需要做集群哨兵:sentinel哨兵就是一个redis进程哨兵的工作原理:1.多个sentinel发现并确认master有问题2.选取出一个s......