爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      Redis系列之持久化机制

      首页 知识中心 数据库 文章详情页

      Redis系列之持久化机制

      2023-05-06 10:22:06 阅读次数:189

      redis,数据库

      需求背景
      Redis是内存数据库,数据都是存储在内存中,为避免进程意外退出导致数据的永久丢失,需要定期将Redis中的数据以某种形式(数据或命令)从内存保存到硬盘;当下次Redis重启时,利用持久化文件实现数据恢复。此外,为了灾备,可将持久化文件拷贝到一个远程位置。
      Redis支持四种持久化方式:

      • RDB
      • AOF
      • 虚拟内存
      • Diskstore

      在设计思路上,前两种是基于全部数据都在内存中,即小数据量存储;而后两种方式则是作者在尝试存储数据超过物理内存时,即大数据量存储。后两种仍然是在实验阶段,vm 方式基本已经被作者放弃,海量数据存储方面并不是 Redis 所擅长的领域。

      虚拟内存

      即visual memory方式,Redis用来进行用户空间的数据换入换出的一个策略,此种方式在实现的效果上比较差,主要问题是代码复杂,重启慢,复制慢等,目前已经被作者放弃。
      当key很小而value很大时,使用VM的效果会比较好,因为这样节约的内存比较大。
      当key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,可考虑将key,value组合成一个新的value。
      ​​​vm-max-threads​​参数设置访问swap文件的线程数,设置最好不要超过机器的核数;设置为0,则所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟,但是对数据完整性有很好的保证。

      Diskstore

      Diskstore方式是作者放弃虚拟内存方式后选择的一种新的实现方式,即传统的B-tree方式,目前仍在实验阶段。

      RDB

      概述

      即定时快照方式(snapshot),将当前进程中的数据生成快照保存到硬盘,因此也称作快照持久化,文件后缀是rdb,RDB文件是经过压缩的二进制文件。

      由于AOF优先级更高,当AOF开启时,Redis会优先加载AOF文件来恢复数据,其次自动执行RDB文件的读取实现数据恢复。服务器载入RDB文件期间处于阻塞状态,直到载入完成为止。另外若开启RDB文件校验,且文件损坏,则Redis启动失败,启动失败原因输出到日志中。

      该持久化方式实际是在 Redis 内部一个定时器事件,每隔固定时间去检查当前数据发生的改变次数与时间是否满足配置的持久化触发的条件,如果满足则通过操作系统 fork 调用来创建出一个子进程,子进程默认会与父进程共享相同的地址空间,通过子进程来遍历整个内存来进行存储操作,而主进程则仍然可以提供服务,当有写入时由操作系统按照内存页为单位来进行 ​​copy-on-write​​ 保证父子进程之间不会互相影响。当子进程完成写RDB文件,用新文件替换老文件。缺点:定时快照只是代表一段时间内的内存映像,所以系统重启会丢失上次快照与重启之间所有的数据。

      触发方式

      1. 手动触发
        save和bgsave命令都可以生成二进制文件​​​dump.rdb​​。save命令会阻塞Redis服务器进程,直到RDB文件创建完毕为止;在Redis服务器阻塞期间,服务器不能处理任何命令请求。而bgsave命令会创建一个子进程,由子进程来负责创建RDB文件,父进程(即Redis主进程)则继续处理请求。save会阻塞,已废弃,线上生产环境不推荐使用。故而,自动触发使用的是bgsave命令。
      2. 自动触发
        有3种情况自动触发RDB文件的bgsave:
      1. ​​save m n​​:配置文件,指定当m秒内发生n次变化时,会触发bgsave。
      2. 在主从复制场景下,如果从节点执行全量复制操作,则主节点会执行bgsave命令,并将RDB文件发送给从节点
      3. 执行shutdown命令时

      配置

      ​​save m n​​​:没有此配置,相当于自动的RDB持久化关闭
      ​​​stop-writes-on-bgsave-error yes​​​:当bgsave出现错误时,Redis是否停止执行写命令;设置为yes,则当硬盘出现问题时,可以及时发现,避免数据丢失;设置为no,则Redis无视bgsave的错误继续执行写命令,当对Redis服务器的系统(尤其是硬盘)使用监控时,该选项考虑设置为no
      ​​​rdbcompression yes​​​:是否开启RDB文件压缩
      ​​​rdbchecksum yes​​​:是否开启RDB文件校验,在写入文件和读取文件时都起作用;关闭此配置,在写入文件和读取文件时大约能带来10%的性能提升,但无法监测到数据损坏
      ​​​dbfilename dump.rdb​​​:RDB文件名
      ​​​dir ./​​:RDB、AOF文件所在目录

      实现原理

      ​​save m n​​是通过serverCron函数、dirty计数器、和lastsave时间戳来实现的。serverCron是Redis服务器的周期性操作函数,默认每隔100ms执行一次;该函数对服务器的状态进行维护,其中一项工作就是检查 save m n 配置的条件是否满足,如果满足就执行bgsave。

      dirty计数器是Redis服务器维持的一个状态,记录上一次执行bgsave/save命令后,服务器状态进行多少次修改(包括增删改);而当save/bgsave执行完成后,会将dirty重新置为0。dirty记录的是服务器进行多少次修改,而不是客户端执行多少修改数据的命令。

      lastsave时间戳也是Redis服务器维持的一个状态,记录的是上一次成功执行save/bgsave的时间。

      save m n的原理如下:每隔100ms,执行serverCron函数;在serverCron函数中,遍历save m n配置的保存条件,只要有一个条件满足,就进行bgsave。对于每一个save m n条件,只有下面两条同时满足时才算满足:

      1. 当前时间-lastsave > m
      2. dirty >= n

      执行流程

      Redis系列之持久化机制

      1. Redis父进程首先判断:当前是否在执行save,或bgsave/bgrewriteaof的子进程,如果在执行则bgsave命令直接返回。bgsave/bgrewriteaof 的子进程不能同时执行,主要是基于性能方面的考虑:两个并发的子进程同时执行大量的磁盘写操作,可能引起严重的性能问题。
      2. 父进程执行fork操作创建子进程,这个过程中父进程是阻塞的,Redis不能执行来自客户端的任何命令
      3. 父进程fork后,bgsave命令返回”Background saving started”信息并不再阻塞父进程,并可以响应其他命令
      4. 子进程创建RDB文件,根据父进程内存快照生成临时快照文件,完成后对原有文件进行原子替换
      5. 子进程发送信号给父进程表示完成,父进程更新统计信息

      文件结构

      RDB文件的概况图:

      ----------------------------# RDB文件是二进制的,所以并不存在回车换行来分隔一行一行.
      52 45 44 49 53 # 以字符串 "REDIS" 开头
      30 30 30 33 # RDB 的版本号,大端存储,比如左边这个表示版本号为0003
      ----------------------------
      FE 00 # FE = FE表示数据库编号,Redis支持多个库,以数字编号,这里00表示第0个数据库
      ----------------------------# Key-Value 对存储开始
      FD $length-encoding # FD 表示过期时间,过期时间是用 length encoding 编码存储
      $value-type # 1 个字节用于表示value的类型,比如set,hash,list,zset等
      $string-encoded-key # Key 值,通过string encoding 编码,同样后面会讲到
      $encoded-value # Value值,根据不同的Value类型采用不同的编码方式
      ----------------------------
      FC $length-encoding # FC 表示毫秒级的过期时间,后面的具体时间用length encoding编码存储
      $value-type # 同上,也是一个字节的value类型
      $string-encoded-key # 同样是以 string encoding 编码的 Key值
      $encoded-value # 同样是以对应的数据类型编码的 Value 值
      ----------------------------
      $value-type # 下面是没有过期时间设置的 Key-Value对,为防止冲突,数据类型不会以 FD, FC, FE, FF 开头
      $string-encoded-key
      $encoded-value
      ----------------------------
      FE $length-encoding # 下一个库开始,库的编号用 length encoding 编码
      ----------------------------
      ... # 继续存储这个数据库的 Key-Value 对
      FF ## FF:RDB文件结束的标志

      首先存储一个REDIS字符串(验证作用,表示是RDB文件),redis的版本信息(用4个字节,以大端big endian方式存储和读取),具体的数据库,结束符EOF,检验和。关键是databases,存储多个数据库,数据库按照编号顺序存储,0号数据库存储完,才轮到1,一直到最后一个数据库。

      Redis系列之持久化机制

       

      每一个数据库存储方式如下,首先一个1字节的常量SELECTDB,表示切换db,下一个数据库的编号,它的长度是可变的,db里面具体的key-value对的数据。

      Redis系列之持久化机制

       

      ​​key_value_pairs​​则存储具体的键值对信息,包括key、value值,及其数据类型、内部编码、过期时间、压缩信息等。

      int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime, long long now) {
      /* Save the expire time */
      if (expiretime != -1) {
      /* If this key is already expired skip it */
      if (expiretime < now) return 0;
      if (rdbSaveType(rdb,REDIS_RDB_OPCODE_EXPIRETIME_MS) == -1) return -1;
      if (rdbSaveMillisecondTime(rdb,expiretime) == -1) return -1;
      }
      /* Save type, key, value */
      if (rdbSaveObjectType(rdb,val) == -1) return -1;
      if (rdbSaveStringObject(rdb,key) == -1) return -1;
      if (rdbSaveObject(rdb,val) == -1) return -1;
      return 1;
      }

      存储时先检查expire time,如果已经过期则不存储,否则将expire time存下来。即使是存储expire time,也是先存储它的类型为REDIS_RDB_OPCODE_EXPIRETIME_MS,然后再存储具体过期时间。接下来存储真正的key-value对,首先存储value的类型,然后存储key(它按照字符串存储),然后存储value

      Redis系列之持久化机制

       

      在rdbsaveobject中,会根据val的不同类型,按照不同的方式存储,不过从根本上来看,最终都是转换成字符串存储,比如val是一个linklist,那么先存储整个list的字节数,然后遍历这个list,把数据取出来,依次按照string写入文件。对于hash table,也是先计算字节数,然后依次取出hash table中的dictEntry,按照string的方式存储它的key和value,然后存储下一个dictEntry。 总之,RDB的存储方式,对一个key-value对,会先存储expire time(如果有的话),然后是value的类型,然后存储key(字符串方式),然后根据value的类型和底层实现方式,将value转换成字符串存储。

      当redis再启动时,RDB文件中保存数据库的号码,以及它包含的key-value对,以及每个key-value对中value的具体类型,实现方式,和数据,redis只要顺序读取文件,然后恢复object即可。由于保存有expire time,发现当前时间晚于expire time,即数据已经过期,则不恢复这个key-value对。

      子进程复制父进程的地址空间,即子进程拥有父进程fork时的数据库,子进程执行save的操作,把它从父进程那儿继承来的数据库写入一个temp文件即可。在子进程复制期间,redis会记录数据库的修改次数(dirty)。当子进程完成时,发送给父进程SIGUSR1信号,父进程捕捉到这个信号,就知道子进程完成复制,然后父进程将子进程保存的temp文件改名为真正的RDB文件(即真正保存成功了才改成目标文件,这才是保险的做法)。然后记录下这一次save的结束时间。

      问题

      1. 执行bgsave耗费较长,不够实时:在子进程保存期间,父进程的数据库已经被修改,而父进程只是记录修改的次数(dirty),被没有进行修正操作。使得RDB保存的不是实时的数据库。
      2. redis在serve cron的时候,会根据dirty数目和上次保存的时间,来判断是否符合条件,符合条件就进行bgsave,任意时刻只能有一个子进程来进行后台保存,因为保存是个很费I/O的操作,多个进程大量I/O效率不高,而且不好管理。
      3. 当系统停止,或无意中Redis被kill掉,写入Redis的数据会发生丢失。

      压缩

      Redis默认采用LZF算法对RDB文件进行压缩。RDB文件的压缩并不是针对整个文件进行的,而是对数据库中的字符串进行的,且只有在字符串达到一定长度(20字节)时才会进行。压缩比较耗时,但能大大减小RDB文件的体积,因此压缩默认开启;可通过命令关闭:​​config set rdbcompression no​​。

      AOF

      即Append Only File,将Redis执行的每次写命令记录到单独的日志文件中。类似MySQL基于statement的binlog方式,即每条会使Redis内存数据发生改变的命令都会追加到一个log文件中。

      配置

      Redis默认开启RDB关闭AOF。

      appendonly no # 是否开启AOF
      appendfilename "appendonly.aof" # AOF文件名
      dir ./ # RDB文件和AOF文件所在目录
      appendfsync everysec # fsync持久化策略
      no-appendfsync-on-rewrite no # AOF重写期间是否禁止fsync;如果开启该选项,可以减轻文件重写时CPU和硬盘的负载(尤其是硬盘),但是可能会丢失AOF重写期间的数据;需要在负载和安全性之间进行平衡
      auto-aof-rewrite-percentage 100 # 文件重写触发条件之一,aof_current_size和aof_base_size的比值
      auto-aof-rewrite-min-size 64mb # 文件重写触发提交之一,文件的最小体积
      aof-load-truncated yes:如果AOF文件结尾损坏,Redis启动时是否仍载入AOF文件,默认开启
      aof_current_size # 当前AOF大小
      aof_base_size # 上一次重写时AOF大小

      加载

      当AOF开启,但AOF文件不存在时,即使RDB文件存在也不会加载(更早的一些版本可能会加载,但3.0不会)。

      文件校验:与RDB类似,如果文件损坏,则日志中会打印错误,Redis启动失败。但若AOF文件结尾不完整(机器突然宕机等导致),且​​aof-load-truncated​​参数开启,则日志中会输出警告,Redis忽略掉AOF文件的尾部,启动成功。

      伪客户端:Redis的命令只能在客户端上下文中执行,而载入AOF文件时命令是直接从文件中读取的,并不是由客户端发送。故Redis服务器在载入AOF文件之前,会创建一个没有网络连接的客户端,之后用它来执行AOF文件中的命令,命令执行的效果与带网络连接的客户端完全一样。

      核心流程

      主要包括三个步骤:

      1. 命令追加append:将Redis的写命令追加到缓冲区​​aof_buf​​,不是直接写入文件,主要是为了避免每次有写命令都直接写入硬盘,导致硬盘IO成为Redis负载的瓶颈。命令追加的格式是Redis命令请求的协议格式,一种纯文本格式,兼容性好、可读性强、容易处理、操作简单避免二次开销等优点。在AOF文件中,除了用于指定数据库的select命令是由Redis添加的,其他都是客户端发送来的写命令。
      2. 文件写入write和文件同步sync:根据不同的同步策略将​​aof_buf​​​中的内容同步到硬盘;Redis提供多种AOF缓存区的同步文件策略,策略涉及到操作系统的write函数和fsync函数。为了提高文件写入效率,在现代操作系统中,当用户调用write函数将数据写入文件时,操作系统通常会将数据暂存到一个内存缓冲区里,当缓冲区被填满或超过指定时限后,才真正将缓冲区的数据写入到硬盘里。可以提高效率,但也有安全问题:如果计算机停机,内存缓冲区中的数据会丢失;因此系统同时提供​​fsync​​​、​​fdatasync​​​等同步函数,可以强制操作系统立刻将缓冲区中的数据写入到硬盘里,从而确保数据的安全性。AOF缓存区的同步文件策略由参数​​appendfsync​​控制:
      • always:命令写入​​aof_buf​​后立即调用系统fsync操作同步到AOF文件,fsync完成后线程返回。每次有写命令都要同步到AOF文件,硬盘IO成为性能瓶颈,Redis只能支持大约几百TPS写入。即便是使用固态硬盘(SSD),每秒大约也只能处理几万个命令,而且会大大降低SSD的寿命。
      • no:命令写入​​aof_buf​​后调用系统write操作,不对AOF文件做fsync同步;同步由操作系统负责,通常同步周期为30秒。文件同步的时间不可控,且缓冲区中堆积的数据会很多,数据安全性无法保证。
      • everysec:命令写入​​aof_buf​​后调用系统write操作,write完成后线程返回;fsync同步文件操作由专门的线程每秒调用一次。everysec是前述两种策略的折中,是性能和数据安全性的平衡,因此是Redis的默认配置,也是推荐配置。
      1. 文件重写(rewrite):定期重写AOF文件,达到压缩的目的。

      重写

      rewrite,Redis服务器执行的写命令越来越多,AOF文件也会越来越大;过大的AOF文件影响服务器的正常运行,也会导致数据恢复需要的时间过长。文件重写是指定期重写AOF文件,减小AOF文件的体积。把Redis进程内的数据转化为写命令,同步到新的AOF文件;不会对旧的AOF文件进行任何读取、写入操作。

      对于AOF持久化来说,文件重写虽然是强烈推荐的,但并不是必须的;即使没有文件重写,数据也可以被持久化并在Redis启动的时候导入;因此在一些实现中,会关闭自动的文件重写,然后通过定时任务在每天的某一时刻定时执行。

      文件重写可以压缩AOF文件:

      1. 删除过期的数据、无效的命令
      2. 合并重复的命令:为了防止单条命令过大造成客户端缓冲区溢出,对于list、set、hash、zset类型的key,并不一定只使用一条命令;而是以某个常量为界将命令拆分为多条。这个常量在​​redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD​​定义,不可更改,3.0+版本中值是64。

      重写流程

      Redis系列之持久化机制

      1. Redis父进程首先判断当前是否存在正在执行 bgsave/bgrewriteaof的子进程,如果存在则bgrewriteaof命令直接返回,如果存在bgsave命令则等bgsave执行完成后再执行。主要是基于性能方面考虑。
      2. 父进程执行fork操作创建子进程,这个过程中父进程是阻塞的。
      3. 3.1) 父进程fork后,bgrewriteaof命令返回​​Background append only file rewrite started​​​信息并不再阻塞父进程,并可以响应其他命令。Redis的所有写命令依然写入AOF缓冲区,并根据appendfsync策略同步到硬盘,保证原有AOF机制的正确。
        3.2) 由于fork操作使用写时复制技术,子进程只能共享fork操作时的内存数据。由于父进程依然在响应命令,因此Redis使用AOF重写缓冲区​​​aof_rewrite_buf​​​保存这部分数据,防止新AOF文件生成期间丢失这部分数据。也就是说,bgrewriteaof执行期间,Redis的写命令同时追加到​​aof_buf​​​和​​aof_rewirte_buf​​两个缓冲区。
      4. 子进程根据内存快照,按照命令合并规则写入到新的AOF文件。
      5. 5.1) 子进程写完新的AOF文件后,向父进程发信号,父进程更新统计信息,具体可以通过​​info persistence​​​查看。
        5.2) 父进程把AOF重写缓冲区的数据写入到新的AOF文件,保证新AOF文件所保存的数据库状态和服务器当前状态一致。
        5.3) 使用新的AOF文件替换老文件,完成AOF重写。

      触发

      rewrite触发,分为手动触发和自动触发:

      • 手动触发:直接调用​​bgrewriteaof​​命令,与bgsave有些类似:都是fork子进程进行具体的工作,且都只有在fork时阻塞。
      • 自动触发:根据​​auto-aof-rewrite-min-size​​​和​​auto-aof-rewrite-percentage​​​两个参数确定触发时机,同时满足时才会自动触发AOF重写。另外,​​auto-aof-rewrite-percentage​​​参数由​​aof_current_size​​​、​​aof_base_size​​​两个决定。注:可通过​​info persistence​​命令查看参数值。

      注意:

      1. 重写由父进程fork子进程进行
      2. 重写期间Redis执行的写命令,需要追加到新的AOF文件中,为此Redis引入了aof_rewrite_buf缓存。

      缺点

      追加 log 文件可能导致体积过大,当系统重启恢复数据时如果是AOF的方式则加载数据会非常慢,几十G的数据可能需要几小时才能加载完,当然这个耗时并不是因为磁盘文件读取速度慢,而是由于读取的所有命令都要在内存中执行一遍。由于每条命令都要写 log,所以使用AOF的方式,Redis 的读写性能也会有所下降。

      AOF文件格式,保存的是一条条命令,首先存储命令长度,然后存储命令,分隔符。
      redis server中有一个​​​sds aof_buf​​​,如果AOF持久化打开的话,每个修改数据库的命令都会存入这个​​aof_buf​​​(保存的是AOF文件中命令格式的字符串),然后event loop每循环一次,在​​server cron​​​中调用​​flushaofbuf​​​,把​​aof_buf​​​中的命令写入AOF文件(其实是write,真正写入的是内核缓冲区),再清空​​aof_buf​​,进入下一次loop。数据库的所有变化,都可以通过AOF文件中的命令来还原,达到保存数据库的效果。

      ​​flushaofbuf​​调用write,它只是把数据写入内核缓冲区,真正写入文件时内核自己决定的,可能需要延后一段时间。redis支持配置,可以配置每次写入后sync,则在redis里面调用sync,将内核中的数据写入文件,这不过这要耗费一次系统调用,耗费时间而已。还可以配置策略为1秒钟sync一次,则redis会开启一个后台线程(所以说redis不是单线程,只是单eventloop而已),这个后台线程会每一秒调用一次sync。RDB的时候为什么没有考虑sync的事情呢?因为RDB是一次性存储的,不像AOF这样多次存储,RDB的时候调用一次sync也没什么影响,而且使用bg save的时候,子进程会自己退出(exit),这时候exit函数内会冲刷缓冲区,自动写入文件中。

      如果不想使用aof_buf保存每次的修改命令,也可以使用aof持久化。redis提供​​aof_rewrite​​,即根据现有的数据库生成命令,然后把命令写入aof文件中。进行aof_rewrite的时候,redis变量每个数据库,然后根据key-value对中value的具体类型,生成不同的命令,比如是list,则它生成一个保存list的命令,这个命令里包含了保存该list所需要的的数据,如果这个list数据过长,还会分成多条命令,先创建这个list,然后往list里面添加元素,总之,就是根据数据反向生成保存数据的命令。然后将这些命令存储aof文件,这样不就和aof append达到同样的效果了么?

      AOF格式也支持后台模式。执行​​aof_bgrewrite​​时,也是先fork一个子进程,让子进程进行aof_rewrite,把它复制的数据库写入一个临时文件,然后写完后用信号通知父进程。父进程判断子进程的退出信息是否正确,然后将临时文件更名成最终的AOF文件。

      在子进程持久化期间,父进程的数据库可能有更新,怎么把这个更新通知子进程呢?进程间通信?

      在子进程执行aof_bgrewrite期间,父进程会保存所有对数据库有更改的操作的命令(增,删除,改等),把他们保存在​​aof_rewrite_buf_blocks​​​链表中,每个block都可以保存命令,存不下时,新申请block,然后放入链表后面即可。当子进程通知完成保存后,父进程将​​aof_rewrite_buf_blocks​​的命令append进AOF文件就可以。

      至于AOF文件的载入,也就是一条一条的执行AOF文件里面的命令而已。不过考虑到这些命令就是客户端发送给redis的命令,所以redis干脆生成一个假的客户端,它没有和redis建立网络连接,而是直接执行命令即可。首先搞清楚,这里的假的客户端,并不是真正的客户端,而是存储在redis里面的客户端的信息,里面有写和读的缓冲区,它是存在于redis服务器中的。直接读入AOF的命令,放入客户端的读缓冲区中,然后执行这个客户端的命令即可完成AOF文件的载入。

      // 创建伪客户端
      fakeClient = createFakeClient();
      while(命令不为空) {
      // 获取一条命令的参数信息 argc, argv
      // 执行
      fakeClient->argc = argc;
      fakeClient->argv = argv;
      cmd->proc(fakeClient);
      }

      RDB vs AOF

      bgsave做镜像全量持久化,AOF做增量持久化。
      AOF持久化的实时性更好,即当进程意外退出时丢失的数据更少,因此AOF是目前主流的持久化方式,不过RDB持久化仍然有其用武之地。

      RDB保存的只是最终的数据库,它是一个结果。AOF不同于RDB保存db的数据,它保存的是一条条建立数据库的命令。

      综合

      在redis实例重启时,优先使用aof来恢复内存的状态,如果没有aof日志,就会使用rdb文件来恢复。
      aof文件过大恢复时间过长怎么办?定期做aof重写,压缩aof文件日志大小。Redis4.0之后有了混合持久化的功能,将bgsave的全量和aof的增量做融合处理,这样既保证了恢复的效率又兼顾了数据的安全性。
      如果对方追问那如果突然机器掉电会怎样?取决于aof日志sync属性的配置,如果不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据。

      RDB适合灾难恢复
      AOF:把所有的对 Redis 的服务器进行修改的命令都存到一个文件里,命令的集合。
      每一个写命令都通过 write 函数追加到 ​​​appendonly.aof​​​ 中。
      缺点是对于相同的数据集来说,AOF 的文件体积通常要大于 RDB 文件的体积。根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB。

      参考

      ​​Redis持久化-AOF​​深入学习Redis持久化
      ​​Redis RDB文件格式全解析​​

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.51cto.com/u_15851118/5805389,作者:johnny233,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:Kubesphere设置mysql的网络映射

      下一篇:154-docker 安装mysql 区分大小写

      相关文章

      2025-05-19 09:05:01

      项目更新到公网服务器的操作步骤

      项目更新到公网服务器的操作步骤

      2025-05-19 09:05:01
      公网 , 数据库 , 文件 , 更新 , 服务器
      2025-05-19 09:04:53

      Django rest froamwork-ModelSerializer

      Django rest froamwork-ModelSerializer

      2025-05-19 09:04:53
      django , sqlite , 数据库
      2025-05-19 09:04:38

      mysql只有在任务处于完成状态才能运行

      mysql只有在任务处于完成状态才能运行

      2025-05-19 09:04:38
      MySQL , 任务 , 数据库 , 查询 , 状态
      2025-05-19 09:04:30

      设置28401事件后启动数据库时报错ORA-49100

      设置28401事件后启动数据库时报错ORA-49100

      2025-05-19 09:04:30
      ORA , 数据库 , 时报
      2025-05-14 10:03:13

      MySQL 索引优化以及慢查询优化

      MySQL 是一种广泛使用的关系型数据库管理系统,因其性能优异和使用便捷而备受欢迎。然而,随着数据量的增长和查询复杂度的增加,性能瓶颈也变得越来越明显。

      2025-05-14 10:03:13
      MySQL , 优化 , 使用 , 性能 , 数据库 , 查询 , 索引
      2025-05-14 10:03:05

      Oracle数据库用户权限分析

      Oracle数据库用户权限分析

      2025-05-14 10:03:05
      Oracle , 分析 , 数据库 , 权限 , 用户
      2025-05-14 10:02:48

      互斥锁解决redis缓存击穿

      在高并发系统中,Redis 缓存是一种常见的性能优化方式。然而,缓存击穿问题也伴随着高并发访问而来。

      2025-05-14 10:02:48
      Redis , 互斥 , 数据库 , 线程 , 缓存 , 请求
      2025-05-14 10:02:48

      SQL Server 账号管理1

      SQL Server 账号管理主要包含登录名、用户、架构、角色等管理。通过对账号的管理可以有效的提高数据库系统的安全性,规范运维及使用。

      2025-05-14 10:02:48
      Server , SQL , 对象 , 数据库 , 权限 , 用户
      2025-05-14 10:02:48

      SQL Server 事务日志体系结构1--基本术语

      事务包括对数据库的一次更改或一系列更改。它有一个明确开始和明确结束。开始时使用BEGIN TRANSACTION语句,或者SQL Server会自动为您开始一个事务。

      2025-05-14 10:02:48
      Server , SQL , 事务 , 数据库 , 日志 , 磁盘
      2025-05-13 09:51:17

      dblogin登陆数据库时报错ORA-04060

      dblogin登陆数据库时报错ORA-04060

      2025-05-13 09:51:17
      ORA , 数据库 , 时报
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5246567

      查看更多

      最新文章

      Django rest froamwork-ModelSerializer

      2025-05-19 09:04:53

      mysql只有在任务处于完成状态才能运行

      2025-05-19 09:04:38

      设置28401事件后启动数据库时报错ORA-49100

      2025-05-19 09:04:30

      MySQL 索引优化以及慢查询优化

      2025-05-14 10:03:13

      Oracle数据库用户权限分析

      2025-05-14 10:03:05

      SQL Server 账号管理1

      2025-05-14 10:02:48

      查看更多

      热门文章

      redis-数据操作-键命令

      2023-03-29 10:07:52

      Nacos数据持久化到MySQL

      2023-05-12 07:20:56

      MySQL的间隙锁

      2023-05-12 07:20:56

      ​云原生微服务K8s容器编排第七章之ETCD的使用及备份

      2023-03-16 07:45:55

      Reids持久化

      2023-05-16 09:44:09

      k8s的operator-hub中的redis-operator的redis-cluster的CreateRedisLeaderService处理

      2022-11-08 07:33:08

      查看更多

      热门标签

      数据库 mysql 字符串 数据结构 MySQL 算法 redis oracle java sql python 数据 索引 SQL 查询
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      【TDengine 时序数据库,在物联网的应用】

      Windows 安装mysql数据库

      批量更新数据问题

      文总结MySQL各种锁

      多种方法解决java.sql.SQLSyntaxErrorException: Unknown database ‘xxx‘的错误

      MySQL数据库中创建表并给某个字段添加数据

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号