🚀 Database
1、数据库基础
1.1 事务的概念和特性
1.2 锁
1.3 锁协议
1.4 事务日志
1.5 MVCC实现原理
1.6 基础知识
1.6.1 三范式
1.6.2 多表连接方式
1.6.3 存储过程
1.6.4 TRUNCATE和DROP的区别
1.6.5 触发器
1.6.6 视图
2、MySQL
2.1 索引
2.2 索引组织表
2.3 InnoDB和MyISAM的区别
2.4 Checkpoint技术
2.5 宕机恢复原理
2.6 数据库优化
2.7 分库分表
2.8 一致性哈希算法
2.9 主从复制
3、Redis
3.1 概述
3.1.1 为什么Redis单线程还这么快
3.1.2 Redis数据类型
3.1.3 持久化机制
3.1.4 过期机制和内存淘汰策略
3.2 线程模型
3.3 分布式问题
3.3.1 Redis实现分布式锁
3.4 缓存异常
3.4.1 缓存击穿、缓存雪崩
3.5 高可用
3.5.1 主从复制
3.5.2 哨兵模式
3.5.3 集群模式
-
+
游客
注册
登录
持久化机制
## 1 什么是持久化 1. 持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。 ## 2 Redis 中持久化机制有哪些 Redis 中持久化机制主要有两种,分别是**RDB**(默认)和**AOF**。 ### 2.1 RDB #### 2.1.1 含义 1. RDB 文件主要用于**保存和还原 Redis 服务器所有数据库中的所有键值对数据**。 2. 创建方式主要有两种,分别是 `SAVE` 和 `BGSAVE`: 1. `SAVE` 命令**由服务器进程直接执行保存操作**,所以该命令**会阻塞服务器**。 2. `BGSAVE` 命令**由子进程执行保存操作**,所以该命令**不会阻塞服务器**。 3. 因为 `BGSAVE` 命令可以在不阻塞服务器进程的情况下执行,所以**可以通过设置服务器配置的 `save` 选项**,**让服务器每隔一段时间自动执行一次 `BGSAVE` 命令**,用户**可以通过 `save` 选项设置多个保存条件**,但**只要其中任意一个条件被满足**,**服务器就会执行 `BGSAVE` 命令**。 #### 2.1.2 优缺点 ##### 2.1.2.1 优点 1. 整个 Redis 数据库**只包含一个文件**,这**对于文件备份来说非常方便**,比如,我们可能打算每个小时归档一次最近 24 小时的数据,同时还要每天归档一次最近 30 天的数据,通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。 2. 对于**灾难性恢复**而言,RDB 也是一个不错的选择,因为我们**可以非常轻松的将一个单独的文件压缩后再转移到其他存储介质上**。 3. **性能最大化**,对于 Redis 的服务进程而言,在开始持久化时,他**唯一需要做的只是 `fork` 出子进程**,之后再**由子进程完成这些持久化的工作**,这样**可以极大地避免服务进程执行 IO 操作**。 4. 相比于 AOF 机制,**如果数据集很大**,**RDB 的启动效率会更高**。 ##### 2.1.2.2 缺点 1. **数据安全性低**,因为**RDB 是间隔一段时间进行持久化**,如果**持久化之前 Redis 发生故障**,**会发生数据丢失**,所以这种方式**更适合数据要求不严谨的时候**。 ### 2.2 AOF #### 2.2.1 含义 1. AOF 文件**通过保存所有修改数据库的写命令请求来记录服务器的数据库状态**。 2. **命令请求会先保存到 AOF 缓冲区里面**,之后再**定期写入并同步到 AOF 文件**,然后**服务器只要载入并重新执行保存在 AOF 文件中的命令**,**就可以还原数据库本来的状态**。 #### 2.2.2 持久化的效率和安全性 1. `appendfsync`**选项的不同值对 AOF 持久化功能的安全性以及 Redis 服务器的性能有很大的影响**: 1. 当 `appendfsync` 的值为 `always` 时: 1. 服务器**在每个事件循环都要将 `aof_buf` 缓冲区中的所有内容写入到 AOF 文件**,**并且同步 AOF 文件**。 2. 所以 `always` 的**效率是最低的**,但却是**最安全的**,因为**即使出现故障停机**,AOF 持久化**也只会丢失一个事件循环中所产生的的命令数据**。 2. 当 `appendfsync` 的值为 `everysec` 时: 1. 服务器**在每个事件循环都要将 `aof_buf` 缓冲区的所有内容写入到 AOF 文件**,并且**每隔一秒就要在子线程中对 AOF 文件进行一次同步**。 2. 从效率上来讲,`everysec` 模式**足够快**,并且**就算出现故障停机**,数据库**也只会丢失一秒钟的命令数据**。 3. 当 `appendfsync` 的值为 `no` 时: 1. 服务器**在每个事件循环都要将 `aof_buf` 缓冲区的所有内容写入到 AOF 文件**,至于**何时对 AOF 文件进行同步**,则**由操作系统控制**。 2. 因为**该模式下 `flushAppendOnlyFile` 调用无须执行同步操作**,所以该模式下的**AOF 文件写入速度是最快的**,不过因为该模式下**会在系统缓存中积累一段时间的写入数据**,所以该模式的**单次同步时长是最长的**,当**出现故障停机时**,将**会丢失上次同步 AOF 文件之后的所有鞋命令数据**。 > 1. 文件写入和文件同步的区别? > 1. **文件写入是指写入到内存缓冲区中**,**文件同步是指将内存缓冲区中的数据刷新到磁盘中**。 > 2. 事件循环是什么? > 1. Redis**服务器进程就是一个事件循环**,这个循环中的**文件事件负责接收客户端的命令请求**,以及**向客户端发送命令回复**,而**时间事件则负责像 `serverCron` 函数这样需要定时运行的函数**。 #### 2.2.3 AOF 重写 ##### 2.2.3.1 前言 1. 因为 AOF 持久化是**通过保存被执行的写命令来记录数据库状态**的,所以**随着服务器运行时间的流逝**,**AOF 文件中的内容会越来越多**,**文件的体积也会越来越大**。 2. 如果不加以控制,**体积过大的 AOF 文件可能会对 Redis 服务器**,**甚至整个宿主计算机造成影响**,同时**使用 AOF 文件来进行数据还原所需要的时间也会越来越多**,为了**解决 AOF 体积膨胀**的问题,Redis 提供了**文件重写**的功能。 3. 通过文件重写,Redis 服务器可以**创建一个新的 AOF 文件来替代现有的 AOF 文件**,**新旧两个 AOF 文件所保存的数据库状态相同**,但**新 AOF 文件不会包含任何浪费空间的冗余命令**,所以**新 AOF 文件的体积通常会比旧 AOF 文件的体积要小得多**。 ##### 2.2.3.2 原理 1. AOF 重写功能的实现原理是**从数据库中读取键现在的值**,**然后用一条命令去记录键值对**,**代替之前记录这个键值对的多条命令**。 2. 这样通过 AOF 重写生成的新 AOF 文件**只包含当前数据库状态所必须的命令**,因此**不会浪费任何硬盘空间**。 3. 在实际中,为了**避免在执行命令时造成客户端输入缓冲区溢出**,**重写程序在处理列表**、**哈希表**、**集合**、**有序集合这四种可能会带有多个元素的键时**,**会先检查所包含的元素数量**,**如果元素数量超过了**`src/redic.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD`**常量的值**(当前版本为 64),**那么重写程序将使用多条命令来记录键的值**,**而不单单使用一条命令**。 4. 具体的示例如下: 1. 假如服务器对 `animals` 键执行了以下命令: ![](/media/202107/2021-07-15_115641.png) 2. 为了记录 `animals` 键的状态,AOF 文件必须保存上面列出的四条命令。 3. 如果服务器想减少保存 `animals` 键所需命令的数量,那么服务器可以通过读取 `animals` 键的值,然后用一条 `SADD animals "Dog" "Panda" "Tiger" "Lion" "Cat"` 命令来代替上面的四条命令,这样就将保存 `animals` 键所需的命令从 4 条减为一条了。 4. 除了上面列举的列表键和集合键之外,其他所有类型的键都可以用同样的方法去减少 AOF 文件中的命令数量。 #### 2.2.4 AOF 后台重写 ##### 2.2.4.1 前言 1. 上面介绍的 AOF 重写程序 `aof_rewrite()` 函数可以很好地完成创建一个新的 AOF 文件的任务,但是,因为这个函数**会进行大量的写入操作**,所以**调用这个函数的线程将被长时间阻塞**,因为**Redis 服务器使用单线程来处理命令请求**,所以**如果这个服务器直接调用 `aof_rewrite()` 函数的话**,那么**在重写 AOF 文件期间**,**服务器将无法处理客户端发来的命令请求**。 2. 因此 Redis 决定**将 AOF 重写程序放到子线程里执行**,这样做可以同时达到两个目的: 1. **子进程进行 AOF 重写期间**,**服务器进程**(父进程)**可以继续处理命令请求**。 2. **子进程带有服务器进程的数据副本**,**使用子进程而不是线程**,**可以在避免使用锁的情况下**,**保证数据的安全性**。 ##### 2.2.4.2 原理 1. 虽然使用子进程有诸多好处,但是使用子进程也有一个问题需要解决,因为**子进程在进行 AOF 重写期间**,**服务器进程还需要继续处理命令请求**,而**新的命令可能会对现有的数据库状态进行修改**,从而**使得服务器当前的数据库状态和重写后的 AOF 文件所保存的数据库状态不一致**,例如: 1. 假如当子进程开始进行文件重写时,数据库中只有 `k1` 一个键,但是当子进程完成 AOF 文件重写之后,服务器进程的数据库中已经新设置了 `k2`、`k3`、`k4` 三个键,因此,重写后的 AOF 文件和服务器当前的数据库状态并不一致,新的 AOF 文件只保存了 `k1` 一个键的数据,而服务器数据库现在却有 `k1`、`k2`、`k3`、`k4` 四个键。 2. 上面的执行过程如下所示: ![](/media/202107/2021-07-15_143801.png) 2. 为了解决这种数据不一致问题,Redis 服务器设置了一个**AOF 重写缓冲区**,这个缓冲区**在服务器创建子进程之后开始使用**,当 Redis 服务器**执行完一个写命令之后**,他会**同时将这个写命令发送给 AOF 缓冲区和 AOF 重写缓冲区**。 ![](/media/202107/2021-07-15_144611.png) 3. 这样一来可以保证: 1. **AOF 缓冲区的内容会定期被写入和同步到 AOF 文件**,**对现有 AOF 文件的处理工作会如常进行**。 2. **从创建子进程开始**,**服务期执行的所有写命令都会被记录到 AOF 重写缓冲区里面**。 4. 当**子进程完成 AOF 重写工作之后**,他**会向父进程发送一个信号**,**父进程在接收到该信号后**,**会调用一个信号处理函数**,并执行以下工作: 1. **将 AOF 重新缓冲区中的所有内容写入到新 AOF 文件**,这时**新 AOF 文件所保存的数据库状态将和服务器当前的数据库状态一致**。 2. **对新的 AOF 文件进行改名**,**原子地覆盖现有的 AOF 文件**,**完成新旧两个 AOF 文件的替换**。 5. 这个**信号处理函数执行完毕之后**,**父进程就可以像往常一样接受命令请求了**。 6. **在整个 AOF 后台重写过程中**,**只有信号处理函数执行时会对服务器进程**(父进程)**造成阻塞**,**在其他时候**,**AOF 后台重写都不会阻塞父进程**,这**将 AOF 重写对服务器性能造成的影响降到了最低**。 7. 具体示例如下: ![](/media/202107/2021-07-15_145716.png) #### 2.2.5 优缺点 ##### 2.2.5.1 优点 1. 该机制可以带来[**更高的数据安全性**](#2-2-2-持久化的效率和安全性)。 2. 如果**日志过大**,Redis 可以**自动启用[重写机制]()。** 3. AOF**包含一个格式清新**、**易于理解的日志文件用于记录所有的修改操作**。 ##### 2.2.5.2 缺点 1. 对于**相同数量的数据集**而言,**AOF 文件通常要大于 RDB 文件**,而且因为 AOF 文件**记录的是执行命令**,在**恢复的时候需要重新执行相应的命令**,**RDB 存储是数据**,**恢复时直接恢复即可**,因此**RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快**。 2. 根据同步策略的不同,**AOF 在运行效率上往往会慢于 RDB**。 ## 3 如何选择何时的持久化方式 1. 一般来说,如果想达到足以**达到 PostgreSQL 的数据安全性**,我们**应该同时使用两种持久化功能**,在这种情况下,当**Redis 重启的时候**,**会优先载入 AOF 文件来恢复原始的数据**,因为在**通常情况下 AOF 文件保存的数据集要比 RDB 保存的数据集要完整**。 2. 如果我们**可以承受数据分钟以内的丢失**,那么**可以只使用 RDB 持久化**。 3. 一般**不推荐只使用 AOF 持久化**,因为**定时生成的 RDB 快照非常便于数据库备份**,并且**RDB 恢复数据集的速度要比 AOF 快**。 ## 参考文献 1. [几率大的 Redis 面试题(含答案)](https://blog.csdn.net/Butterfly_resting/article/details/89668661)。 2. [Redis 面试题(总结最全面的面试题)](https://juejin.cn/post/6844904127055527950)。 3. [redis 持久存储 RDB 和 AOF 的区别及优缺点](https://www.cnblogs.com/bigox/p/11574642.html)。 4. redis 设计与实现(第二版)。
ricear
2021年7月22日 11:01
©
BY-NC-ND(4.0)
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码