RedisRedis持久化之AOF详解(Redis专栏启动)
Posted 小明java问道之路
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RedisRedis持久化之AOF详解(Redis专栏启动)相关的知识,希望对你有一定的参考价值。
📫作者简介:小明java问道之路,2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建工设优化。文章内容兼具广度深度、大厂技术方案,对待技术喜欢推理加验证,就职于知名金融公司后端高级工程师。
📫 热衷分享,喜欢原创~ 关注我会给你带来一些不一样的认知和成长。
🏆 2022博客之星TOP3 | CSDN博客专家 | 后端领域优质创作者 | CSDN内容合伙人
🏆 InfoQ(极客邦)签约作者、阿里云专家 | 签约博主、51CTO专家 | TOP红人、华为云享专家
🔥如果此文还不错的话,还请👍关注、点赞、收藏三连支持👍一下博主~
🍅 文末获取联系 🍅 👇🏻 精彩专栏推荐订阅收藏 👇🏻
专栏系列(点击解锁)
学习路线(点击解锁)
知识定位
全面讲解MySQL知识与企业级MySQL实战 🔥计算机底层原理🔥
本文目录
本文导读
本文为Redis持久化系列第二篇,上一篇【Redis】Redis持久化之RDB详解,本文讲解兼具广度与深度,首先讲解什么是RedisAOF、如何开启AOF持久化,深入其AOF的原理,AOF持久化实现、AOF数据恢复、AOF三种写回硬盘策略、AOF重写机制,解析RedisAOF要先执行命令后写日志,以及在实战过程中AOF和RDB对比,最后扩展Redis4.0新特性的混合持久化模式。
一、什么是Redis AOF
Redis提供了两种持久性机制:一种是RDB也称为快照模式,一种是AOF日志也称为追加模式。
AOF是一个日志文件,Redis的每个命令都将以AOF格式写入AOF文件,AOF日志仅记录修改内存的指令,AOF日志记录不同于mysql先写入日志然后再执行操作(两阶段提交),AOF是执行成功的命令,然后记录命令在日志文件中,当需要恢复时,直接导入AOF文件以执行其中的记录,并且记录是实时的,AOF日志存储Redis服务器的顺序指令序列。
二、如何开启AOF持久化
AOF 机制默认处于未开启状态,通过在配置文件中将appendonly参数配置为yes来启用AOF持久性。
#修改配置文件:
vim /etc/redis/redis.conf
appendonly yes # 把 no 改为 yes
#确定存储文件名是否正确
appendfilename "appendonly.aof"
#重启服务:
sudo /etc/init.d/redis-server restart
三、AOF的原理
每当修改Redis的命令时,服务器都会将该命令写入appendonly.aof 文件,该文件存储服务器执行的所有修改(成功的)命令。因此,只要服务器执行aof文件,可以达到恢复数据的目的,这个过程也称为命令重演。
1、AOF持久化实现
AOF持久性的实现可以分为:命令追加( append ,当AOF持久性功能打开时,Redis将在执行写入命令后,以协议格式(即RESP,Redis客户端和服务器之间的通信协议)将执行的写入命令附加到Redis服务器维护的AOF缓冲区的末尾。)、文件写入( write,Redis将调用flushAppendOnlyFile函数,以确定是否需要在每个事件周期结束之前将AOF缓存中的内容写入并同步到AOF文件)、文件同步( sync )、文件重写(rewrite)和重启加载(load)这几步。如下图所示
Redis将在执行写操作命令会将命令追加到 server.aof_buf 缓冲区,所有写入命令都将添加到AOF缓存中,然后通过 write() 系统调用,将aof_buf 缓冲区中数据写入aof文件。此时,数据还没有写入硬盘,而是复制到内核缓冲区的页面缓存 page cache,等待内核将数据写入硬盘,内核缓冲区中的数据何时写入硬盘由内核决定。
AOF缓存将根据相应的策略与硬盘同步,AOF日志将越来越大就需要定期重写以实现压缩,当Redis重新启动时,可以加载AOF文件进行数据恢复。
2、AOF数据恢复
AOF文件包含重建Redis数据所需的所有写入命令,因此只要重新读入并执行保存在AOF文件中的写入命令,Redis就可以恢复Redis关闭前的状态。伪客户端是指 Redis命令只能在客户端的上下文中执行,用于加载AOF文件的命令直接来自AOF文件,而不是网络连接。因此,服务器使用没有网络连接的伪客户端来执行保存在AOF文件中的命令。伪客户端执行命令的效果与具有网络连接的客户端的效果完全相同。
3、AOF三种写回硬盘策略
Redis 3 种写回硬盘的策略,说的是在 redis.conf 配置文件中的 appendfsync 配置项可以有以下 3 种参数可填。
Redis将在结束每个事件之前调用 flushAppendOnlyFile() 函数,以确定是否需要将AOF缓存中的内容写入并同步到AOF文件。flushAppendOnlyFile() 函数的行为由redis.conf 配置中appendfsync选项的值决定,有三个可选值:always、everysec和no。
Always(同步写回):在执行每个写操作命令后,AOF日志数据将同步写回硬盘;
Everysec(每秒写回):在执行每个写操作命令后,将命令写入AOF文件的内核缓冲区,然后每秒将缓冲区的内容写回硬盘;
No(操作系统控制的回写)意味着回写硬盘的时间不受Redis控制,而是转移到由操作系统所控制的回写入时间。也就是说,在执行每个写操作命令之后,该命令首先被写入AOF文件的内核缓冲区,然后操作系统决定何时将缓冲区内容写回硬盘。
这三种方法都有缺点:Always(同步写回),如果每次执行后命令都同步到瓷盘中,这会影响主线程的性能;Everysec(每秒回写)使用每秒回写一次的频率,以避免同步回写的性能开销。虽然它减少了对系统性能的影响,但如果发生中断,在最后一秒没有中断的命令操作仍将丢失;No(操作系统控制写回)。保存到磁盘的操作由操作系统控制。只要AOF中没有写回命令,一旦服务器停机,数据就会丢失;
写回策略 | 写回时间 | 优点 | 缺点 |
Always | 同步写回 | 可靠性高,最大程度保证安全性 | 性能开销大 |
Everysec | 每秒写回 | 性能适中 | 宕机时有1秒的数据丢失 |
No | 操作系统控制的回写 | 性能好 | 宕机存在丢失数据较大 |
4、AOF重写机制
重写机制,就是重写旧日志中的多个命令变为新日志中的一个命令。
假设对列表进行n次修改后,一条数据处于“***”状态。只有LPUSH u:list“**” 命令可以恢复数据,这为n-1个命令节省了空间,AOF重写后,日志文件将收缩,但将整个数据库的最新数据的操作日志写回磁盘仍然是一个耗时的过程。
重写不会阻塞主线程,重写过程由后台线程bgrewriteaof完成,这也是为了避免阻塞主线程,从而导致数据库性能下降。
Redis设置了一个AOF重写缓冲区,该缓冲区将在服务器创建子进程后使用,当Redis执行写命令时,它将同时向AOF缓冲区和AOF重写缓冲区发送写命令。当子进程完成AOF重写时,它将向父进程发送信号。在接收到信号后,父进程将调用信号处理函数将AOF重写缓冲区中的所有内容写入新的AOF文件,以确保新AOF文件保存的数据库状态与服务器的当前状态一致,并重命名新的AOF文件,自动覆盖现有AOF文件并完成新旧文件的替换继续处理客户端请求命令。
5、为什么Redis AOF要先执行命令后写日志?
Redis在向AOF里面记录日志的时候,不会首先检查这些命令。因此,如果它先记日志然后执行命令,则可能会在日志中记录错误的命令,Redis在使用日志恢复数据时可能会出错,如果Redis也先写日志,然后再操作,那么AOF日志中会有许多无效/错误的命令记录。
与MySQL和其他数据库的事务机制相比,Redis事务可以称为弱事务。如果事务中发生错误,将继续执行。如果事务失败,Redis不会回滚,对于此类事务,将有许多命令无法成功修改数据,如果先写日志,也会有很多无效的命令。
这两种风险都与AOF写回磁盘的时间有关。如果控制线写命令,再写AOF日志就可以解决这两个问题。
四、AOF和RDB对比
RDB持久化 | AOF持久化 |
---|---|
全量备份,一次保存整个数据库。 | 增量备份,一次只保存一个修改数据库的命令。 |
每次执行持久化操作的间隔时间较长。 | 保存的间隔默认为一秒钟(Everysec) |
数据保存为二进制格式,其还原速度快。 | 使用文本格式还原数据,所以数据还原速度一般。 |
执行 SAVE 命令时会阻塞服务器,但手动或者自动触发的 BGSAVE 不会阻塞服务器 | AOF持久化无论何时都不会阻塞服务器。 |
1、进行数据恢复时,既有 dump.rdb文件,又有 appendonly.aof 文件,应该首先通过appendonly.aof 恢复数据,这可以最大程度地确保数据安全。
2、只需要数据备份,不太关心一小部分数据的丢失,那么可以使用RDB模式,RDB文件也易于迁移并放入多个实例中进行数据恢复
五、Redis4.0的混合持久化模式
Redis 4.0的新特性是混合持久化模式,混合持久化模式同时使用RDB快照和AOF日志的混合持久模式,将RDB文件内容和增量AOF文件内容存储在同一个文件(相同的AOF格式文件)中,可以通过配置参数 aof-use-rdb-preamble 来启用混合持久性模式,config get aof-use-rdb-preamble命令进行查看。
由于RDB快照数据和AOF日志数据存储在同一个文件中,因此AOF格式文件不再只存储全部AOF日志,而是第一部分存储RDB快照,第二部分存储从RDB快照持久化开始到持久化结束的增量AOF日志。因此,RDB数据通常占大多数,AOF日志只是增量日志的一小部分
在混合持久策略下,当重新启动下一个Redis实例时,首先加载RDB快照的内容,然后重放增量AOF日志。这可以取代以前的RDB完全导入或AOF完全重放。
总结
本文为Redis持久化系列第二篇,上一篇【Redis】Redis持久化之RDB详解,本文讲解兼具广度与深度,首先讲解什么是RedisAOF、如何开启AOF持久化,深入其AOF的原理,AOF持久化实现、AOF数据恢复、AOF三种写回硬盘策略、AOF重写机制,解析RedisAOF要先执行命令后写日志,以及在实战过程中AOF和RDB对比,最后扩展Redis4.0新特性的混合持久化模式。
Redis 总结
目 录
什么是Redis
Redis(Remote Dictionary Server) 是一个使用 C 语言编写的,开源的(BSD许可)高性能非关系型(NoSQL)的键值对数据库。
Redis 可以存储键和五种不同类型的值之间的映射。键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。
redis每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。另外redis也常用来做分布式锁。
Redis为什么快?
- 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。
同时数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是O(1); - 数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的;
- 采用单线程。
避免了不必要的上下文切换和竞争条件,不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗; - 使用多路 I/O 复用模型,非阻塞 IO;
- 使用底层模型不同。
它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis 直接自己构建了 VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;
Redis有哪些常用的数据类型?
Redis主要有5种数据类型,包括String,List,Set,Zset,Hash
String (字符串、整数或者浮点数): 做简单的键值对缓存
List 列表: 存储一些列表型的数据结构
set 无序集合: 交集、并集、差集的操作
hash 包含键值对的无序散列表: 结构化的数据,比如一个对象
zset 有序集合 : 去重但可以排序
Redis RDB和AOF持久化的区别,如何选择?
什么是Redis持久化?
持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。
Redis 的持久化机制是什么?
Redis 提供两种持久化机制 RDB(默认) 和 AOF 机制:
-
RDB:Redis DataBase,把当前数据生成快照保存在硬盘上。
RDB是Redis默认的持久化方式。按照一定的时间将内存的数据以快照的形式保存到硬盘中,对应产生的数据文件为dump.rdb。通过配置文件中的save参数来定义的周期。 -
AOF:Append Only File持久化,记录每次对数据的操作到硬盘上。
将Redis执行的每次写命令记录到单独的日志文件中,当重启Redis会重新将持久化的日志中文件恢复数据。
RDB和AOF的优缺点
- AOF文件比RDB更新频率高,优先使用AOF还原数据。
- AOF比RDB更安全也更大
- RDB性能比AOF好
- 如果两个都配了优先加载AOF
如何选择
1、一般来说, 如果想达到足以媲美PostgreSQL的数据安全性,应该同时使用两种持久化功能。在这种情况下,当 Redis 重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整。
2、如果可以承受数分钟以内的数据丢失,那么你可以只使用RDB持久化。
3、只使用AOF持久化,但并不推荐。因为定时生成RDB快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比AOF恢复的速度要快,除此之外,使用RDB还可以避免AOF程序的bug。
4、如果只希望数据在服务器运行的时候存在,可以不使用任何持久化方式。
如何解决缓存击穿、缓存穿透、雪崩问题?
缓存击穿
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案
- 设置热点数据永远不过期。
- 加互斥锁
缓存穿透
对某个一定不存在的数据进行请求,该请求将会穿透缓存到达数据库。
缓存穿透是指缓存和数据库中都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。
解决方案
- 对这些不存在的数据缓存一个空数据;
- 对这类请求进行过滤。
缓存雪崩
指的是由于数据没有被加载到缓存中,或者缓存数据在同一时间大面积失效(过期),又或者缓存服务器宕机,导致大量的请求都到达数据库。
在有缓存的系统中,系统非常依赖于缓存,缓存分担了很大一部分的数据请求。当发生缓存雪崩时,数据库无法处理这么大的请求,导致数据库崩溃。
解决方案:
- 为了防止缓存在同一时间大面积过期导致的缓存雪崩,可以通过观察用户行为,合理设置缓存过期时间来实现
(缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。) - 一般并发量不是特别多的时候,使用最多的解决方案是加锁排队
- 给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存。
- 为了防止缓存服务器宕机出现的缓存雪崩,可以使用分布式缓存,分布式缓存中每一个节点只缓存部分的数据,当某个节点宕机时可以保证其它节点的缓存仍然可用。
- 也可以进行缓存预热,避免在系统刚启动不久由于还未将大量数据进行缓存而导致缓存雪崩。
以上是关于RedisRedis持久化之AOF详解(Redis专栏启动)的主要内容,如果未能解决你的问题,请参考以下文章
RedisRedis持久化之RDB详解(Redis专栏启动)