文章目录
😊 @ 作者:Lion J
💖 @ 主页: https://blog.csdn.net/weixin_69252724
🎉 @ 主题:Redis__数据持久化
⏱️ @ 创作时间:2024年05月01日
这里写目录标题
- 文章目录
- Redis的持久化
-
- RDB持久化是什么?
- AOF持久化
-
- [什么是 AOF 持久化?](#什么是 AOF 持久化?)
- AOF的工作流程
- [AOF 持久化方式有哪些?](#AOF 持久化方式有哪些?)
- AOF为什么是在命令执行之后记录日志?
- AOF重写是什么?
- AOF的写操作的原理?
- [如何选择RDB AOF?](#如何选择RDB AOF?)
由于Redis是缓存数据库, 但是为了保证在某些特殊情况下, 比如要求数据的重用 机器故障,数据库重启,或者是为了同步数据(分布式情况的主从数据库一致)。使用缓存的时候,我们经常需要对内存中的数据进行持久化也就是将内存中的数据写入到硬盘中。
Redis的持久化
使用缓存的时候,我们经常需要对内存中的数据进行持久化也就是将内存中的数据写入到硬盘中。就叫做数据的持久化
Redis 支持持久化,主要是支持 3 种持久化方式:
- 快照(RDB)
- 只追加文件(AOF)
- RDB 和 AOF 的混合持久化
RDB持久化是什么?
Redis 可以通过创建快照来获得存储在内存里面的数据在 某个时间点 上的副本,将创建的快照写入到磁盘中写入到二进制的文件中,默认的文件名为 dump.rdb。
。
Redis 创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis 主从结构,主要用来提高 Redis 性能),还可以将快照留在原地以便重启服务器的时候使用。快照持久化是 Redis 默认采用的持久化方式,在 redis.conf 配置文件中默认有此下配置:
- 触发RDB的快照的时机?\
快照持久化是 Redis 默认采用的持久化方式,在 redis.conf 配置文件中默认有此下配置:
sql
如下配置:
save 900 1 :表示 900 秒钟内至少 1 个键被更改则进行快照。
save 300 10 :表示 300 秒内至少 10 个键被更改则进行快照。
save 60 10000 :表示 60 秒内至少 10000...
如果不需要持久化,那么你可以注释掉所有的 save 行来停用保存功能. 也可以在客户端通过 save
- RDB 创建快照时会阻塞主线程吗?
- save : 同步保存操作,会阻塞 Redis 主线程;
- bgsave : fork 出一个子进程,子进程执行,不会阻塞 Redis 主线程,默认选项。
AOF持久化
什么是 AOF 持久化?
以日志的形式来记录每个写操作,将 Redis 执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis 启动之初会读取该文件
重新构建数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
与快照持久化相比,AOF 持久化的实时性更好。默认情况下 Redis 没有开启 AOF方式的持久化(Redis 6.0 之后已经默认是开启了),可以通过 appendonly 参数开启:
sql
appendonly yes
如何持久化
开启 AOF 持久化后每执行一条会更改 Redis 中的数据的命令,Redis 就会将该命令写入到 AOF 缓冲区 server.aof_buf 中 ,然后再写入到 AOF 文件中 (此时还在系统内核缓存区未同步到磁盘),最后再根据持久化方式( fsync策略)的配置来决定何时将系统内核缓存区的数据同步到硬盘中的。
同步到磁盘中才算持久化保存,否则依然存在数据丢失的风险. 比如说:系统内核缓存区的数据还未同步,磁盘机器就宕机了,那这部分数据就算丢失了。
AOF 文件的保存位置和 RDB 文件的位置相同,默认的文件名是 appendonly.aof。
AOF的工作流程
- 命令追加(append):所有的写命令会追加到 AOF 缓冲区中。
- 文件写入(write):将 AOF 缓冲区的数据写入到 AOF 文件中。这一步需要调用write函数(系统调用),write将数据写入到了系统内核缓冲区之后直接返回了(延迟写)。注意!!!此时并没有同步到磁盘。
- 文件同步(fsync):AOF 缓冲区根据对应的持久化方式( fsync 策略)向硬盘做同步操作。这一步需要调用 fsync 函数(系统调用), fsync 针对单个文件操作,对其进行强制硬盘同步,fsync 将阻塞直到写入磁盘完成后返回,保证了数据持久化。
- 文件重写(rewrite):随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
- 重启加载(load):当 Redis 重启时,可以加载 AOF 文件进行数据恢复。
- write:写入系统内核缓冲区之后直接返回(仅仅是写到缓冲区),不会立即同步到硬盘。虽然提高了效率,但也带来了数据丢失的风险。同步硬盘操作通常依赖于系统调度机制,
Linux 内核通常为 30s 同步一次,具体值取决于写出的数据量和 I/O 缓冲区的状态。
- fsync:fsync用于强制刷新系统内核缓冲区(同步到到磁盘),确保写磁盘操作结束才会返回。
AOF 持久化方式有哪些?
在 Redis 的配置文件中存在三种不同的 AOF 持久化方式( fsync策略),它们分别是:
- appendfsync always:主线程调用 write 执行写操作后,后台线程( aof_fsync 线程)立即会调用 fsync 函数同步 AOF 文件(刷盘),fsync 完成后线程返回,这样会严重降低 Redis 的性能(write + fsync)。
- appendfsync everysec:主线程调用 write 执行写操作后立即返回,由后台线程( aof_fsync 线程)每秒钟调用 fsync 函数(系统调用)同步一次 AOF 文件(write+fsync,fsync间隔为 1 秒)
- appendfsync no:主线程调用 write 执行写操作后立即返回,让操作系统决定何时进行同步,Linux 下一般为 30 秒一次(write但不fsync,fsync 的时机由操作系统决定)
这 3 种持久化方式的主要区别在于 fsync 同步 AOF 文件的时机(刷盘的时机不一样)。
为了兼顾数据和写入性能,可以考虑 appendfsync everysec 选项 ,让 Redis 每秒同步一次 AOF 文件,Redis 性能受到的影响较小。而且这样即使出现系统崩溃,用户最多只会丢失一秒之内产生的数据。
当硬盘忙于执行写入操作的时候,Redis 还会优雅的放慢自己的速度以便适应硬盘的最大写入速度。
AOF为什么是在命令执行之后记录日志?
关系型数据库(如 MySQL)通常都是执行命令之前记录日志(方便故障恢复,如undo log),而 Redis AOF 持久化机制是在执行完命令之后再记录日志。
- 避免额外的检查开销,AOF 记录日志不会对命令进行语法检查;
- 在命令执行完之后再记录,不会阻塞当前的命令执行。
同时这样也带来了问题 - 如果刚执行完命令 Redis 就宕机会导致对应的修改丢失;
- 可能会阻塞后续其他命令的执行(AOF 记录日志是在 Redis 主线程中进行的)。
在同步策略里,比如每个写命令、每秒钟同步一次等。如果选择了每个写命令都进行同步,那么每次写入操作都会触发一次磁盘同步,可能会导致主线程在等待同步完成时被阻塞。
,这样就会频繁IO操作,与主线程竞争资源
AOF重写是什么?
当 AOF 变得太大时,Redis 能够在后台自动重写 AOF 产生一个新的 AOF 文件,这个新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。
AOF 重写(rewrite) 是一个有歧义的名字,该功能是通过读取数据库中的键值对来实现的,程序无须对现有 AOF 文件进行任何读入、分析或者写入操作。
并不是对本身AOF文件做出任何操作
由于 AOF 重写会进行大量的写入操作,为了避免对 Redis 正常处理命令请求造成影响,Redis 将 AOF 重写程序放到子进程里执行。
AOF的写操作的原理?
- AOF 文件重写期间,Redis 还会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新 AOF 文件期间,记录服务器执行的所有写命令。
- 当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新的 AOF 文件保存的数据库状态与现有的数据库状态一致。
- 最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作。
开启 AOF 重写功能:
可以调用 BGREWRITEAOF 命令手动执行,也可以设置下面两个配置项,让程序自动决定触发时机:
- auto-aof-rewrite-min-size:如果 AOF 文件大小小于该值,则不会触发 AOF 重写。默认值为 64 MB;auto-aof-rewrite-- -------
- percentage:执行 AOF 重写时,当前 AOF 大小(aof_current_size)和上一次重写时 AOF 大小(aof_base_size)的比值。如果当前 AOF 文件大小增加了这个百分比值,将触发 AOF 重写。将此值设置为 0 将禁用自动 AOF 重写。默认值为 100
Redis 7.0 版本之前,如果在重写期间有写入命令,AOF 可能会使用大量内存,重写期间到达的所有写入命令都会写入磁盘两次。
因为此时在原来的AOF上上做文章, 同时新的AOF又是在新的数据上
如何选择RDB AOF?
- RDB 比 AOF 优秀的地方:
- RDB 文件存储的内容是经过压缩的二进制数据, 保存着某个时间点的数据集,文件很小,适合做数据的备份,灾难恢复。AOF 文件存储的是每一次写命令,类似于 MySQL 的 binlog 日志,通常会比 RDB 文件大很多。当 AOF 变得太大时,Redis 能够在后台自动重写 AOF。新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。不过, Redis 7.0 版本之前,如果在重写期间有写入命令,AOF 可能会使用大量内存,重写期间到达的所有写入命令都会写入磁盘两次。
- 使用 RDB 文件恢复数据,直接解析还原数据即可,不需要一条一条地执行命令,速度非常快。而 AOF 则需要依次执行每个写命令,速度非常慢。也就是说,与 AOF 相比,恢复大数据集的时候,RDB 速度更快。
- AOF 比 RDB 优秀的地方:
- RDB 的数据安全性不如 AOF,没有办法实时或者秒级持久化数据。生成 RDB 文件的过程是比较繁重的, 虽然 BGSAVE 子进程写入 RDB 文件的工作不会阻塞主线程,但会对机器的 CPU 资源和内存资源产生影响,严重的情况下甚至会直接把 Redis 服务干宕机。AOF 支持秒级数据丢失(取决 fsync 策略,如果是 everysec,最多丢失 1 秒的数据),仅仅是追加命令到 AOF 文件,操作轻量。
- RDB 文件是以特定的二进制格式保存的,并且在 Redis 版本演进中有多个版本的 RDB,所以存在老版本的 Redis 服务不兼容新版本的 RDB 格式的问题。
- AOF 以一种易于理解和解析的格式包含所有操作的日志。你可以轻松地导出 AOF 文件进行分析,你也可以直接操作 AOF 文件来解决一些问题。比如,如果执行FLUSHALL命令意外地刷新了所有内容后,只要 AOF 文件没有被重写,删除最新命令并重启即可恢复之前的状态。