《Redis核心技术与实战》学习总结(四)——Redis的持久化机制
mhr18 2024-11-04 12:48 39 浏览 0 评论
Redis的持久化机制
一旦Redis服务器宕机,内存中的数据会全部丢失。如果单靠从后端DB中恢复,一来会给DB带来巨大的压力,二来从DB拉取数据性能较低会导致应用程序响应变慢。因此,Redis的数据持久化很重要,而且不能从后端DB中恢复。
Redis提供的数据持久化机制只要包括两个:
- AOF(Append Only File)日志
- RDB 快照
在Redis 4.0之后,新增了混合持久化机制,它将AOF 和 RDB的优点结合了起来。
AOF日志
所谓AOF,即Append Only File,意思是只会追加写的文件。在Redis中,AOF日志最大的特点就是写后日志,即Redis执行命令将数据写入内存后才记录日志。
延伸:MySQL使用的是WAL日志,即Write Ahead Log 写前日志。例如redo log,它记录的是修改后的数据。不过,AOF却是记录的命令,这些命令是以文本形式保存的。
AOF中存了什么东西?
刚刚说到,AOF记录的是Redis接收的命令,这些命令都是以文本形式保存的。
例如,下图展示了一个AOF日志的内容:
解读:"*3" 表示命令由三个部分组成,"$3 set"表示这部分有三个字节,即"set"命令有三个字节。同理,后续"$7 testkey"表示该部分有七个字节,即"testkey"命令有七个字节。第三部分同理,不再赘述。
AOF的优点是什么?
Redis在向AOF中记录日志时,为了避免额外的开销,不会对写入的命令进行语法检查。因此,如果采用先写日志方式,那么日志中就有可能会记录错误的命令,导致Redis在使用AOF恢复数据的时候,可能会出错。
因此,AOF采用后写日志,只有命令成功执行之后才会被记录到日志中。否则,系统就会向客户端报错。所以,AOF的优点主要就在于可以避免记录错误命令的情况,并且由于是写后日志,因此它也不会阻塞当前的写操作。
AOF的缺点是什么?
AOF有两个潜在的风险点:
一是如果将Redis作为DB用的话(当然一般情况很少这样选型),如果某个命令因为服务器宕机没有记入日志,那么Redis无法用AOF日志进行数据恢复。换句话说,Redis接收的命令及其相应数据有丢失的风险。
二是如果在写AOF日志到磁盘时磁盘写压力过大,会导致写盘很慢,由于AOF日志也是在主线程中执行,因此可能会导致后续的操作无法执行。换句话说,AOF日志可能会给下一个操作带来阻塞的风险。
如何规避AOF的潜在风险?
从刚刚的介绍中可以了解到,AOF的两个潜在的风险点都和AOF写回磁盘的时机有关,换句话说,要想规避风险,只要能控制一个写命令执行完成后AOF日志写回磁盘的时机 就能解决。
在Redis中,AOF机制提供了三个配置项供我们选择:
(1)Always,即同步写回:每个命令执行完,立马同步将日志写到磁盘;
画外音>此选项可以做到基本不丢数据,但是性能较差,会影响主线程性能。
(2)Everysec,即每秒写回:每个命令执行完,只是先将日志写到AOF文件的内存缓冲区,每隔一秒钟再把缓冲区中的内容写到磁盘;
画外音>此选项可以减少对主线程性能的影响,但是如果发生宕机,仍然存在命令操作丢失的风险。
(3)No,即不主动控制何时写回,由操作系统来控制写回:每个命令执行完,先将日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区的内容写回磁盘。
画外音>此选项性能较好,但回收策略就变成了黑盒子,且宕机时可能会出现数据丢失较多的风险。
这三种写回时机策略的优缺点总结在下图中:
可以看到,这三种策略在可靠性上是从高到低,而在性能上则是从低到高。这和关系型数据库的隔离级别项是类似的,安全性越高,则性能越低。
一般情况下,允许数据有一点丢失,又希望性能还不错的话,请选择Everysec策略。这也是系统设计中最常见的原则-trade off(权衡取舍),我们需要在多个指标之间做取舍。
如何保持Redis的高性能?
我们都知道Redis具有较高的性能,那么,对于AOF日志来说,它是否有可能拖累Redis性能?答案是可能的,如果写入的日志文件过大,就有可能拖累性能。
Note:日志文件过大不仅对写回磁盘时造成性能影响,在使用日志进行故障恢复时也有影响。因为,Redis的单线程设计,日志中的命令只能一条一条按顺序执行,“重放”过程会变慢。
那么,日志文件过大该怎么破?
AOF提供了重写机制,即如果AOF需要一次记录的命令太多,Redis会进行重写:Redis根据现状创建一个新的AOF文件,它会读取所有键值对,然后对每一个键值对用一条命令记录它的写入。
换句话说,重写机制就是在给AOF日志文件做瘦身,具体实现其实就是将旧日志中的多条命令换成一条新的命令,即“多变一”。下图就展示了这样的一个实例:
从上图中可以看出,重写后的日志较旧日志节省了好几条命令的空间,这对于有可能会被修改成百上千次的key/value来说,能节省的空间当然就更大了。
其次,AOF的重写机制是由后台子进程(bgrewriteaof)来执行的,它不会影响主线程,进而避免阻塞主线程导致性能下降。
AOF的非阻塞重写过程如下图所示:
从上图中可以看出,当AOF重写的时候Redis会先fork出一个后台子进程,它会执行一次内存拷贝用于接下来的重写。然后,Redis会使用两个日志(正在使用的AOF日志 和 新的AOF重写日志)来保证在重写过程中,新写入的数据不会丢失。
用蒋德钧老师的八个字概括AOF重写的过程:“一个拷贝,两处日志”。
AOF重写何时被触发?
在Redis中,有两个配置项在控制AOF重写的触发时机。
如果AOF文件大小同时超出下面这两个配置项时,会自动触发AOF重写。
auto-aof-rewrite-min-size:
表示运行AOF重写时文件的最小大小,默认为64MB
auto-aof-rewrite-percentage:
表示比上次重写后的日志文件体量增加了多少百分比,默认为100%
RDB内存快照
RDB(Redis DataBase)内存快照是Redis提供的第二个持久化机制,它既能避免数据丢失,又能更快地恢复数据。
所谓内存快照,就是指内存中的数据在某一个时刻的状态记录,它类似于照片。在Redis中,这些照片是就后缀为RDB的文件。
与AOF的对比
与AOF相比,RDB记录的是某一个时刻的数据(二进制的形式)而不是操作命令,因此,在做数据恢复的时候,我们可以直接将RDB文件读入内存就可以完成恢复。
这样一来,就可以避免AOF的缺点:需要按照顺序逐一重新执行操作命令所带来的低效的性能问题。
画外音>但是内存快照也并不是最优选项。
全量快照与增量快照
当Redis中数据并不多时,我们可以直接做RDB的全量快照,这样一次性就记录了所有的数据,一个都不少。
但是,当数据量越来越大之后,做全量快照的过程中写入磁盘的时间会逐渐增大,全量数据越多,RDB文件就会越大,往磁盘上写数据的时间开销也就越大。
因为,Redis的单线程模型(这里仅探讨6.0之前的Redis单线程版本)决定了开发者需要避免阻塞主线程的所有操作。当全量数据越大,RDB快照的写入操作就越有概率会阻塞主线程。
因此,Redis也提供了增量快照,即一次全量快照之后,后续的快照只需要对修改的数据进行快照记录,就可以避免每次全量快照的开销。
RDB文件如何生成?
Redis提供了两个命令 save 和 bgsave 来生成RDB文件,其中:
(1)save 在主线程上执行,会导致主线程阻塞;(不建议使用)
(2)bgsave 会在一个后台子进程中专门用于写入RBD文件,它不会引起主线程阻塞;(它也是Redis RDB生成的默认配置)
画外音>为什么是子进程而不是子线程?因为Redis就是一个进程,而且是一个只有单线程的进程,一般也将其单线程称为主线程。
下图展示了bgsave的执行过程:
因此,我们可以通过bgsave命令来做全量快照操作。
RDB做快照时数据能修改吗?
刚刚提到,RDB做快照和拍照类似,当你拍照的时候,也是希望在那一瞬间不希望被拍的人乱动。数据,也是同理。
但是,如果在给数据做快照时,数据不能被修改,那无疑等同于停服,会给业务造成一定影响。
幸运的是,Redis早已经帮我们想好了这个问题,Redis借助了OS提供的写时复制(Copy-On-Write, COW)技术,支持在执行RDB快照生成的期间,正常处理写操作。
下面通过一幅图来介绍COW技术:
总结一下,Redis支持快照期正常处理写操作大概有两个核心步骤:
(1)如果主线程是读取操作,那么主线程和bgsave子进程互不影响;
(2)如果主线程是修改操作,那么主线程打算修改一个key/value时,这个数据就会生成一个副本,主线程会对这个副本进行修改(而不是原来的位置)。同时,bgsave子进程可以把原来位置的数据继续写入RDB文件。
有了这两个核心步骤,Redis在生成RBD文件时既保证了数据完整性,同时又允许对数据做修改,还避免了对正常业务的影响。
多久做一次快照合适?
和拍照类似,“连拍”可以抓住某一时刻连续的单个场景。对数据而言,也是如此,如果快照的间隔变短,那么丢失的数据量也不会很多。
那么,问题来了,多久做一次RDB快照比较合适?
首先,我们需要有一个基本认知:虽然bgsave不会阻塞主线程,但是如果频繁地执行全量快照,也会带来一定的性能问题。
(1)频繁执行全量快照,磁盘压力会变大!因为,多个快照会竞争优先的磁盘带宽,前一个快照还没有做完,后一个又开始了...
(2)虽然bgsave本身不会阻塞主线程,但是fork这个bgsave的创建过程会阻塞主线程!
其次,我们在一次全量快照之后即可做多次增量快照,因此这里说的快照频率一般情况下是指增量快照的间隔时间。
最后,在增量快照操作的间隔期间,Redis需要记住哪些数据被修改了,这也会带来额外的空间开销问题,如下图所示:
因此,虽然RDB较AOF具有恢复速度快的优点,但是快照的频率不太好控制,因此如果频率太低,两次快照之间可能会有较多数据丢失的风险;如果频率太高,会产生较多额外的开销。
混合持久化
在Redis 4.0之后,新增了混合持久化机制,它将AOF 和 RDB的优点结合了起来。
Note:
Redis 4.0通过以下配置即可开启混合持久化(前提条件:先开启AOF):
# aof‐use‐rdb‐preamble yes
Redis 5.0及之后已经默认开启了混合持久化,使用以下命令可以验证:
> config get aof-use-rdb-preamble
1) "aof-use-rdb-preamble"
2) "yes"
简单来说,它的执行策略包括以下两个核心步骤:
(1)RDB内存快照以一定的频率执行;
(2)在两次快照之间使用AOF记录所有的修改命令操作;
混合持久化的执行过程也可以用一幅图展现:
那么,它所具有的优势也就体现了出来:
(1)不用频繁地生成快照,避免频繁fork子进程操作对主线程的影响;
(2)AOF日志只用于两次快照间的命令记录,不需记录所有操作,即避免了日志文件过大,也避免了重写的开销。
如此,它就有点“鱼和熊掌兼得”的味道,即利用了RDB文件的快速恢复性 + AOF只记录操作命令的简单性。它也成为了Redis 5.0及之后版本的默认持久化选项。
End总结
本文总结了Redis持久化的几个核心要点:
(1)AOF是啥,其机制的优缺点
(2)RDB是啥,其机制的优缺点
(3)混合持久化又是啥
关于如何选择持久化方式,蒋德钧老师给出了几点建议:
(1)当数据不能丢失时(即可靠性要求很高的场景),建议使用混合持久化机制;
(2)当允许数据丢失分钟级时,可以只使用RDB快照;
(3)如果一定要只使用AOF,优先使用Everysec配置,因为它在可靠性和性能之间取得了一个平衡;
参考资料
极客时间,蒋德钧《Redis核心技术与实战》
黄建宏,《Redis设计与实现》
拉钩教育,刘海丰《架构设计面试精讲》
作者:Edison Zhou
相关推荐
- 【推荐】一个开源免费、AI 驱动的智能数据管理系统,支持多数据库
-
如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!.前言在当今数据驱动的时代,高效、智能地管理数据已成为企业和个人不可或缺的能力。为了满足这一需求,我们推出了这款开...
- Pure Storage推出统一数据管理云平台及新闪存阵列
-
PureStorage公司今日推出企业数据云(EnterpriseDataCloud),称其为组织在混合环境中存储、管理和使用数据方式的全面架构升级。该公司表示,EDC使组织能够在本地、云端和混...
- 对Java学习的10条建议(对java课程的建议)
-
不少Java的初学者一开始都是信心满满准备迎接挑战,但是经过一段时间的学习之后,多少都会碰到各种挫败,以下北风网就总结一些对于初学者非常有用的建议,希望能够给他们解决现实中的问题。Java编程的准备:...
- SQLShift 重大更新:Oracle→PostgreSQL 存储过程转换功能上线!
-
官网:https://sqlshift.cn/6月,SQLShift迎来重大版本更新!作为国内首个支持Oracle->OceanBase存储过程智能转换的工具,SQLShift在过去一...
- JDK21有没有什么稳定、简单又强势的特性?
-
佳未阿里云开发者2025年03月05日08:30浙江阿里妹导读这篇文章主要介绍了Java虚拟线程的发展及其在AJDK中的实现和优化。阅前声明:本文介绍的内容基于AJDK21.0.5[1]以及以上...
- 「松勤软件测试」网站总出现404 bug?总结8个原因,不信解决不了
-
在进行网站测试的时候,有没有碰到过网站崩溃,打不开,出现404错误等各种现象,如果你碰到了,那么恭喜你,你的网站出问题了,是什么原因导致网站出问题呢,根据松勤软件测试的总结如下:01数据库中的表空间不...
- Java面试题及答案最全总结(2025版)
-
大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Sprin...
- 数据库日常运维工作内容(数据库日常运维 工作内容)
-
#数据库日常运维工作包括哪些内容?#数据库日常运维工作是一个涵盖多个层面的综合性任务,以下是详细的分类和内容说明:一、数据库运维核心工作监控与告警性能监控:实时监控CPU、内存、I/O、连接数、锁等待...
- 分布式之系统底层原理(上)(底层分布式技术)
-
作者:allanpan,腾讯IEG高级后台工程师导言分布式事务是分布式系统必不可少的组成部分,基本上只要实现一个分布式系统就逃不开对分布式事务的支持。本文从分布式事务这个概念切入,尝试对分布式事务...
- oracle 死锁了怎么办?kill 进程 直接上干货
-
1、查看死锁是否存在selectusername,lockwait,status,machine,programfromv$sessionwheresidin(selectsession...
- SpringBoot 各种分页查询方式详解(全网最全)
-
一、分页查询基础概念与原理1.1什么是分页查询分页查询是指将大量数据分割成多个小块(页)进行展示的技术,它是现代Web应用中必不可少的功能。想象一下你去图书馆找书,如果所有书都堆在一张桌子上,你很难...
- 《战场兄弟》全事件攻略 一般事件合同事件红装及隐藏职业攻略
-
《战场兄弟》全事件攻略,一般事件合同事件红装及隐藏职业攻略。《战场兄弟》事件奖励,事件条件。《战场兄弟》是OverhypeStudios制作发行的一款由xcom和桌游为灵感来源,以中世纪、低魔奇幻为...
- LoadRunner(loadrunner录制不到脚本)
-
一、核心组件与工作流程LoadRunner性能测试工具-并发测试-正版软件下载-使用教程-价格-官方代理商的架构围绕三大核心组件构建,形成完整测试闭环:VirtualUserGenerator(...
- Redis数据类型介绍(redis 数据类型)
-
介绍Redis支持五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)及Zset(sortedset:有序集合)。1、字符串类型概述1.1、数据类型Redis支持...
- RMAN备份监控及优化总结(rman备份原理)
-
今天主要介绍一下如何对RMAN备份监控及优化,这里就不讲rman备份的一些原理了,仅供参考。一、监控RMAN备份1、确定备份源与备份设备的最大速度从磁盘读的速度和磁带写的带度、备份的速度不可能超出这两...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)