| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> redis 持久化原理 -> 正文阅读 |
|
[大数据]redis 持久化原理 |
前言
我们先来看看演化这个事儿。 软件都是迭代中越做越复杂。redis 也是这样,刚开始做了一个简单功能,通过一定的数据结构组织数据,让你能够相当快的拿到这些数据; 慢慢地,场景越来越多,想要的功能支持越来越强烈;好,redis 慢慢给你实现。 当然,这是功能层面的迭代演进,性能上呢? 首先,我要处理客户端的请求,按照服务端 socket 编程几个步子写,相当容易; 写好之后,你说不行,QPS 至少 10W+;于是,继续改造,写了一套 Reactor 模型来应对网络请求,10W+ 的 QPS 目标达到了。 用了一段时间你又说,这服务一断电,所有数据就没了,我的心血… 能不能靠谱点,想个办法恢复! 于是,又接着写了一个拷贝进程,满足一定条件,就把整个内存快照同步至磁盘,出现断电或者重启,直接从磁盘加载,数据就恢复了,完美!这就是 RDB。 你用了段时间,服务故障崩溃了,重启时 RDB 给你进行了数据恢复,你依然很生气,怎么丢了最近很多数据? 我又想了个办法,干脆把所有的命令都记录下来,下次恢复数据直接重放不就行了?balbala… 很快就写了出来,并且支持三种落盘策略(always, everysec, non)以提升效率,这就是 AOF。 交付的时候,我特意嘱咐道,RDB 和 AOF 要结合使用,数据恢复时,会先加载 RDB 全量数据,然后再重放 AOF 增量就能恢复了,这种情况下能尽可能将损失降到最低。生产上,我们也经常采用这种方式。 一天,你因为线上访问量剧增,redis 服务崩了,准备重启,但花了好长时间才完全恢复,你怒火冲冲质问道,怎么要重启这么久??? 因为 AOF 文件太大,重放了很久。 很好奇,前有 RDB 全备,AOF 增量备份能有多少数据。排查后发现,主要是针对一批相同的 keys 做了大量修改操作;突然间意识到,其实存最新的 value 即可。 于是又写了一个叫 AOF 重写的操作,本质是从拿到这些 key 的最新 value,生成 AOF 指令,来达到压缩 AOF 文件的目的。 终于,开始稳定了。 当然,redis 发展肯定没有这么波折,以上流程只是为了形象化展示 redis 发展历程。 一、持久化?持久化是什么?就 redis 而言,本质就是将内存中不稳定的数据,通过一些刷盘策略写入磁盘,从而达到断电等故障能恢复数据的效果。 说到持久化,我们一般关心以下几个问题:
等等,其实我们可能更关心的是:
带着问题,我们一起往下寻找答案~ 二、RDBRDB 全称 redis database,是以时间为轴线的全量内存快照,存在磁盘上。快照,就是那个时间点内存数据库的全景图,就像拍照一样,把那个瞬间的所有状态“咔”的一声记录下来。 实际过程中,我们可以定期执行 RDB 操作,要进行数据恢复的时候,找到最近的一个快照点进行恢复,可以将数据丢失风险尽可能的降低。 1. 落盘策略:很慢? 这个主要取决于你的数据量,比如,你的配置是 16Gb redis 内存,目前已占用 80%,相当于 10多个Gb的数据了,执行一次是需要花一定的时间。 redis 提供了两种方式,一种是 save,另一种是 bgsave。两者底层处理原理都一样,最大的区别点在于 SAVE 由主线程执行,会阻塞客户端命令;BGSAVE 由 fork 的子进程处理,不会阻塞执行。 1)SAVE: 在命令行输入:
全程会阻塞,直到 RDB 文件创建完毕。 2)BGSAVE: 在命令行输入:
这个过程会派生出子进程来创建 RDB 文件,父进程继续处理命令请求。 手动执行? 可以在命令行通过 SAVE 或者 BGSAVE 命令手动执行,生成 RDB 文件。 自动执行? 相比于手动执行,通常情况下,我们更希望通过一些配置,达到某些策略条件之后,自动执行 RDB 持久化。 用户可以通过 save 选项设置多个保存条件,但只要其中任意一个条件被满足,服务器就会执行 BGSAVE 命令。
那么只要满足以下三个条件中的任意一个,BGSAVE 命令就会被执行:
占用额外内存? 你可能会问,BGSAVE 操作会 fork 一个进程处理,而子进程会拥有父进程完整的数据集,这个过程相当于占用了双倍的内存空间? 不会。fork 子进程使用了一种叫做写时拷贝的技术(copy-on-write)。
此时,内核会尝试为该页面创建一个新的物理页面,并将内容真正地复制到新的物理页面中,让父子进程真正地各自拥有自己的物理内存页,然后将页表中相应的表项标记为可写: 从上面的描述可以看出,对于没有修改的页面,内核并没有真正地复制物理内存页,仅仅是复制了父进程的页表。这种机制的引入提升了fork的性能,从而使内核可以快速地创建一个新的进程。 2. 恢复策略:RDB 的载入策略是自动加载,没有额外提供载入命令。redis 默认使用 RDB 持久化策略,如果你想采用这种模式, 就不需要再去手动开启了。 在该策略下,redis 在启动时,会自动检测是否存在 RDB 文件,存在的话就进行载入。 服务器在载入RDB文件期间,会一直处于阻塞状态,直到载入工作完成为止。所以,如果你的文件比较大,还是需要花费一定的时间来加载,在这期间,服务对外不可用。 三、AOF1. 落盘(同步)策略:首先:
aof_buf 缓冲区: redis 服务端提供的缓冲区,请求命令会写入 aof_buf 缓冲区,然后由 aof_buf 缓冲区写入内核缓冲区或者同步至磁盘。 落盘时机: 在主事件循环,通过 beforeSleep 方法触发 flushAppendOnlyFile 调用,这便是入口。那,一条命令,经过哪些过程最终追加到 AOF 文件呢?
来看看
2. 恢复策略:恢复一般是指,经历故障或其他行为,通过重启 redis 服务并加载数据文件恢复内存状态的过程。 redis 默认通过 RDB 操作进行持久化,如果需要采用 AOF 持久化可以配置参数:
服务在重启的过程中会自动检测 AOF 文件是否存在,如果存在的话,就开始通过指令重放来恢复内存数据库状态。 指令重放?redis 通过伪客户端的方式,将命令一条条取出来,走正常的命令处理逻辑,直到处理处理完成。 你可能会问,如果一个 key 出现了多次,也要处理多次吗?
没错,这种也要执行多次,虽然内存中肯定只会保留最新的一次操作状态。是不是很臃肿? 接下来,我们通过 AOF 重写来看看怎么解决这个问题。 3. 重写上文提到,AOF 实实在在的记录了每一条命令,尤其是出现大量重复 key 的操作,会使得 AOF 看起来冗余且臃肿;因此,AOF 重写就相当于对 AOF 文件进行压缩,同一个 key 只保留最新的操作记录。 值得注意的是,AOF 重写并不需要从原 AOF 文件中进行压缩,而是直接扫描整个库,把每一个 key / value 转变成写命令,然后追加至临时文件;待重写操作完成后,将临时文件原子性重命名即可。 重写时机? redis 提供了灵活的重写机制,可以自动触发,也可以手动触发。 首先,需要确定是否开启了 AOF 策略,即:
你可以在命令行输入 BGREWRITEAOF 手动触发重写:
另外,redis 也提供了自动触发重写条件:
每次重写之后都会记录文件大小,作为下一次重写的触发条件:当前文件大小超过上次重写的百分比后,触发重写操作。 同时,为避免 AOF 文件过小而触发重写操作,提供了 auto-aof-rewrite-min-size 参数控制重写条件的下限。 子进程? 为避免阻塞主线程,AOF 重写仍然采用 fork 子进程的方式 重写流程: 1)触发重写条件(自动 or 手动)
3)直到 2a 完成后 四、RDB-AOF混合持久化我们先看看 redis 重启自动加载持久化文件的片段:
可以看到,要么是加载 AOF 文件,要么加载 RDB 文件;RDB - AOF 混合文件又是如何来的? 随着 redis 的普及使用,大家发现,不管是 RDB 还是 AOF 都有各自缺点,而两者结合使用可以大大改善这种情况。 于是,redis 4.0 推出了 RDB-AOF 这种混合模式,可以通过下面配置开启:
可以看到,使用混合模式的前提是,需要先开启 AOF;而 使用这种模式,当数据重写后,AOF 文件前半部分是 RDB 数据(采用 RDB 数据格式),AOF 文件后半部分继续追加 AOF 数据(AOF 数据格式)。 因此,我们回到加载部分来看,当采用 RDB-AOF 混合模式时,数据加载也是直接走 AOF 文件加载,由于 AOF 文件存储了 RDB 和 AOF 数据,也就达到了 五、总结redis 提供了两种持久化的方式,分别是
RDB 快照的主要优点:
AOF 文件主要优点:
实际很多情况下,我们可能需要 性能优势 + 数据持久性,因此 redis 也提供了 RDB-AOF 的混用模式,在 AOF 文件中前半部分采用 RDB 数据格式,后部分增量数据采用 AOF 格式存储,这也叫做 由于 AOF 记录的是命令,就有可能出现同一个 key 记录多次的情况而导致 AOF 过度膨胀,因此,引入 生成 RDB 文件 和 AOF 文件重写都是通过 参考文献:
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 13:40:34- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |