【Redis原理探索】深入对持久化原理的AOF(专题篇)

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 【Redis原理探索】深入对持久化原理的AOF(专题篇)

前提回顾


AOF的简介


  • Redis的AOF是类似的Log的机制,每次写操作都会写到硬盘上,当系统崩溃时,可以通过AOF来恢复数据。


  • 每个带有写操作的命令被Redis服务器端收到运行时,该命令都会被记录到AOF文件上。由于只是一个append到文件操作(采用的是存储aof_buf中,并且采用异步方法fsync/fdatasync),所以写到硬盘上的操作往往非常快


AOF的实现


Redis AOF机制包括了两件事,AOF和Rewrite。


  • AOF类似于普通数据库管理系统日志恢复点,当AOF文件随着写命令的运行膨胀时,当文件大小触碰到临界时,rewrite会被运行


  • Rewrite会像replication一样,fork出一个子进程,创建一个临时文件,遍历数据库,将每个key、value对输出到临时文件


  • 输出格式就是Redis的命令,但是为了减小文件大小,会将多个key、value对集合起来用一条命令表达


  • 在rewrite期间的写操作会保存在内存的aof_rewrite_buf_block中,rewrite成功后这些操作也会复制到临时文件中,在最后临时文件会代替AOF文件


以上在AOF打开的情况下,如果AOF是关闭的,那么rewrite操作可以通过bgrewriteaof命令来进行。



AOF的流程


image.png


  • Redis Server启动,如果AOF机制打开那么初始化AOF状态,并且如果存在AOF文件,读取AOF文件。随着Redis不断接受命令,每个写命令都被添加到AOF文件,AOF文件膨胀到重写阈值需要重写时又或者接收到客户端的bgrewriteaof命令。


  • fork出一个子进程进行rewrite,而父进程继续接受操作命令,现在的写操作命令都会被额外添加到一个aof_rewrite_buf_blocks缓冲中。


  • 信号,把aof_rewrite_buf_blocks的缓冲添加到rewrite后的AOF文件中,然后切换AOF的文件fd,采用新文件覆盖旧文件。rewrite任务完成,继续第二个步骤。




关键点


  • 由于写操作通常是有缓冲的,有可能AOF操作并没有写到硬盘中,可以通过fsync()/fdatasync()来强制输出到硬盘中


  • 而fsync()的频率可以通过配置文件中的flush策略来指定,可以选择每次事件循环写操作都强制fsync或者每秒fsync至少运行一次


  • **当rewrite子进程开始后,父进程接受到的命令会添加到aof_rewrite_buf_blocks中,使得rewrite成功后,将这些命令添加到新文件中。


  • 在rewrite过程中,原来的AOF也可以选择是否继续添加,由于存在性能上的问题,在rewrite过程中,如果fsync()继续执行,会导致IO性能受损影响Redis性能。所以一般情况下rewrite期间禁止fsync()到旧AOF文件这策略可以在配置文件中修改。(就是在rewrite过程中aof操作的同步机制,可以会暂时停止不会save到aof文件中)。


  • 在rewrite结束后,在将新rewrite文件重命名为配置中指定的文件时,如果旧AOF存在,那么会unlink旧文件并删除


  • 这是就存在一个问题,处理rewrite文件迁移的是主线程,rename(oldpath, newpath)过程会覆盖旧文件,这是rename会unlink(oldfd),而unlink操作会导致block主线程





自动的bgrewriteaof


  • 避免aof文件过大,我们会周期性的做bgrewriteaof来重整aof文件。以前我们会额外的配置crontab在业务低峰期执行这个命令,这额外的增加一个workaroud的脚本任务在大集群里是很糟糕的,不易检查,出错无法即时发现


  • 于是这个自动bgrewriteaof功能被直接加到redis的内部。首先对于aof文件,server对象添加一个字段来记录aof文件的大小server.appendonly_current_size每次aof发生变化都会维护这个字段


aof.c


nwritten = write(server.appendfd,server.aofbuf,sdslen(server.aofbuf));
.....
server.appendonly_current_size += nwritten;
复制代码


bgrewriteaof完毕或者实例启动载入aof数据后也会调用aofUpdateCurrentSize这个函数维护这个字段,同时会记录下此时的aof文件的大小server.auto_aofrewrite_base_size作为基准值,用于接下来判断aof增长率。



aof.c


aofUpdateCurrentSize();
server.auto_aofrewrite_base_size = server.appendonly_current_size;
复制代码


有了当前值和基准值我们就可以判断aof文件的增长情况。另外还需要配置两个参数来判断是否需要自动触发bgrewriteaof。


redis.h


int auto_aofrewrite_perc; /* Rewrite AOF if % growth is > M and... */
off_t auto_aofrewrite_min_size; /* the AOF file is at least N bytes. */
复制代码


  • auto_aofrewrite_perc: AOF文件的大小超过基准百分之多少后触发bgrewriteaof。默认这个值设置为100,意味着当前AOF是基准大小的两倍的时候触发bgrewriteaof把它设置为0可以禁用自动触发的功能


  • auto_aofrewrite_min_size: 当前AOF文件大于多少字节后才触发。避免在aof较小的时候无谓行为。默认大小为64mb。


两个参数都是可以在conf里静态配置,或者通过config set来动态修改的。


redis 127.0.0.1:6379> config get auto-aof-rewrite-percentage
1) "auto-aof-rewrite-percentage"
2) "100"
redis 127.0.0.1:6379> config get auto-aof-rewrite-min-size
1) "auto-aof-rewrite-min-size"
2) "1048576"
redis 127.0.0.1:6379> config get auto-aof-rewrite-min-size
1) "auto-aof-rewrite-min-size"
2) "1048576"
redis 127.0.0.1:6379> config set auto-aof-rewrite-percentage 200
OK
redis 127.0.0.1:6379> config set auto-aof-rewrite-min-size 10485760
OK
复制代码


然后就是触发检查的主逻辑,serverCron时间事件中每次都会检查现有状态和参数来判断是否需要启动bgrewriteaof


redis.c


if (server.bgsavechildpid == -1 &&
              server.bgrewritechildpid == -1 &&
              server.auto_aofrewrite_perc &&
              server.appendonly_current_size > server.auto_aofrewrite_min_size)
          {
             long long base = server.auto_aofrewrite_base_size ?
                             server.auto_aofrewrite_base_size : 1;
             long long growth = (server.appendonly_current_size*100/base) - 100;
             if (growth >= server.auto_aofrewrite_perc) {
                 redisLog(REDIS_NOTICE,"Starting automatic rewriting of AOF on %lld%% growth",growth);
                 rewriteAppendOnlyFileBackground();
             }
         }
复制代码


以上代码显示,如果aof文件增长百分率growth大于auto_aofrewrite_perc,则自动的触发后一个bgrewriteaof




延迟bgrewriteaof


这是个小的改进,手动触发的bgrewriteaof的时候如果同时存在bgsave在备份,会推迟这次操走的事件,设置server.aofrewrite_scheduled=1,待到bgsave结束后的下一次serverCron里才会触发


设置 aofrewrite_scheduled=1


aof.c

void bgrewriteaofCommand(redisClient *c) {
     if (server.bgrewritechildpid != -1) {
         addReplyError(c,"Background append only file rewriting already in 
         progress");
     } else if (server.bgsavechildpid != -1) {
         server.aofrewrite_scheduled = 1;
         addReplyStatus(c,"Background append only file rewriting 
         scheduled");
     } else if (rewriteAppendOnlyFileBackground() == REDIS_OK) {
         addReplyStatus(c,"Background append only file rewriting 
         started");
     } else {
         addReply(c,shared.err);
     }
 }
复制代码



触发bgrewriteaof


redis.c

if (server.bgsavechildpid == -1 && server.bgrewritechildpid == -1 &&
        server.aofrewrite_scheduled){
         rewriteAppendOnlyFileBackground();
    }






相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
打赏
0
0
0
0
379
分享
相关文章
Redis的两种持久化方式---RDB、AOF
通过本文的介绍,我们详细讲解了Redis的两种主要持久化方式:RDB和AOF。每种方式都有其独特的优缺点和适用场景。在实际应用中,可以根据具体需求选择合适的持久化方式,或者同时启用RDB和AOF,以达到最佳效果。希望本文能帮助您更好地理解和应用Redis的持久化机制,构建高效、可靠的数据存储解决方案。
151 79
Redis原理—5.性能和使用总结
本文详细探讨了Redis的阻塞原因、性能优化、缓存相关问题及数据库与缓存的一致性问题。同时还列举了不同缓存操作方案下的并发情况,帮助读者理解并选择合适的缓存管理策略。最终得出结论,在实际应用中应尽量采用“先更新数据库再删除缓存”的方案,并结合异步重试机制来保证数据的一致性和系统的高性能。
Redis原理—5.性能和使用总结
Redis的数据持久化策略有哪些 ?
Redis 提供了两种方式,实现数据的持久化到硬盘。 1. RDB 持久化(全量),是指在指定的时间间隔内将内存中的数据集快照写入磁盘。 2. AOF持久化(增量),以日志的形式记录服务器所处理的每一个写、删除操作 RDB和AOF一起使用, 在Redis4.0版本支持混合持久化方式 ( 设置 aof-use-rdb-preamble yes )
Redis原理—2.单机数据库的实现
本文概述了Redis数据库的核心结构和操作机制。
Redis原理—2.单机数据库的实现
Redis原理—1.Redis数据结构
本文介绍了Redis 的主要数据结构及应用。
Redis原理—1.Redis数据结构
Redis原理—4.核心原理摘要
Redis 是一个基于内存的高性能NoSQL数据库,支持分布式集群和持久化。其网络通信模型采用多路复用监听与文件事件机制,通过单线程串行化处理大量并发请求,确保高效运行。本文主要简单介绍了 Redis 的核心特性。
Redis原理—3.复制、哨兵和集群
详细介绍了Redis的复制原理、哨兵原理和集群原理。
|
3月前
|
Redis 持久化揭秘:选择 RDB、AOF 还是混合持久化?
Redis 是一个内存数据库,意味着它主要将数据存储在内存中,从而能够提供极高的性能。然而,作为内存数据库,Redis 默认情况下的数据不会永久保存。为了确保数据在重启或故障后能够恢复,Redis 提供了几种 **持久化机制**。这些机制允许 Redis 将内存中的数据保存到硬盘上,从而实现数据持久化。
221 22
Redis 持久化揭秘:选择 RDB、AOF 还是混合持久化?
Redis持久化机制 RDB 和 AOF 的选择
Redis持久化机制 RDB 和 AOF 的选择
132 0
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
88 2
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比

热门文章

最新文章