小伙用 12 张图讲明白了 Redis 持久化!(上)

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: 小伙用 12 张图讲明白了 Redis 持久化!

00 前言


很多小伙伴都用 Redis 做缓存,那如果 Redis 服务器宕机,内存中数据全部丢失,应该如何做数据恢复呢?有人说很简单呀,直接从 MySQL 数据库再读回来就得了


这种方式存在两个问题:一是频繁访问 MySQL 数据库,有一定的风险;二是,从界面上来看,从 MySQL 读就不如从 Redis 快。


远哥远哥,那咋办呀?教教我吧。


我用中指抵着小胖的下吧,说到:傻瓜,我们可以做持久化呀。Redis 的持久化分两种,一种是 AOF,另一种是 RDB。来,坐哥哥腿上,我给你好好说道说道。


老规矩,先上张脑图:


640.png


0.1 什么是持久化?


持久化(Persistence),即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、XML 数据文件中等等。持久化是将程序数据在持久状态和瞬时状态间转换的机制。


01 怎么理解 Redis 的单线程?


必须声明一点:Redis 的单线程,是指 Redis 的网络 IO 和键值对读写是由一个线程(主线程)完成的,这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。


1.0 Redis 快的原因?


基于内存


  • 数据都存储在内存里,减少了一些不必要的 I/O 操作,操作速率很快。


高效的数据结构


  • 底层多种数据结构支持不同的数据类型,支持 Redis 存储不同的数据;
  • 不同数据结构的设计,使得数据存储时间复杂度降到最低。


合理的线程模型


  • I/O 多路复用模型同时监听多个客户端连接;
  • 单线程在执行过程中不需要进行上下文切换,减少了耗时。


02 AOF 持久化


AOF(Append Only File) 持久化是通过保存 Redis 服务器所执行的写命令来记录数据库状态,也就是每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾。


修改 redis.conf 配置文件,默认是 appendonly no(关闭状态),将 no 改为 yes 即可开启 AOF 持久化:


appendonly yes


在客户端输入如下命令也可,但是 Redis 服务器重启后会失效。


192.168.17.101:6379> config set appendonly yes
OK


AOF 持久化功能的实现可以分为命令追加(append)、文件写回磁盘两个步骤。


2.0 命令追加


AOF 持久化功能开启时,Redis 在执行完一个写命令之后,会将被执行的写命令追加到服务器状态的 aof_buf 缓冲区的末尾,此时缓冲区的记录还没有写入到 appendonly.aof 文件中


2.0.1 AOF 的格式


AOF 保存的是 Redis 的写命令,比如:执行命令 set testkey testvalue,它存储的内容如下图所示:


640.png


其中,“*3” 表示当前命令有三个部分,每部分都是由 $+ 数字开头,后面紧跟着具体的命令、键或值。这里,数字表示这部分中的命令、键或值一共有多少字节。例如, $3 set 表示这部分有 3 个字节,也就是 set 命令。


2.0.2 写后日志有啥优缺点?


AOF 记录日志的方式被称为写后日志,也就是先执行命令再记录,而 MySQL 中的 redo log、binlog 等都是写前日志。它的写入流程是下图这样的:


640.png


写后有什么优点?


  • 记录 AOF 时不会对命令进行语法检查 ,写后就只记录了执行成功的命令。(避免保存的错误的命令,恢复的时候就完犊子了)
  • 执行完之后再记录,不会阻塞当前的写操作


写后有什么缺陷?


  • 如果执行完一个命令还没来得及写日志就宕机了会造成响应数据丢失。
  • AOF 的写入由主线程处理,如果写入时出现较长耗时,那就会影响主线程处理后续的请求。


你发现没有?写后的两个缺陷都是 AOF 的写入磁盘时相发生的,我们来看看它是怎么写入的呢?


2.1 AOF 写入磁盘


AOF 提供了三个选择,也就是 AOF 配置项 appendfsync 的三个可选值。


  • Always,同步写回:每个写命令执行完,立马同步地将日志写回磁盘;
  • Everysec(默认),每秒写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘;
  • No,操作系统控制的写回:每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。


2.1.0 三种策略的优缺点


针对避免主线程阻塞和减少数据丢失问题,这三种写回策略都无法做到两全其美。主要原因是:


  • Always(同步写回) 基本不丢数据,但是它在每一个写命令后都有一个慢速的落盘操作,影响主线程性能;
  • No(操作系统控制的写回)在写完缓冲区后,继续执行后续的命令,但是落盘的时机已经不在 Redis 手中了,只要 AOF 记录没有写回磁盘,一旦宕机对应的数据就丢失了;
  • Everysec(每秒写回)采用一秒写回一次的频率,避免了 Always 的性能开销,虽然减少了对系统性能的影响,但是如果发生宕机,上一秒内未落盘的命令操作仍然会丢失。


640.png


总结一下就是:想高性能,选择 No 策略;想高可靠性,选择 Always 策略;允许数据有一点丢失,又希望性能别受太大影响,选择 Everysec 策略。


2.2 AOF 恢复数据


不说了,看图:


640.png


2.3 AOF 重写


我不知道你发现没有?AOF 文件是不断地将写命令追加到文件的末尾来记录数据库状态的。写命令不断增加,AOF 体积也越来越大。


有些命令是执行多次更新同一条数据,但其实它是可以合并成同一条命令的。比如:LPUSH 对列表数据做了 6 次更改,但 AOF 只需要记录最后一次更改。因为日志恢复时,只需要执行最后一次更改的命令即可


为了处理这种情况,Redis 提供了 AOF 的重写机制。它的多变一功能,把 6 条写命令合并成一条。如下所示:


640.png


如果你的某些键有成百上千次的修改,重写机制节约的空间就很可观了。


2.3.1 触发重写


有两种触发的方法,一个是调用命令 BGREWRITEAOF;一个是修改配置文件参数。


# 方式一
192.168.17.101:6379> BGREWRITEAOF
Background append only file rewriting started
# 方式二
auto-aof-rewrite-percentage 100 #当前AOF文件大小和上一次重写时AOF文件大小的比值
auto-aof-rewrite-min-size 64mb  #文件的最小体积


2.3.2 重写步骤


  1. 创建子进程进行 AOF 重写
  2. 将客户端的写命令追加到 AOF 重写缓冲区
  3. 子进程完成 AOF 重写工作后,会向父进程发送一个信号
  4. 父进程接收到信号后,将 AOF 重写缓冲区的所有内容写入到新 AOF 文件中
  5. 对新的 AOF 文件进行改名,覆盖现有的 AOF 文件


640.png


2.4 相关配置


# 是否开启AOF功能
appendonly no
# AOF文件件名称
appendfilename "appendonly.aof"
# 写入AOF文件的三种方式
appendfsync always
appendfsync everysec
appendfsync no
# 重写AOF时,是否继续写AOF文件
no-appendfsync-on-rewrite no
# 自动重写AOF文件的条件
auto-aof-rewrite-percentage 100 #百分比
auto-aof-rewrite-min-size 64mb #大小
# 是否忽略最后一条可能存在问题的指令
aof-load-truncated yes


2.5 优缺点

优点


  1. AOF 文件可读性高,分析容易
  2. AOF 文件过大时,自动进行重写
  3. 追加形式,写入时不需要再次读取文件,直接加到末尾


缺点


  1. 相同数据量下,AOF 一般比 RDB 大
  2. AOF 恢复时需要重放命令,恢复速度慢
  3. 根据 fsync 策略,AOF 的速度可能慢于 RDB


相关实践学习
基于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
相关文章
|
1月前
|
存储 监控 负载均衡
保证Redis的高可用性是一个涉及多个层面的任务,主要包括数据持久化、复制与故障转移、集群化部署等方面
【5月更文挑战第15天】保证Redis高可用性涉及数据持久化、复制与故障转移、集群化及优化策略。RDB和AOF是数据持久化方法,哨兵模式确保故障自动恢复。Redis Cluster实现分布式部署,提高负载均衡和容错性。其他措施包括身份认证、多线程、数据压缩和监控报警,以增强安全性和稳定性。通过综合配置与监控,可确保Redis服务的高效、可靠运行。
203 2
|
1天前
|
存储 NoSQL Redis
《面试官之你说我听》:简明的图解Redis RDB持久化、AOF持久化
《面试官之你说我听》:简明的图解Redis RDB持久化、AOF持久化
|
1天前
|
存储 NoSQL 安全
Redis系列学习文章分享---第十五篇(Redis最佳实践--设计优雅的key+合适的数据结构+持久化如何配置+慢查询问题解决)
Redis系列学习文章分享---第十五篇(Redis最佳实践--设计优雅的key+合适的数据结构+持久化如何配置+慢查询问题解决)
7 1
|
2天前
|
存储 缓存 JSON
Redis-持久化-淘汰机制-IO策略
Redis-持久化-淘汰机制-IO策略
|
1月前
|
存储 NoSQL 程序员
Redis(持久化 -- RDB & AOF)
Redis(持久化 -- RDB & AOF)
33 2
|
9天前
|
存储 NoSQL Redis
redis大key对持久化的影响
redis大key对持久化的影响
16 0
|
9天前
|
NoSQL 安全 Redis
redis持久化方式—RDB
redis持久化方式—RDB
25 0
|
9天前
|
缓存 NoSQL 安全
深入理解redis持久化—AOF日志
深入理解redis持久化—AOF日志
20 0
|
29天前
|
存储 缓存 NoSQL
redis 高可用与 持久化
redis 高可用与 持久化
|
1月前
|
NoSQL 算法 Java
【redis源码学习】持久化机制,java程序员面试算法宝典pdf
【redis源码学习】持久化机制,java程序员面试算法宝典pdf