面试redis之两大金刚,你懂吗

前言

Redis持久化,一个老掉牙的问题,但是面试官就是喜欢问。这也是我们学Redis必会的一个知识点。Redis作为内存数据库,它工作时,数据都保存在内存里,这也是它为什么很快的一个原因。但存到内存里肯定是有丢数据的风险,所以Redis是有设计持久化的。Redis持久化分为两种:RDB和AOF。

图片

RDB持久化

RDB(Redis DataBase),是redis默认的存储方式,RDB持久化其实就是将内存的数据直接做了一份快照到磁盘上。触发RDB持久化的方式有:

  • 符合配置的快照保存规则(配置文件里save开头的配置);

  • 执行save或者bgsave命令;

  • 执行flushall命令;

  • 执行主从复制操作 (第一次)。

配置文件redis.conf中,save开头的配置为RDB持久化相关配置。具体解释如下:

  • save “” 表示关闭rdb持久化;
  • save 3600 1 表示每1小时至少有1个key改变,就触发一次持久化可以写多个条件 ;
  • save 3600 1 300 100 60 10000 这里定义了三个策略,它们相互之间为或的关系。

图片

RDB文件生成过程

我们以bgsave为例子来看下Redis生成RDB文件的大致过程是怎样的。

int rdbSaveBackground(char *filename, rdbSaveInfo *rsi) {
    pid_t childpid;
    long long start;

 // 如果已经存在aof重写子进程以及rdb生成子进程则直接返回错误
    if (server.aof_child_pid != -1 || server.rdb_child_pid != -1) return C_ERR;
    ...
    // fork子进程进行RDB文件生成
    if ((childpid = fork()) == 0) {
        ...
        // 生成RDB文件
        retval = rdbSave(filename,rsi);
        if (retval == C_OK) {
            size_t private_dirty = zmalloc_get_private_dirty(-1);

            if (private_dirty) {
                serverLog(LL_NOTICE,
                    "RDB: %zu MB of memory used by copy-on-write",
                    private_dirty/(1024*1024));
            }

            server.child_info_data.cow_size = private_dirty;
            // 通知父进程RDB文件生成完毕
            sendChildInfo(CHILD_INFO_TYPE_RDB);
        }
        //子进程退出
        exitFromChild((retval == C_OK) ? 0 : 1);
    } else {
       //父进程业务逻辑
        ...
    }
    return C_OK; 
}

(1)Redis主进程首先判断当前是否存在已经在执行的aof重写子进程以及rdb文件生成子进程,如果存在的话则直接进行返回。为什么要进行这样的判断呢?主要还是从服务器性能方面进行考量,如果服务器有多个子线程在进行RDB持久化操作,那么必定会对磁盘造成比较大的IO压力,如果服务器中还部署了其他服务甚至会影响其他服务的正常运行。

(2)Redis主进程fork子进程进行RDB文件生成操作,在fork的过程中,此时的Redis主进程是阻塞的,不能响应客户端请求,子进程fork完成之后可以继续响应客户端请求。

(3)fork出来的子进程遍历内存数据进行RDB文件生成操作。

(4)如果此时客户端的请求需要修改缓存数据,那么如上面fork子进程的原理,通过COW机制,操作系统会开辟新的内存空间给Redis主进程进行新的缓存数据写入。

(5)子进程快照数据生成完成之后,替换原来老的RDB文件。

图片

RDB触发时机

Redis主要支持两种持久化操作来生成RDB文件,分别是save、bsave命令方式手动生成以及在配置文件中配置时间间隔自动进行RDB文件生成。

手动命令触发

客户端连接到redis之后我们可以通过save以及bsave命令进行RDB文件的立即创建,两者的区别如下:

save:通过主线程触发,会阻塞Redis业务,如果内存数据比较多的话,会导致长时间不能响应外部请求;

客户端执行bsave命令进行RDB持久化,Redis主线程会fork子线程出来进行RDB文件持久化操作,这样避免了主线程的阻塞即便正在持久化操作依然可以响应外部数据缓存请求。

不过这里值得注意的是,虽然fork子进程之后不会阻塞主进程,但是在fork的过程中会阻塞主进程,尤其是在内存数据比较大的时候,阻塞主进程的时间会更长。

配置自动触发

另外在Redis的配置文件redis.conf中,我们可以配置按照一定的时间间隔来进行RDB持久化操作。如下配置:

save 900 1
save 300 10
save 60 10000

其他的触发RDB文件生成的操作这里不再赘述了,像从节点执行全量数据同步的时候,也会触发主节点生成RDB文件发送给从节点。

AOF持久化

AOF(Append Only File)持久化,是其将Reids执行过的所有写指令记录下来,保存到日志里,类似MySQL的bin-log。默认配置文件里该持久化方式是关闭的,需要将配置修改为:

appendonly yes

由于AOF是将Redis服务的写操作日志写到日志文件里,当写操作非常频繁时,那么它对磁盘也会造成很大的压力。所以,AOF的磁盘数据落地(fsync函数)也有三个策略:

Always:表示只要有写入就会调用fsync函数;

Everysec:表示每秒调用fsync函数一次;

No:表示不调用fscyn函数,完全跟着系统走;

图片

建议选择everysec,比较保守一些。

AOF重写

AOF文件如果不做干预,它会一直增涨,直到将你的磁盘写满。好在Redis给AOF提供了重写机制。我们可以直接执行如下命令,进行AOF重写:

bgrewriteaof;

执行完该命令后,AOF文件会根据已经持久化的RDB文件和现有AOF文件重新整理,它会把无用的写日志清空,最终达到瘦身目的。

当然,AOF还有一个重写的配置,两个参数:

参数说明
auto-aof-rewrite-min-sizeAOF文件必须要不低于这个尺寸时才会触发重写,后面的每次重写就不会根据这个变量了(根据上一次重写完成之后的大小)。此变量仅初始化启动redis有效
auto-aof-rewrite-percentage如果该数值定义为80,则表示当AOF文件增长的尺寸超过上次大小(AOF文件上次重写后的大小会被记录下来)百分80时就会触发重写操作

RDB和AOF如何选

在实际生产环境中,根据数据量、应用对数据的安全要求、预算限制等不同情况,会有各种各样的持久化策略。

如,完全不使用任何持久化、使用RDB持久化或AOF持久化的一种,或同时开启快照持久化和AOF持久化等。此外,持久化的选择必须与Redis的主从策略一起考虑,因为主从复制与持久化同样具有数据备份的功能,而且主机Master和从机Slave可以独立的选择持久化方案。

如果Redis中的数据完全丢弃也没有关系(如Redis完全用作DB层数据的cache),那么无论是单机,还是主从架构,都可以不进行任何持久化。

在单机环境下(对于个人开发者,这种情况可能比较常见),如果可以接受十几分钟或更多的数据丢失,选择RDB持久化对Redis的性能更加有利,如果只能接受秒级别的数据丢失,应该选择AOF。

但在多数情况下,我们都会配置主从环境,Slave的存在既可以实现数据的热备,也可以进行读写分离分担Redis读请求,以及在Master宕掉后继续提供服务。在这种情况下,一种可行的做法是:

  • Master:完全关闭持久化,这样可以让Master的性能达到最好;
  • Slave:关闭RDB持久化,开启AOF(如果对数据安全要求不高,开启RDB持久化关闭AOF也可以),并定时对持久化文件进行备份(如备份到其他文件夹,并标记好备份的时间)。然后关闭AOF的自动重写,然后添加定时任务,在每天Redis闲时(如凌晨12点)调用bgrewriteaof。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/14680.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

易基因:ChIP-seq等揭示热休克转录因子A1b调控植物高温胁迫响应的分子机制|应激反应

在拟南芥中,热休克转录因子A1b(HEAT SHOCK TRANSCRIPTION FACTORA1b,HSFA1b)通过影响种子产量来调控对环境胁迫的抗性。HSFA1b是生殖适应性的决定性因素,这种调控机制怎么形成的呢? 2018年,英国…

【微电网_储能】基于启发式状态机策略和线性程序策略优化方法的微电网中的储能研究【给定系统约束和定价的情况下】(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

前端项目代码规范

一、变量与函数的命名(变量名和函数名是最好的注释) 通常情况下函数小陀峰、类名大陀峰、变量短横线/小陀峰、const全大写单词要表达出正确的语义,如:array类型或其它集合类型用英语复数格式、其它类型不要用复数格式区分函数为功…

【服务器】Linux搭建我的世界服务器 + 公网远程联机教程

Yan-英杰的主页 悟已往之不谏 知来者之可追 C程序员,2024届电子信息研究生 目录 前言 1. 安装JAVA 2. MCSManager安装 3.局域网访问MCSM 4.创建我的世界服务器 5.局域网联机测试 6.安装cpolar内网穿透 7. 配置公网访问地址 8.远程联机测试 9. 配置固定…

C++ 线程

linux使用线程 在linux使用线程可能出现,在编译时不会报错,但执行出错的问题。 undefined reference to pthread_create这是由于ubuntu平台下调用pthread_create()函数,pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 …

MII、 RMII、 GMII、 RGMII 接口介绍

1、RGMII 接口概要 以太网的通信离不开物理层 PHY 芯片的支持,以太网 MAC 和 PHY 之间有一个接口,常用的接口有MII、 RMII、 GMII、 RGMII 等。 MII(Medium Independent Interface, 媒体独立接口): MII 支持…

RabbitMQ之介绍以及安装

1.1 MQ的相关概念 1.1.1 什么是MQ ​ MQ,从字面意思上看,本质是个队列,FIFO先入先出,只不过队列中存放的内容是message而已,还是一种跨进程的通信机制,用于上下游传递消息。在互联网架构中,MQ…

移远通信笔试题

限时60分钟 1.下列关于栈叙述正确的是 A A) 栈顶元素最先能被删除 B)栈顶元素最后才能被删除 C)栈底元素永远不能被删除 D)以上三种都不对 在栈中,最后被压入的元素总是在栈顶上方,而栈顶元素总是最先被弹出的元…

理解龙格库塔法基本C程序

先学习龙格-库塔法; 龙格-库塔,Runge-Kutta,该方法用于数值求解微分方程; 其中包括著名的欧拉法; 经典四阶法 该方法主要是在已知方程导数和初值信息,利用计算机仿真时应用,省去求解微分方…

人工智能之配置环境教程一:安装VsCode和Anaconda

人工智能之配置环境教程一:安装VsCode和Anaconda 作者介绍一. 安装VScode编辑器二. 安装Anaconda 作者介绍 孟莉苹,女,西安工程大学电子信息学院,2021级硕士研究生,张宏伟人工智能课题组。 研究方向&#…

shell脚本----条件判断语句

文章目录 一、条件测试1.1 文件测试和整数测试文件测试整数值比较 1.2字符串测试和逻辑测试字符串测试:逻辑测试 二、if语句三、case语句 一、条件测试 1.1 文件测试和整数测试 文件测试 test命令 测试表达是是否成立,若成立则返回0,否则返…

元宇宙的应用领域

应用领域一:游戏 1.游戏是最先成长起来的元宇宙场景。虚拟社交身份、开放性、经济系统、沉浸感、世界可持续性是元宇宙游戏需关注的五大特征。 2.元宇宙游戏依然是游戏,现阶段参与元宇宙游戏的主要是游戏爱好者。新的概念依旧需要好的游戏产品支撑。团…

malloc的一些知识

这是一个叫malloc的家伙,一直勤勤恳恳帮你为所欲为的玩转系统内存。可是长路漫漫,唯malloc作伴,我却不懂它。走近malloc,多了解一下总没错。 可能对我们来讲,malloc就是void* malloc (size_t len),调用就是…

4月24日作业

作业1 #include <iostream> using namespace std; template <typename T> class Node { private: T* p; //指针指向栈的首地址 int maxsize; //栈最大容量 int top-1; //栈顶 public: Node(){} //无参构造 Node(int max):maxsize(max)//有参构造 填最大容…

JavaScript 知识总结下篇(更新版)

91.实现一个 promise 参考链接&#xff1a;实现一个完美符合Promise/A规范的Promise Issue #4 forthealllight/blog GitHub function myPromise(constructor) {let self this;self.status "pending" // 定义状态改变前的初始状态self.value undefined;// 定义状…

基于html+css的图片展示32

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

STM32WB55_NUCLEO开发(11)----发送数据到手机

概述 本篇文章将详细介绍如何在上节配置的基础上&#xff0c;实现通过点击STM32WB开发板上的按键发送数据到手机上。 硬件准备 首先需要准备一个开发板&#xff0c;这里我准备的是NUCLEO-WB55RG 的开发板&#xff1a; 蓝牙配置 选择“mySVC”选项卡。添加第二个特征&…

有始有终的编码原则

基本情况 在程序员的修炼之道之中&#xff0c;说到&#xff1a; 这个建议能简单地应用到大多数场合。简单说就是&#xff0c;分配资源的函 数或对象&#xff0c;对释放资源应负有责任。 这其实就是我们常说的谁分配的就谁负责释放&#xff0c;这也是内存释放的一个原则&#x…

CGI, FastCGI, WSGI, uWSGI, uwsgi一文搞懂

1. CGI # 1、通用网关接口&#xff08;Common Gateway Interface/CGI&#xff09;是一种重要的互联网技术&#xff0c;可以让一个客户端&#xff0c;从网页浏览器向执行在网络服务器上的程序请求数据。CGI描述了服务器和请求处理程序之间传输数据的一种标准。 # 2、CGI程序可以…

Hive ---- DDL(Data Definition Language)数据定义

Hive ---- DDL&#xff08;Data Definition Language&#xff09;数据定义 1. 数据库&#xff08;database&#xff09;1. 创建数据库2. 查询数据库3. 修改数据库4. 删除数据库5. 切换当前数据库 2. 表&#xff08;table&#xff09;1. 创建表2. 查看表3. 修改表4. 删除表5. 清…