首页 > 数据库 >深入理解redis持久化—AOF日志

深入理解redis持久化—AOF日志

时间:2024-06-23 11:28:20浏览次数:26  
标签:AOF aof 写入 redis 文件 缓冲区 日志 重写

redis为什么需要持久化

redis是内存数据库,redis所有的数据都保存在内存中

如果此时pc关机或重启,那么内存中的用户数据岂不是丢失了?redis这么不安全吗?

作为数据库,保证数据的安全,持久是基本需求,redis采用了AOF和RDB两种持久化方式,将用户数据以特殊形式保存在磁盘中,确保重启时可以恢复之前的内存数据状态

AOF(Append Only File)日志

redis的AOF持久化方式是:redis每执行一次写操作,就将对应的命令记录到一个磁盘文件中,redis一旦宕机,重启时重新执行这些命令就可以恢复之前的数据状态

在这里插入图片描述

这种保存写操作命令到日志的持久化方式,就是 Redis 里的 AOF(Append Only File) 持久化功能

写日志的步骤:

1.写入aof内核缓冲区

2.将内核缓冲区的数据写入磁盘

Redis 是先执行写操作命令后,才将该命令记录到 AOF 日志里的,这么做其实有两个好处:

1.避免额外的检查,如果一条命令不符合协议的语法,那么这条语句是不会被执行的,如果先写入日志,就会导致恢复数据时,这条命令失效,造成了不必要的性能开销

2.不会阻塞当前写操作的执行,因为执行命令和写日志两个操作都是由主进程进行的,先保证写操作的执行,再进行写日志

AOF持久化的缺陷

1.由于执行写操作和写日志是两个串行的操作,如果在写入日志之前redis故障,就会导致数据丢失

2.写日志操作虽然不会阻塞上一个写操作的执行,但是会阻塞下一个写操作的执行

在这里插入图片描述

问题根源——写日志的时机

我们刚刚介绍的,先执行写操作,随后写日志其实是redis日志写策略的一种,现在介绍redis提供的写日志的三种策略

1.Always:每次进行写操作后,将命令写入aof内核缓冲区,随即写入磁盘

2.Everysec:每次进行写操作后,将命令写入aof内核缓冲区,每隔一秒将数据写入磁盘

3.NO:每次进行写操作后将命令写入aof内核缓冲区,由操作系统决定写磁盘的时机

不难发现,每次进行写操作后都必须将命令写入内核aof内核缓冲区,这个过程并不耗时,容易造成阻塞的是写磁盘操作

三种策略的优缺点:

在这里插入图片描述

操作系统何时将aof缓冲区的数据写入磁盘?

当应用程序向文件写入数据时,内核通常先将数据复制到内核缓冲区中,然后排入队列,然后由内核决定何时写入硬盘,也就是说,内核缓冲区不止由aof的数据,还有其它的数据,真正的写磁盘时机由操作系统的策略决定

写磁盘时机可以由程序员决定吗?
fsync函数是操作系统提供的同步函数,可以强制让操作系统立即将内核缓冲区的数据写入到磁盘中
上面提到的 Always和Everysec两种写磁盘策略本质上就是调用了fsync函数

AOF重写机制

聪明的你,有没有发现AOF日志会记录一些无效信息?

比如,我执行了set name wjq,随后又执行了set name wjq++,此时数据库中name对应的值实际上是wjq++,而wjq这个值被覆盖了,是无效的,而AOF全部记录了这两条命令,并在恢复数据时重新执行这两条命令,而实际上只需要记录第二条命令,这无疑造成了性能浪费

那么,如何判断某条命令(set name wjq)可以不被记录呢?

很简单,只要查看数据库中现有的数据(wjq++),其中的数据是恢复时所必需的

所以,AOF重写机制就是

读取当前数据库中的所有键值对,然后将每一个键值对用一条命令记录到「新的 AOF 文件」,等到全部记录完后,就将新的 AOF 文件替换掉现有的 AOF 文件。

重写工作完成后,就会将新的 AOF 文件覆盖现有的 AOF 文件,这就相当于压缩了 AOF 文件,使得 AOF 文件体积变小了。

AOF后台重写

之所以使用AOF重写机制,不是因为AOF记录了无效的信息,而是因为当数据量过大时,AOF文件占用空间过多,我们需要将AOF文件进行压缩

所以,AOF重写机制的触发时机是:当 AOF 文件大于 64M 时

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

你有没有发现,在正常的AOF日志写操作时,是对每一条命令写入aof缓冲区,这个过程并不耗时

但AOF重写时,AOF文件已经超过了64M,这时进行生成命令、写入新文件的操作相当耗时,万万不能放在主进程中进行,那怎么办呢?

所以,Redis 的重写 AOF 过程是由后台子进程 bgrewriteaof 来完成的

当需要进行AOF重写时,fork出一个子进程,由子进程执行重写操作,这样就不会阻塞主进程了

重写期间数据不一致的问题

考虑这样的情况:在子进程进行AOF重写操作时,主进程添加或修改了新的数据,这时子进程只拥有fork时刻的父进程的副本,而没有新添加的数据,并且在AOF重写完成后会用新AOF文件覆盖旧的AOF文件,也就是说,这种数据不一致会导致AOF重写期间添加和修改的数据丢失

解决:

既然在AOF重写期间的新数据只会出现在父进程,而不会出现在子进程,那我们将新数据追加到子进程不就好了

方案:

父进程拥有aof缓冲区

子进程拥有aof重写缓冲区

1.先执行客户端发送的写操作命令

2.将命令写入父进程aof缓冲区

3.将命令写入子进程aof重写缓冲区

这样就解决了父子进程数据不一致和数据丢失的问题

总结

1.AOF日志的持久化具体过程:每执行一条写命令,将该命令写入aof缓冲区,然后由三种写策略(always、everysec、no)决定何时将aof缓冲区数据写入磁盘文件

2.在数据库恢复时,重放磁盘中AOF文件中保存的命令,就实现了内存数据的恢复

3.由于aof记录每一条写命令,会造成记录无效数据的情况,并且数据量大时,aof文件的体积也会过大

为缓解aof的空间占用,redis设计了aof重写的机制,它会扫描数据库中的键值对,并为之生成命令,写入一个新的aof文件中,全部键值对写入完成后,新的aof文件会覆盖旧aof文件,这个过程避免了无效命令的记录,压缩了aof文件体积

大时,aof文件的体积也会过大

为缓解aof的空间占用,redis设计了aof重写的机制,它会扫描数据库中的键值对,并为之生成命令,写入一个新的aof文件中,全部键值对写入完成后,新的aof文件会覆盖旧aof文件,这个过程避免了无效命令的记录,压缩了aof文件体积

不过由于执行aof重写操作的时机是旧aof文件超过64M,也就是说aof重写操作将会很耗时,redis使用一个fork出的子进程来执行这个任务,但是在子进程进行aof重写时,如果父进程产生了新aof数据,会造成数据不一致,且在子进程完成aof重写并覆盖旧aof文件后,这些多出的不一致数据会丢失,所以在aof重写期间追加的新aof数据会先写入父进程aof缓冲区,再写入子进程aof重写缓冲区,解决了数据不一致和数据丢失的问题

推荐学习 https://xxetb.xetslk.com/s/p5Ibb

标签:AOF,aof,写入,redis,文件,缓冲区,日志,重写
From: https://blog.csdn.net/2303_77208351/article/details/139755287

相关文章

  • Redis Desktop Manager for Mac(Redis桌面管理工具) v2022.5.0中文版
    RedisDesktopManagerforMac是Mac平台上一款非常实用的Redis可视化工具。RDM支持SSL/TLS加密,SSH隧道,基于SSH隧道的TLS,为您提供了一个易于使用的GUI,可以访问您的Redis数据库并执行一些基本操作:将键视为树,CRUD键,通过shell执行命令。RedisDesktopManagerforMac(Redis桌......
  • Redis-数据结构-跳表详解
    Redis概述Redis-数据结构-跳表详解跳表(SkipList)是一种基于并联的链表结构,用于在有序元素序列中快速查找元素的数据结构。Redis中广泛使用跳表来实现有序集合(SortedSet)这一数据结构。1.跳表的基本概念和特点跳表的核心思想是通过在不同层级(level)上增加指针来加速查......
  • 大数据运维学习笔记之filebeat+kafka+MM1跨机房实时日志传输案例——筑梦之路
    日志数据量:日均30亿  ......
  • Redis中集合的底层实现原理
            Redis中对于Set类型的底层实现,直接采用了hashTable。但对于Hash、ZSet、List集合的底层实现进行了特殊的设计,使其保证了Redis的高性能。        对于Hash与ZSet集合,其底层的实现实际有两种:压缩列表zipList,与跳跃列表skipList。这两种实现对于用户来......
  • Redis作为常见的缓存工具,我们是如何进行redis缓存持久化的呢?
    Redis的数据是全部存储在内存之中,但如果这时候Redis服务宕机,那存储在内存中的数据也会一并丢失,所以为了让redis的数据避免丢失或者是少丢失一点,就要利用策略来将redis的数据存入到磁盘之中,所以就诞生了redis的持久化。即Redis持久化的意义就是为了保证突然宕机,内存数据不会全部......
  • 深入PHP框架开发:实现高效的日志记录系统
    在软件工程中,日志记录是一种记录程序运行时发生事件的实践,它对于调试、监控和安全分析至关重要。PHP框架提供了多种方式来实现日志记录,这些方式可以帮助开发者捕获和存储关键信息。本文将详细探讨在PHP框架中实现日志记录的不同策略和技术。日志记录的基本概念在深入探讨......
  • 一条Redis命令是如何执行的?
    一条Redis命令是如何执行的?源码结构核心数据结构redisServerredisClientredisDbredisObjectaeEventLoop核心流程redis启动流程main()主循环aeEventProcess执行过程命令执行的流程过程1(redis启动)过程2(客户端与服务端建立链接)过程3(客户端发送命令给服务端)过程4(写就绪将......
  • 数据库优化及慢查询日志分析
    在数据库调优中,我们的目标就是响应时间更快,吞吐量更大。利用宏观的监控工具和微观的日志分析可以快速帮我们找到调优的思路和方式。一、数据库服务器的优化步骤1、观察服务器状态是否存在周期性波动(双11,618等),如果是执行2,否跳到3;2、加缓存,更改缓存失效策略。如果解决则......
  • redis持久化操作【随记】
    持久化Redis它是将数据保存到内存当中,内存里的数据最大特点:断电易失.保存在内存的数据就没有了.如果如果这些数据还有用,业务使用啥的,不能就让它这么没有了.redis当中提供持久化机制,说白了,将内存的数据—->写入到磁盘.–>持久化.1rdb方式redisdatabase,持......
  • 深入解析Redis:从基础到高可用性
    引言在现代应用程序中,数据的高性能、高可用性和一致性至关重要。Redis作为一种开源的内存数据结构存储,不仅提供了极快的读写速度,还支持多种数据结构和高可用性机制。本文将深入探讨Redis的基础知识、关键特性、常见应用场景以及其高可用性机制——主从复制和哨兵。Redis简介......