首页 > 数据库 >Redis稳定性之战:AOF日志支撑数据持久化

Redis稳定性之战:AOF日志支撑数据持久化

时间:2024-03-12 09:34:20浏览次数:14  
标签:AOF 快照 文件 Redis aof RDB 日志

Redis24篇集合

1 介绍

AOF(Append Only File)持久化:以独立日志的方式存储了 Redis 服务器的顺序指令序列,并只记录对内存进行修改的指令。
当Redis服务发生雪崩等故障时,可以重启服务并重新执行AOF文件中的指令达到恢复数据的目的。也就是说,通过重放(replay),来重新建立 Redis 当前实例的内存数据结构。这种模式有没有很熟悉,可以联想到MySQL主从同步时的relay log。
相对于咱们上一篇介绍的《RDB内存快照提供持久化能力》定点快照的做法,AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式。

2 AOF实现日志记录

2.1 开启AOF日志记录

1、 开启AOF日志记录:在redis.conf文件中,找到 APPEND ONLY MODE 设置

appendonly yes  # 默认不开启, 为 no

2、配置默认文件名:在redis.conf文件中设置

appendfilename “appendonly.aof”

2.2 执行流程

image

流程如上图所示,我们解析如下:

2.2.1 将所有的写命令(set、hset)Append 到aof_buf缓冲区中

Redis 接收到 set keyName someValue 命令的时候,会先将数据写到内存,Redis 会按照如下格式写入 AOF 文件。

  1. *3:表示当前指令分为三个部分,每个部分都是 $ + 数字开头,后面是3部分的具体内容:指令、键、值。
  2. 数字:表示这部分的命令、键、值多占用的字节大小。比如 $3表示这部分包含 3 个字符,也就是 set 的长度。

我们看看一个典型的aof文件示例,为了清晰表示,下面的注释都是手动加的:

[root@localhost bin]#vim appendonly.aof
#  执行 set key value
*3
$3           # 这边代表set命令,长度为3
set
$9 
user_name      # 这边代表keyName,长度为9
$5 
brand      #  这边代表keyValue,长度为5


# 执行 mset key1 1 ,key2 2 ,key33 3
# aof日志如下:
*7  # 本批命令需要往下读7行非 $ 开始的命令
$4  #接着读取4个字节宽度,‘mset’长度为4,记为 $4
mset
$4  #接着读取4个字节宽度,‘key1’长度为4,记为 $4
key1
$1  #接着读取1个字节宽度,‘1’长度为1,记为 $1
1
$4
key2
$1
2
$5  #接着读取的字节宽度,‘$key33’长度为5,记为 $5
key33
$1
3

2.2.2 AOF缓冲区根据策略向硬盘做sync同步

AOF为什么把命令append到aof_buf中,然后再进行同步?
这是因为Redis使用单进程响应命令(参考笔者这篇《深刻理解高性能Redis的本质》),如果每次写AOF文件命令都直接持久化到硬盘,那么操作会是不是被间断,且性能完全取决于硬盘I/O负载。这个跟 MySQL 就没啥区别了。
先写入缓冲区aof_buf中,Redis可以提供多种缓冲区同步硬盘的策略,在性能、安全、数据可靠性方面做出平衡。

同步策略需关注以下几个配置:

1、 appendfsync 模式

appendfsync always  # 接受写命令后立即写入磁盘,强持久化但执行慢,不推荐
appendfsync everysec # 每秒写入磁盘一次, 性能和持久化方面做了折中, 推荐
appendfsync no  #  依赖操作系统自身同步的配置和策略,性能较佳,但是没法保证实时和完全持久化

2、no-appendfsync-on-rewrite
在 AOF 重写期间是否禁用 fsync。这可以提高重写性能,但可能会增加数据丢失的风险。

# 默认值:no
# 可选值:yes 或 no
no-appendfsync-on-rewrite yes

2.2.3 AOF文件Rewrite实现压缩

随着AOF文件越来越大,需要定期对AOF文件进行重写,达到压缩减负的目的,避免AOF文件过大导致性能和数据可靠性问题。
重写后的AOF文件变小的原因主要有以下几点:
1、进程内已超时的数据不再写入:在重写过程中,Redis不会将已经超时的数据写入新的AOF文件,这有助于减少不必要的数据记录。
2、删除无效命令:旧的AOF文件中可能包含无效的命令,如del key1hdel key2srem keysset a111等。重写过程会识别并删除这些无效命令,只保留最终数据的写入命令,从而减小了文件大小。
3、合并多条写命令:为了进一步优化AOF文件的大小,重写过程会将多条写命令合并为一个。例如,lpush list alpush list blpush list c可以合并为lpush list a b c。这种合并减少了命令的数量,进而减小了AOF文件的大小。
4、防止单条命令过大:对于某些操作类型(如list、set、hash、zset),为了防止单条命令过大造成客户端缓冲区溢出,重写过程会以64个元素为界拆分多条命令。虽然这在一定程度上可能增加了命令的数量,但它确保了每条命令的大小都在可控范围内,有助于维持整体文件大小的合理性。
总之AOF重写降低了文件占用空间,同时提升加载性能,因为更小的AOF 文件可以更快地被Redis加载。

AOF重写关注以下配置:
1、auto-aof-rewrite-percentage
触发 AOF 重写的增长百分比。例如,如果当前 AOF 文件大小是 100MB,并且这个值设置为 100,那么当 AOF 文件增长到 200MB 时,说明增长了100%,Redis 会尝试重写 AOF。

# 默认值:`100`
`auto-aof-rewrite-percentage 100`

2、auto-aof-rewrite-min-size

AOF 文件的最小大小,以便触发重写。即使 AOF 文件的增长百分比超过了 auto-aof-rewrite-percentage 设置的值,但如果文件大小小于这个值,Redis 也不会触发重写。

# 默认值:`64mb`
auto-aof-rewrite-min-size 64mb

image

2.2.4 故障重启时的数据恢复

当Redis服务器重启时,可以加载AOF文件进行数据恢复。
image

流程如下:

  1. 当AOF和RDB文件同时存在时,优先加载AOF
  2. 若关闭了AOF(apendonly no),则加载RDB文件
  3. 加载AOF/RDB成功之后,redis重启成功。如果无相关的持久化,则直接启动成功。
  4. 如果AOF/RDB 数据恢复存在错误,则启动失败,并打印输出错误信息

2.3 RDB和AOF的比较和混合持久化

咱们上一篇介绍了《RDB内存快照提供持久化能力》定点快照的用户,那RDB跟AOF究竟孰优孰虑?
现实情况下,无论使用RDB或者AOF都差点意思。使用 rdb 来恢复内存状态,势必会丢失一部分数据。使用 AOF 日志重放,重放对性能有一定的影响,而且在 Redis 实例很大的情况下,需要花费很长的时间。
Redis 4.0 解决了这个问题,才用了一个新的持久化模式——混合持久化,该 混合模式 默认是关闭状态的。
将 RDB 文件的内容和 rdb快照时间点之后的增量的 AOF 日志文件存在一起。这时候 AOF 日志不需要再是全量的日志,而是最近一次快照时间点之后到当下发生的增量 AOF 日志,通常这部分 AOF 日志很小。
所以执行有如下顺序:

  • 查找rdb内容,如果存在先加载 rdb内容再 重放剩余的 aof。
  • 没有rdb内容,直接以aof格式重放整个文件。
    这样快照就不用频繁的执行,同时由于 AOF 只需要记录最近一次快照之后的数据,不需要记录所有的操作,避免了出现单次重放文件过大的问题。

开启混合持久化模式:

aof-use-rdb-preamble yes

这个设置告诉Redis在AOF重写时使用混合持久化模式。当这个选项设置为yes时,重写后的AOF文件将包含RDB格式的数据前缀和AOF格式的增量修改操作。

总结

  • RDB提供了快照模式,记录某个时间的Redis内存状态。RDB设计了 bgsave 和写时复制,尽可能避免执行快照期间对读写指令的影响,但是频繁快照会给磁盘带来压力以及 fork 阻塞主线程。需把握频率。
  • AOF 日志存储了 Redis 服务的顺序指令序列,通过重放(replay)指令来写入日志文件,并通过写回策略来避免高频读写给Redis带来压力。
  • RDB快照的照片时间间隔,必然会带来数据缺失,如果允许分钟级别的数据丢失,可以只使用 RDB。
  • 如果只用 AOF,写回策略优先使用 everysec 的配置选项,因为它在可靠性和性能之间取了一个平衡。
  • 数据不能丢失时,内存快照和 AOF 的混合使用是一个很好的选择。

标签:AOF,快照,文件,Redis,aof,RDB,日志
From: https://www.cnblogs.com/wzh2010/p/18049659

相关文章

  • Redis安装之集群-哨兵模式(sentinel)模式
    官网说明:https://redis.io/docs/management/sentinel/一、背景Redis主从复制模型在一定程度上解决了读写分离、容灾恢复、数据备份、水平扩容支撑高并发的问题,但仍存在单点故障问题,即Mater宕机后,集群将无法提供写服务。二、方案原理主从复制的问题在于Mater宕机后,Slave......
  • 浮木云学习日志(10)---页面框架布局
    随着对浮木云软件设计开发平台的深入了解,发现浮木云真的是一个很人性化的工具。前两次对浮木云的布局容器、弹性容器和栅格容器进行了简单的了解,同时也知道这些容器是页面是设计框架的基础,本次我会根据自己对容器的了解进行的一个简单的页面框架构建。感兴趣的小伙伴可以直接去他......
  • php反序列化和redis未授权
    1、centos系统安装http,php,redis服务更新yum源httpphpredis2、使用redis未授权漏洞写入phpinfo3、配合gopher协议ssrf漏洞向服务器写入任意数据4、演示ssh免密码登录5、画图解释PHP反序列化漏洞的原理6、预习一下java反序列化漏洞,包括继承,重写等概念......
  • Redis安装之Redis7主从复制(replica)安装(Linux版)
    官网说明:https://redis.io/docs/management/replication/一.背景单机部署存在单点故障及数据丢失问题,为了实现读写分离容灾恢复数据备份水平扩容支撑高并发等功能,Redis可基于主从复制的特性搭建集群。二.方案原理2.1.读写分离Master主机负责写操作,Slave从机负......
  • 3月11号(工程日志第五天)
    所学时间:4小时代码行数:413行博客园数:1篇所学知识:今天将学习了安卓开发对于数据库sqlite的增删改查操作,并学会了部分的试图修改操作。MainActivitypackagecom.example.myapplication;importandroidx.appcompat.app.AppCompatActivity;importandroid.annotation.Suppre......
  • k02_redis命令
    链接redis方式一:redis-cli-h192.168.88.129-p6379-aroot方式二:redis-cli-h192.168.88.129-p6379AUTHrootredis通用命令help@string 查看帮助keys* 查询所有keyMSETkvk1v1 批量插入exists 确定一个键是否存在常见常见命令信息help@s......
  • 11_redis事务
    redis事务数据库事务所有的数据库操作都必须一次性完成,要么成功,要么失败。redis事务可以一次执行多个命令,本质上是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不被其他命令插入,不许加载(不许被不属于该集合的命令插入)。开启:以MULTI开始一个事务入......
  • redis常用命令
    1、启动Redis>redis-server[--port6379]如果命令参数过多,建议通过配置文件来启动Redis。>redis-server[xx/xx/redis.conf]6379是Redis默认端口号。2、连接Redis>./redis-cli[-h127.0.0.1-p6379]3、停止Redis>redis-clishutdown >killredis-pid以上......
  • [springboot] SpringBoot启动成功后因actuator健康检测报:Redis health check failed/
    0序背景:项目中引入了spring-boot-starter-actuator健康检测模块<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>1问题描述确认微服务刚启动后,因K8S集群周期性定时(默认每隔1......
  • 日志
    LogBack配置文件Maven项目中xml要放在resource,文件夹下面<?xmlversion="1.0"encoding="UTF-8"?><configuration><!--CONSOLE:表示当前的日志信息是可以输出到控制台的。--><appendername="CONSOLE"class="ch.qos.logb......