Redis原理--持久化

devtools/2025/3/20 15:06:00/

Redis的数据都保存在内存,如果Redis宕机,数据将会全部丢失,因此必须有一种机制来保证Redis里的数据不会因为故障而丢失,这种机制就是Redis的持久化机制。

Redis持久化机制

1、快照

快照是一次全量备份,快照是内存数据的二进制序列化形式,在存储上非常紧凑。

2、AOF日志

AOF日志是连续的增量备份,AOF日志记录是内存数据修改的指令记录文本。AOF日志在长期运行过程中会无比庞大,数据库重启时需要加载AOF日志进行指令重放,这个过程无比漫长,因此需要定期进行AOF重写,给AOF瘦身。

快照原理

我们知道Redis是单线程服务,Redis在处理服务请求的同时,还有进行内存快照。而内存快照需要将数据写到磁盘,进行IO操作,可文件的IO操作不能使用多路复用API。此外,那Redis是如何处理的呢?---Redis使用操作系统的多进程COW(Copy On Write)来实现快照持久化。

Redis在持久化时会调用glibc函数的fork产生一个子进程,快照持久化完全交给子进程处理,父进程继续处理客户端请求。

子进程做数据持久化不会修改现有的内存数据结构,它只是对数据结构进行遍历读取,然后序列化写到磁盘。但是父进程不一样,它必须持续服务客户端请求,然后对内存数据结构进行不间断的修改。

这个时候就会用到操作系统的COW机制来进行数据页面的分离。

如上图所示,数据段是由很多操作系统页面组合而成,当父进程对其中的一个页面的数据进行修改时,会将被共享的页面复制一份分离出来,然后对这个复制的页面进行修改。这时子进程相应的页面是没有变化的,还是进程产生时那一瞬间的数据。

随着父进程修改的持续进行,越来越多的共享页面被分离出来 ,内存就会持续增长,但是不会超出数据内存的2倍大小。另外,Redis实例里冷数据占比往往比较高,所以很少出现所有页面都被分离的情况。

子进程因为数据没有变化看,它能看到的丝毫内存里数据在进程产生的一瞬间就凝固了,再也不会改变。这就是为什么Redis的持久化叫快照的原因。

AOF原理

AOF日志存储的是Redis服务器的顺序指令序列,AOF日志只记录对内存进行修改的指令记录。

Redis会在收到客户端修改指令后,进行参数校验,逻辑处理,如果没有问题,就立即将该指令文本存储到AOF日志中。也就是说,先执行指令才将日志存盘。

AOF在长期运行过程中,会越拉越大,需要定期进行瘦身。Redis提供了bgrewriteaof指令对AOF日志进行瘦身,其原理就是开辟一个子进程对内存进行遍历,转换成一系列Redis的操作指令,序列化到一个新的AOF日志中。序列化完毕后再将操作期间发生的增量AOF日志追加到这个新的AOF日志文件中,追加完毕后就立即替代旧的AOF文件了,瘦身工作就完成了。

AOF日志是以文件的形式存在的,当程序对AOF日志文件进行写操作时,实际上是将内容写到了内核为文件描述符分配的一个内核缓存中,然后内核会异步将数据刷到磁盘中。

Linux的glibc提供了fsync(int fd)函数可以将指定文件的内容强制从内核缓存刷新到磁盘,但是fsync是磁盘IO操作很慢。生产环境中通常是1S调用一次fsync。

混合持久化

重启 Redis 时,我们很少使用 rdb 来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志相对于使用 rdb 来说要慢很多,这样在Redis 实例很大的时候,启动需要花费很长的时间。
Redis 4.0 为了解决这个问题,带来了一个新的持久化选项--混合持久化。将 rdb 文件的内容和增量的 AOF 日志文件存在一起。这里的AOF 日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小。于是在 Redis 重启的时候,可以先加载rdb 的内容,然后再重放增量AOF 日志。就可以完全替代之前的AOF 全量文件重放,重启效率因此得到大幅提升。


http://www.ppmy.cn/devtools/168652.html

相关文章

最近比突出的DeepSeek与ChatGPT的详细比较分析

引言 随着人工智能技术的快速发展,自然语言处理(NLP)领域涌现出了许多强大的模型和工具。DeepSeek和ChatGPT作为其中的代表,各自在特定领域和应用场景中展现了卓越的性能。本文将从多个维度对DeepSeek和ChatGPT进行比较分析&…

Java学习打卡-Day19-Set、HashSet、LinkedHashSet

Set 接口 无序(添加和取出顺序不一致)(但取出顺序固定)。没有索引。不允许重复,所以最多一个null。遍历方式 迭代器增强for循环不能使用普通for循环索引方式。 HashSet 实现了Set接口,具有相应特征。底…

Java 集合框架

一、引言 在 Java 编程中,集合是一种非常重要的数据结构,它可以用来存储和管理一组对象。Java 集合框架提供了一套丰富的接口和类,用于处理不同类型的集合,如列表、集合、映射等。通过使用集合框架,开发者可以更高效地处理数据,提高代码的可维护性和可扩展性。 二、Jav…

WEB攻防-PHP反序列化-字符串逃逸

目录 前置知识 字符串逃逸-减少 字符串逃逸-增多 前置知识 1.PHP 在反序列化时,语法是以 ; 作为字段的分隔,以 } 作为结尾,在结束符}之后的任何内容不会影响反序列化的后的结果 class people{ public $namelili; public $age20; } var_du…

跨系统投屏:Realme手机(远程)投屏到Linux系统的简单方法

家里长辈年纪上来了,有点老花眼,平常看手机总是觉得字体不够大,还一个劲儿地将手机拿很远。其实那台手机的字体已经调到最大了。 为了让长辈刷手机的时候可以轻松快乐一点,我们帮他将手机投屏到电脑上。毕竟电脑屏幕比手机大多了&…

正则表达式(可用于MySQL、C++、Python)

正则表达式(Regular Expression,简称 regex 或 regexp)是一种用于描述文本模式的字符串。它通过特定的语法规则,允许你匹配、搜索和操作字符串中的内容。 正则表达式可以用来: 匹配文本:可以在字符串中查…

【Linux】浅谈环境变量和进程地址空间

一、环境变量 基本概念 环境变量(Environment Variables)是操作系统提供的一种机制,用于存储和传递配置信息、系统参数、用户偏好设置等。 环境变量的作用 配置程序行为: 程序可以通过环境变量获取配置信息,例如日…

13-动态规划-最长公共子序列

题目 来源 24. 最长公共子序列 思路 不想打字&#xff0c;援引自最长公共子序列 (LCS) 详解例题模板&#xff08;全&#xff09;-CSDN博客 图示举例&#xff1a; 其余详见代码 代码 #include<bits/stdc.h> using namespace std; const int N110; int f[N][N]; int m…