(四)持久化之---AOF持久化的配置和原理

AOF持久化及AOF重写的配置:



默认AOF方式是关闭的,如下图:

如果要开启的话,就是把no改写成yes。如下图:

默认文件名称appendonly.aof,你也可以修改文件名。默认保存目录同样也是配置文件中dir配置项中的设置,它和RDB共用一个目录。如下图:

默认同步策略是每秒,如下图:

我们对数据库做一些操作然后查看一下appendonly.aof文件内容

它会记录所有写操作内容。

*2 表示2个参数
$6 表示第一个参数长度为6
SELECT 第一个参数
$1 第二个参数长度为1
0 第二个参数

AOF重写策略

AOF持久化实现原理:



当AOF持久化开启后,当对数据库进行一次更新操作后,更新命令就会被追加到aof_buf缓冲区的末尾,然后由缓冲区写入到AOF文件。

AOF文件中记录的内容就是对数据更新操作的指令。这个文件本身就是以文本来记录的,如下图:

当需要恢复数据的时候,通过执行AOF文件中记录的更新指令,就可以完成。人为的看里面的指令,然后手动敲命令也可以完成。

AOF重写实现原理:



因为AOF持久化是通过记录命令的方式来保存数据库状态的,随着时间的推移AOF文件肯定会逐渐增大,如果不加以控制会对AOF持久化性能以及数据恢复造成影响。下面举例来更加形象的说明重写的必要:

我们以一个压缩列表为例

根据AOF的原理,那么上面红色方框中的5条命令都要追加到AOF文件中,其实我们看到最后list的状态就是BCDEF值。也就是说为例实现最后的状态,需要追加5条命令。所以在大量内存读写的业务里AOF文件增长的很快,为例解决这个问题,Redis提供了AOF重写功能。

AOF重写就是创建一个新的AOF文件来替换现有的AOF文件,实际上AOF重写并不对现有的旧AOF文件进行操作。

以上面例子来说,当进行重写的时候直接从数据库里去获取list的最新状态,然后在新的AOF文件中直接写一条rpushlist B C D E F命令,从而避免写5条的操作,这样AOF文件的增长速度就会降低,同时容量也不会特别大。

AOF重写程序aof_rewrite函数去完成创建新的AOF文件的任务,但是该函数并不会由Redis主进程去直接调用,而是使用子进程后台去执行(BGREWRITEAOF,该命令其实就是执行aof_rewrite,只不过是由子进程去调用的),这时主进程就会不被阻塞,那么就可以在执行重写的过程中父进程可以继续对外提供响应。整个过程如下:

  • 当重写被触发时父进程调用一个函数,该函数创建一个子进程用于执行BGREWRITEAOF,该子进程创建一个临时文件,然后父进程继续对外提供读写服务
  • 子进程遍历数据库,将每个键值的最新状态输出到临时文件中,在BGREWRITEAOF过程中,父进程把所有对数据库的更新命令同时写入到AOF缓冲区和AOF重写缓冲区(aof_rewrite_buf_blocks),AOF缓冲区(aof_buf)会继续同步到现有AOF文件中(一般情况下在AOF重写期间不建议把AOF缓冲区的内容同步到现有的AOF文件中,这会降低性能,默认为NO)
  • AOF重写完成后子进程通知父进程,父进程调用信号处理函数
  • 信号处理函数会阻塞父进程对外提供读写操作(时间很短,不阻塞就又会出现数据不一致的情况),然后将AOF重写缓冲区的内容写入到新的AOF文件中,最后用新的AOF文件替换现有AOF文件(更名操作)

APPENDFSYNC选项说明:


参数 说明
always 将aof_buf缓冲区中的所有内容写入并同步到AOF文件中,立即执行write()和fsync()系统调用。对于数据的安全性最高,但是执行最慢,如果出现故障只会丢失一个事件循环的内容。
everysec 将aof_buf缓冲区的所有内容写入到AOF文件,如果上次同步AOF的时间距离本次超过1秒,则执行同步,每隔一秒执行一次write()和fsync()系统调用。数据安全性居中,执行快,仅会丢失1秒的数据。
no 将aof_buf缓冲区的所有内容写入到AOF文件,但是何时同步由操作系统决定,仅执行write()系统调用。写入动作效率高,但是不执行同步,但是单次同步消耗时间最长,数据安全性最低,会丢失上一次同步之后的所有数据。

这里要特别说明一下Linux系统的文件写入和同步原理,为什么要说这个,因为不解释一下这个过程,你就很难理解APPENDFSYNC选项中的no参数,如果把Always理解为总是、一直或者实时;而把everysec理解为每秒的话,那no的含义难道是不执行AOF文件同步吗?如果不同步文件,那开启AOF持久化干嘛呢?

在Redis调用appendfsync函数的时候,其实是先调用一个write()函数,然后再调用sync()或者fsync()函数(对于任何程序来说只要想把数据写入磁盘其过程都一样,有些也有例外)。

用户空间:常规进程所在区域,用户发起的,此区域的代码不能直接访问硬件

内核空间:操作系统所在区域,能和设备控制器通讯

当调用了write()函数时,该函数一旦返回正常值,我们可能就认为数据已经写入到了磁盘,但实际上,操作系统在实现磁盘文件的IO时,为了保证IO的效率,会在内存中使用一段专门的地址空间,该空间叫做内核空间,而内核空间之内又会有一段是用作IO的数据缓冲区(这个缓冲区和之前说的aof_buf缓冲区不是一个概念,虽然都在内存中),write()函数的作用就是把数据写入到内核空间的IO缓冲区中。

内核空间的IO缓冲区也有一定大小,当该缓冲区没有写满时或者没有到一个同步周期时,会持续的把write()函数传递的数据写入到该缓冲区中,而当该缓冲区写满或者到了一个同步周期,则会把该缓冲区的内容提交到输出队列,当需要数据到达队列队首的时候,开始执行真正的磁盘IO操作,把数据写入磁盘(这里虽然用来写入磁盘,但是真正的动作不是移动而是复制,复制完成之后,内核空间的IO缓冲区才会释放该数据占用的空间)。这种方式叫做延迟写入。

所以这就会出现一个问题,当调用了write()函数后并不等于数据真的保存到了磁盘,但是这里又会有一个错觉,就是你再次请求该文件的时候,可以显示你最后一次更新的内容,其实这个内容并不是从磁盘上读取过来的,而是从用户空间的缓冲区读取的。接着刚才提到的问题,如果数据在内核空间的IO缓冲区内,而此时操作系统出现故障、断电等异常情况就会造成数据丢失。

为了解决数据丢失问题,Unix系统提供了sync、fsync和fdatasync三个函数。

函数 功能
sync 函数返回0表示成功,该函数负责把所有内核空间中IO缓冲区内修改过的内容推送到输入队列,然后就返回,它并不等待所有磁盘IO操作完成。所以即使调用了sync函数,也不等于成功保存到磁盘了。
fsync 函数返回0表示成功,与sync不同,它只会对指定文件描述符的单一文件生效,强制与该文件相连的所有修改过的数据传送到磁盘上,并且等待磁盘IO完毕,然后返回。当该函数返回0时,才真正表示成功保存到磁盘。数据库会在调用了write()之后调用fsync()。
fdatasync 它与fsync类似,它只影响文件数据部分,不涉及数据属性,比如inode信息。所以相对于fsync它需要较少的写磁盘操作。

所以看了上面的内容,你就知道APPENDFSYNC中no参数的含义.

时间: 2025-01-13 22:45:55

(四)持久化之---AOF持久化的配置和原理的相关文章

redis配置文件基本解析以及RDB持久化与AOF持久化

redis.conf 我们安装成功之后就会有这个配置文件,但是我们一般都不推荐直接使用出厂的配置文件,而是单独拷贝一份使用,以避免我们因为配置错误而带来不必要的麻烦. 如图我单独拷贝了一份在根目录下面的文件夹: redis单元: Tcp-backlog: 设置tcp的backlog,backlog其实是一个连接队列,backlog队列总和=未完成三次握手队列+已经完成三次握手队列. 在这里三次握手队列我参考另一篇博文:https://blog.csdn.net/ityouknow/article

redis持久化之AOF持久化

AOF与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,aof持久化是通过保存redis服务器所执行的写命令来记录数据库状态的.被写入AOF文件的所有命令都是以Redis的命令请求协议格式保存的. 1.AOF持久化的实现 AOF持久化的实现可以分为命令追加(append),文件写入,文件同步(sync)三个步骤. 1.1 命令追加 当AOF持久化功能处于打开状态,服务器在执行完一个写命令之后,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区末尾: struct red

redis++:Redis持久化 rdb & aof 工作原理及流程图 (三)

RDB的原理: 在Redis中RDB持久化的触发分为两种:自己手动触发与Redis定时触发. 针对RDB方式的持久化,手动触发可以使用: 1):save:会阻塞当前Redis服务器,直到持久化完成,线上应该禁止使用. 2):bgsave:该触发方式会fork一个子进程,由子进程负责持久化过程,因此阻塞只会发生在fork子进程的时候. 而自动触发的场景主要是有以下几点: 1):根据我们的 save m n 配置规则自动触发: 2):从节点全量复制时,主节点发送rdb文件给从节点完成复制操作,主节点

redis的 rdb 和 aof 持久化的区别 [转]

aof,rdb是两种 redis持久化的机制.用于crash后,redis的恢复. rdb的特性如下: Code: fork一个进程,遍历hash table,利用copy on write,把整个db dump保存下来.save, shutdown, slave 命令会触发这个操作.粒度比较大,如果save, shutdown, slave 之前crash了,则中间的操作没办法恢复. aof有如下特性: Code: 把写操作指令,持续的写到一个类似日志文件里.(类似于从postgresql等数

redis的rdb与aof持久化机制

Redis提供了两种持久化方案:RDB持久化和AOF持久化,一个是快照的方式,一个是类似日志追加的方式 RDB快照持久化 RDB持久化是通过快照的方式,即在指定的时间间隔内将内存中的数据集快照写入磁盘.在创建快照之后,用户可以备份该快照,可以将快照复制到其他服务器以创建相同数据的服务器副本,或者在重启服务器后恢复数据.RDB是Redis默认的持久化方式 save 900 1 当时间到900秒时,如果至少有1个key发生变化,就会自动触发bgsave命令创建快照 save 300 10 当时间到3

redis源码分析(四)--aof持久化

Redis aof持久化 Redis支持两种持久化方式:rdb与aof,上一篇文章中已经大致介绍了rdb的持久化实现,这篇文章主要介绍aof实现. 与rdb方式相比,aof会使用更多的存储空间,因为它将数据以客户端命令的形式进行存储,并使用ascii编码.但它也有相应的优点,如支持append的方式保存db内容的变动,不需要像rdb方式一样一旦内容有变动,便需要重新完整生成文件才能将变动保存到文件中:同时在子进程持久化的过程中,可以累积客户端的命令到缓存中,最后将缓存内容添加到持久化生成的文件的

Redis源码剖析和注释(十八)--- Redis AOF持久化机制

Redis AOF持久化机制 1. AOF持久化介绍 Redis中支持RDB和AOF这两种持久化机制,目的都是避免因进程退出,造成的数据丢失问题. RDB持久化:把当前进程数据生成时间点快照(point-in-time snapshot)保存到硬盘的过程,避免数据意外丢失. AOF持久化:以独立日志的方式记录每次写命令,重启时在重新执行AOF文件中的命令达到恢复数据的目的. Redis RDB持久化机制源码剖析和注释 AOF的使用:在redis.conf配置文件中,将appendonly设置为y

第十章 Redis持久化--RDB+AOF

注:本文主要参考自<Redis设计与实现> 1.Redis两种持久化方式 RDB 执行机制:快照,直接将databases中的key-value的二进制形式存储在了rdb文件中 优点:性能较高(因为是快照,且执行频率比aof低,而且rdb文件中直接存储的是key-values的二进制形式,对于恢复数据也快) 缺点:在save配置条件之间若发生宕机,此间的数据会丢失 AOF 执行机制:将对数据的每一条修改命令追加到aof文件 优点:数据不容易丢失 缺点:性能较低(每一条修改操作都要追加到aof文

【Redis篇】Redis持久化方式AOF和RDB

一.前述 持久化概念:将数据从掉电易失的内存存放到能够永久存储的设备上. Redis持久化方式RDB(Redis DB)   hdfs:    fsimageAOF(AppendOnlyFile)   hdfs :    edit logs    默认关闭的 二.RDB方式 在默认情况下,Redis 将数据库快照保存在名字为 dump.rdb的二进制文件中 在RDB方式下,有两种方式, 1.一种是手动执行持久化数据命令来让redis进行一次数据快照,而手动执行持久化命令,你依然有两种选择,那就是