AOF 是什么

Append Only File,通过保存 Redis 服务器所执行的命令来记录数据库状态。

AOF 持久化的实现

命令追加

服务器在执行完一个写命令后,会以协议格式将被执行的写命令追加到服务器状态的 aof_buf 缓冲区的末尾:

struct redisServer {
……
// AOF 缓冲区
sds aof_buf;
……
}

AOF 文件的写入和同步

AOF 文件的载入和数据还原

流程:

AOF 重写

为什么需要重写

AOF 持久化是通过保存被执行的写命令来记录数据库状态的,随着服务器运行时间的流逝,AOF 文件的内容会越来越多,文件体积越来越大。如果客户端执行了下面的命令:

127.0.0.1:6379> set name yano
OK
127.0.0.1:6379> set name yano2
OK
127.0.0.1:6379> set name yano3
OK

那么 AOF 文件就需要保存 3 条命令,不仅使保存的 AOF 文件体积变大,还使得 Redis 启动时载入数据变慢。

什么是重写

AOF 文件重写(rewrite),创建新的 AOF 文件替代现有的 AOF 文件,新旧两个 AOF 文件所保存的数据库状态相同,但新 AOF 文件不会包含任何浪费空间的冗余命令,体积更小。

如何重写

不是读取和分析现有的 AOF 文件内容,而是直接从数据库读取值组成相应的命令 AOF 文件。

AOF 后台重写

为什么需要后台重写

重写函数 aof_rewrite 会进行大量的写入操作,执行这个函数的线程会被长时间阻塞,但是 Redis 服务器使用单个线程来处理命令请求,如果直接在主线程直接更新,在重写期间,服务器将无法处理客户端发来的命令请求。所以将 AOF 重写程序放到子进程中执行。

带来的问题

子进程在进行 AOF 重写期间,服务器进程还需要继续处理命令请求,新的命令可能对现有的数据库状态进行修改,导致服务器当前数据库状态和重写后的 AOF 文件保存的数据状态不一致。

AOF 重写缓冲区

为了解决这种数据不一致的问题,Redis 设置了一个 AOF 重写缓冲区,在服务器创建子进程之后开始使用,当 Redis 服务器执行完一个写命令后,同时将这个写命令发送给 AOF 缓冲区AOF 重写缓冲区

当子进程完成 AOF 重写工作后,它会向父进程发送一个信号,父进程在收到这个信号后,会调用一个信号处理函数:

  1. 将 AOF 重写缓冲区的所有内容写入新的 AOF 文件,这样新 AOF 文件所保存的数据库状态就与服务器当前的数据库状态一致;
  2. 对新 AOF 文件改名,原子覆盖现有的 AOF 文件,完成新旧 AOF 文件的替换。

下图左边是正常流程,右边是 AOF 重写期间的流程:

注意

在实际中,为了避免在执行命令时造成客户端输入缓冲区的溢出,重写程序在处理列表、哈希表、集合、有序集合可能带有多个元素的键时,会先检查键所包含的元素数量,如果元素数量超过了一个常量阈值,重写程序会使用多条命令来记录键的值。

实际例子

配置 redis.conf 文件,使用 AOF:

appendonly yes
appendfsync always
appendfilename "appendonly.aof"
dir ./

启动 Redis server:

src/redis-server redis.conf&

启动 Redis client:

src/redis-cli

设置 key:

127.0.0.1:6379> set name yano
OK
127.0.0.1:6379> set name yano2
OK
127.0.0.1:6379> set name yano3
OK

查看 appendonly.aof 文件:

➜  redis-6.2.6 cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$4
name
$4
yano
*3
$3
set
$4
name
$5
yano2
*3
$3
set
$4
name
$5
yano3

参考链接

Redis 源码简洁剖析系列

最简洁的 Redis 源码剖析系列文章

Java 编程思想-最全思维导图-GitHub 下载链接,需要的小伙伴可以自取~

原创不易,希望大家转载时请先联系我,并标注原文链接。

Redis 源码简洁剖析 15 - AOF的更多相关文章

  1. Redis 源码简洁剖析 03 - Dict Hash 基础

    Redis Hash 源码 Redis Hash 数据结构 Redis rehash 原理 为什么要 rehash? Redis dict 数据结构 Redis rehash 过程 什么时候触发 re ...

  2. Redis 源码简洁剖析 07 - main 函数启动

    前言 问题 阶段 1:基本初始化 阶段 2:检查哨兵模式,执行 RDB 或 AOF 检测 阶段 3:运行参数解析 阶段 4:初始化 server 资源管理 初始化数据库 创建事件驱动框架 阶段 5:执 ...

  3. Redis 源码简洁剖析 11 - 主 IO 线程及 Redis 6.0 多 IO 线程

    Redis 到底是不是单线程的程序? 多 IO 线程的初始化 IO 线程运行函数 IOThreadMain 如何推迟客户端「读」操作? 如何推迟客户端「写」操作? 如何把待「读」客户端分配给 IO 线 ...

  4. Redis 源码简洁剖析 13 - RDB 文件

    RDB 是什么 RDB 文件格式 Header Body DB Selector AUX Fields Key-Value Footer 编码算法说明 Length 编码 String 编码 Scor ...

  5. Redis 源码简洁剖析 16 - 客户端

    整体概述 客户端属性 套接字描述符 标志 输入缓冲区 命名及命令参数 命令的实现函数 输出缓冲区 客户端的创建与关闭 创建普通客户端 关闭普通客户端 参考链接 Redis 源码简洁剖析系列 整体概述 ...

  6. Redis 源码简洁剖析 02 - SDS 字符串

    C 语言的字符串函数 C 语言 string 函数,在 C 语言中可以使用 char* 字符数组实现字符串,C 语言标准库 string.h 中也定义了多种字符串操作函数. 字符串使用广泛,需要满足: ...

  7. Redis 源码简洁剖析 04 - Sorted Set 有序集合

    Sorted Set 是什么 Sorted Set 命令及实现方法 Sorted Set 数据结构 跳表(skiplist) 跳表节点的结构定义 跳表的定义 跳表节点查询 层数设置 跳表插入节点 zs ...

  8. Redis 源码简洁剖析 05 - ziplist 压缩列表

    ziplist 是什么 Redis 哪些数据结构使用了 ziplist? ziplist 特点 优点 缺点 ziplist 数据结构 ziplist 节点 pre_entry_length encod ...

  9. Redis 源码简洁剖析 06 - quicklist 和 listpack

    quicklist 为什么要设计 quicklist 特点 数据结构 quicklistCreate quicklistDelIndex quicklistDelEntry quicklistInse ...

随机推荐

  1. 单篇长文TestNG从入门到精通

    简介 TestNG是Test Next Generation的缩写,它的灵感来自于JUnit和NUnit,在它们基础上增加了很多很牛的功能,比如说: 注解. 多线程,比如所有方法都在各自线程中,一个测 ...

  2. Google插件开发探索

    简单的开始 https://blog.lateral.io/2016/04/create-chrome-extension-modify-websites-html-css/ 基础教程 https:/ ...

  3. windows10双系统删除linux

    问题 在这里删除后会发现有残留一个引导区,几百m(下图已经删除完),而且启动会进linux引导,然后必须f12进入选择启动项才可以启动windows 解决方法 使用删除引导就可以了 再使用傲梅分区助手 ...

  4. golang中的标准库strconv

    strconv 包 strconv包实现了基本数据类型与其字符串表示的转换,主要有以下常用函数: Atoi().Itia().parse系列.format系列.append系列. string与int ...

  5. 返回值ModelAndView

  6. Filter-FilterChain多个过滤器执行的细节

    FilterChain过滤器链 Filter   过滤器 Chain  链 FilterChain  就是过滤器链(多个过滤器如何一起工作) 在多个filter过滤器执行时,执行优先顺序由web.xm ...

  7. Nginx命令(全局配置文件与模块)

    目录 一:Nginx命令 二:Nginx全局配置文件 1.nginx全局配置 2.过滤出Nginx 三:Nginx网址模块(解析) 一:Nginx命令 1.-v : 打印版本号 [root@web01 ...

  8. K8s 资源配额管理对象 ResourcesQuota

    Kubernetes 是一个多租户平台,更是一个镜像集群管理工具.一个 Kubernetes 集群中的资源一般是由多个团队共享的,这时候经常要考虑的是如何对这个整体资源进行分配.在 kubernete ...

  9. Android开发-记账本布局-实现记账页面功能选择

    记账页面需要软件盘的弹出,时间的显示和记账类型的选择.为了实现选择的效果,点击图片图片发生变化. 需要制作记账类型数据库,并设置单机事件,单机图片,图片变色,代表选中. 至于软键盘的制作,我直接拿来用 ...

  10. 守护石谈学习Java之路

    ​这次在CSDN Blink发表了几篇关于Java编程学习的小作文,讲述了Java工程师的成长路线.Java学习的技能树和入门工作要关注的核心问题,我继续做一次文章的整合与延展,以文章的形式发表出来, ...