面试官:你说你精通Redis,你看过持久化的配置吗?

前边我们已经介绍了 Redis 五种数据类型的命令配置文件的基本配置,今天让我们从理论和配置两个层面来揭开 Redis持久化的神秘面纱。

所谓持久化可以简单理解为将内存中的数据保存到硬盘上存储的过程。持久化之后的数据在系统重启或者宕机之后依然可以进行访问,保证了数据的安全性。

Redis有两种持久化方案,一种是快照方式( SNAPSHOTTING),简称 RDB;一种是只追加模式( APPEND ONLY MODE),称为AOF。接下来让我们分别了解一下它们的使用与注意事项。

RDB

RDBRedis DataBase的缩写,是 Redis 默认的持久化方案。它能够在指定的时间间隔内将内存数据集快照( snapshot)写入磁盘,恢复时将快照文件( dump.rdb )读回内存。

面试官:你说你精通Redis,你看过持久化的配置吗?

我们先来扒一下配置文件中的 SNAPSHOTTING:

配置文件

save <seconds> <changes></changes></seconds>

在给定的 秒数内,如果对数据库执行的 写入操作数达到设定的值,则将数据同步到数据文件。支持多个条件配合, Redis默认配置文件中提供了三个条件:

save 900 1  //900s内有1个更改
save 300 10 //300s内有10个更改
save 60 10000   //60s内有10000次更改

注意:若不想用 RDB方案,可以把 save ""的注释打开,上边三个注释掉。

stop-writes-on-bgsave-error yes

bgsave出现错误时, Redis是否停止执行写命令;

  • 如果为 yes,则当硬盘出现问题时, Redis将停止接受写入操作,这样我们可以及时发现,避免数据的大量丢失;
  • 如果为 no,则 Redis无视 bgsave的错误继续执行写命令。

如果已经设置了对 Redis服务器的正确监视和持久性,即采用了其他手段发现和控制数据完整性,可能希望禁用此功能,以便即使在磁盘、权限等方面出现问题时, Redis仍能正常工作。

注意:如果后台保存过程将再次开始工作, Redis将自动允许再次写入。

rdbcompression yes

指定存储到本地数据库时是否 压缩Redis采用 LZF压缩)数据,默认为 yes。如果为了节省 CPU时间,可以关闭该选项,但会导致数据库文件变得巨大。

rdbchecksum yes

RDB版本 5开始,在存储快照后,还可以使用 CRC64算法来进行数据校验, CRC64校验放在文件的末尾。开启之后,保存和加载 RDB文件时会增加大约 10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。

禁用 校验和创建的 RDB文件的校验和为零,这将告诉加载代码跳过检查。

dbfilename dump.rdb

指定本地数据库文件名,重启之后自动加载进 内存,手动执行 save 命令的话即刻生效。

大坑请注意flushallshutdown命令都会清空并提交至 dump.rdb

dir ./

指定本地数据库存放目录。

理论

工作方式

  • Redis 需要保存 dump.rdb文件时,它会调用系统函数 fork(),创建一个子进程(与主进程完全一致);
  • 子进程将数据集写入临时文件 RDB中;
  • 当子进程完成对新 RDB 文件的写入时, Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。

这种工作方式使得 Redis 可以从写时复制( copy-on-write)机制中获益。

如何触发RDB快照

  1. 配置文件中默认的快照配置;
  2. 命令 save(阻塞, 只管保存快照,其他的等待)或者是 bgsave(异步)命令,快照同时还可以响应客户端命令;
  3. 执行 flushall 命令,清空数据库所有数据,意义不大;
  4. 执行 shutdown 命令,保证服务器正常关闭且不丢失任何数据,意义也不大。

通过RDB文件恢复数据

在实际开发中,一般会考虑到物理机硬盘损坏的情况,所以我们会选择备份 dump.rdb文件。将备份的 dump.rdb 文件拷贝到 redis的安装目录的 bin目录下,重启 redis服务即可。

优点

  • RDB是一个非常紧凑的文件,非常适用于数据集的备份;
  • RDB是一个紧凑的单一文件,很方便传送到另一个远端数据中心或者亚马逊的S3(可能加密),非常适用于灾难恢复;
  • Redis的主进程不进行 I/O操作,确保了极高的性能;
  • 适合大规模数据的恢复,对于数据的完整性和一致性要求不高的话, RDBAOF方式更加高效。

缺点

  • Redis意外宕机时,你可能会丢失几分钟的数据;
  • RDB 需要经常 fork子进程来保存数据集到硬盘上,当数据集比较大的时候, fork的过程是非常耗时的,可能会导致 Redis在一些毫秒级内不能响应客户端的请求。如果数据集巨大并且 CPU性能不是很好的情况下,这种情况会持续1秒; AOF也需要 fork,但是可以调节重写日志文件的频率来提高数据集的耐久度。

AOF

为了解决 RDB方式在宕机时丢失数据过多的问题,从 1.1 版本开始, Redis增加了一种 durable的持久化方式: AOF

AOFAppend Only File的缩写,默认不开启。 AOF以日志的形式来记录每个写操作,只允许追加文件但不可以改写文件,当服务器重启的时候会重新执行这些命令来恢复原始的数据。

我们再来看一下配置文件中的 APPEND ONLY MODE:

配置文件

appendonly no

默认为关闭状态,改为 yes打开持久化。 AOFRDB可以同时启用而不会出现问题。

appendfilename “appendonly.aof”

文件默认名称,启动即创建。加载 先于 dump.rdb文件

appendfsync

同步策略:系统函数 fsync() 告诉操作系统在磁盘上实际写入数据。 Redis支持三种不同的模式

appendfsync always  //每次发生数据变更会被立即记录到磁盘,性能较差但数据完整性比较好
appendfsync everysec    //默认推荐,异步操作,每秒记录,如果宕机,有1秒内数据丢失
appendfsync no  //不同步,只有在操作系统需要时在刷新数据

要想了解接下来的配置内容,先得说一下”日志重写”的原理:

重写

由于 AOF采用的是将命令追加到文件末尾的方式,所以随着写入命令的不断增加, AOF文件的体积会变得越来越大。为避免出现此种情况,新增了重写机制:可以在不打断服务客户端的情况下,对 AOF文件进行重建( rebuild)。

重写触发: 通过执行 bgrewriteaof命令,可以生成一个新的 AOF文件,该文件包含重建当前数据集所需的 最少命令。 Redis 2.2需手动执行该命令, Redis 2.4则可以通过修改配置文件的方式自动触发(配置在下边涉及)。

重写原理:

  • Redis 执行系统函数 fork() ,创建一个子进程(与主进程完全一致);
  • 子进程开始将新 AOF 文件的内容写入到临时文件;
  • 对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾,这样即使在重写的中途发生停机,现有的 AOF 文件也是安全的;
  • 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。
  • Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF文件的末尾。

no-appendfsync-on-rewrite no

当我们同时执行主进程的 写操作和子进程的 重写操作时,两者都会操作磁盘,而重写往往会涉及到大量的磁盘操作,这样就会造成主进程在写 aof文件的时候出现阻塞的情形。

为了解决这个问题, no-appendfsync-on-rewrite参数出场了。

  • 如果该参数设置为 no,是最安全的方式,不会丢失数据,但是要忍受阻塞的问题;
  • 如果设置为 yes,这就相当于将 appendfsync设置为 no,这说明并没有执行磁盘操作,只是写入了缓冲区。因此这样并不会造成阻塞(因为没有竞争磁盘),但是如果这个时候 redis挂掉,就会丢失数据。丢失多少数据呢?在 linux的操作系统的默认设置下,最多会丢失30s的数据。

因此,如果应用系统无法忍受延迟,而可以容忍少量的数据丢失,则设置为 yes;如果应用系统无法忍受数据丢失,则设置为 no

auto-aof-rewrite-percentage 100

重写百分比,默认为上次重写后 aof文件大小的一倍。

auto-aof-rewrite-min-size 64mb

重写触发的最小值:64mb。

根据 auto-aof-rewrite-min-sizeauto-aof-rewrite-percentage参数确定自动触发时机。 Redis会记录上次重写时的 AOF大小,默认配置是当 AOF文件大小是上次 rewrite后大小的一倍且文件大于 64M时触发。

大型互联网公司一般都是 3G起步

aof-load-truncated yes

AOF文件被截断时,即 AOF文件的最后命令不完整,如果此时启动 Redis,会将 AOF数据加载回内存,此时便会出现问题。

  • yes:加载一个截断的 AOFRedis服务器开始发出日志,通知用户该事件;
  • no:服务器将中止并出现错误,拒绝启动。

当我们得知 AOF文件报错时,可以用以下方法来修复出错的 AOF 文件:

  • 为现有的 AOF文件创建一个备份;
  • 使用 Redis 附带的 redis-check-aof 命令,对原来的 AOF文件进行修复;
  • redis-check-aof &#x2013;fix
  • redis-check-aof --fix appendonly.aof 修复命令,杀光不符合规范的语法
  • 可选)使用 diff -u 对比修复后的 AOF文件和原始 AOF 文件的备份,查看两个文件之间的不同之处;
  • 重启 Redis服务器,等待服务器载入修复后的 AOF文件,并进行数据恢复。

aof-use-rdb-preamble yes

在重写 AOF文件时, Redis能够在 AOF文件中使用 RDB前导,以加快重写和恢复速度。启用此选项后,重写的 AOF文件由两个不同的节组成: RDB fileAOF tail

加载 Redis时,会识别 AOF文件以 Redis字符串开头,并加载带前缀的 RDB文件,然后继续加载 AOF尾部。

理论

优点

  • 数据的完整性和一致性更高, AOF的持久化通过使用不同的策略,最多丢失1秒的数据;
  • AOF文件是一个只进行追加的日志文件,不需要写入 seek
  • Redis可以在 AOF文件体积变得过大时,自动地在后台对 AOF 进行重写,重写操作是绝对安全的;
  • AOF文件记录的写入操作以 Redis协议的格式保存,容易读懂,容易对文件进行分析;

缺点

  • 对于相同的数据集来说, AOF文件的体积通常要大于 RDB文件的体积;
  • 根据所使用的 fsync 策略, AOF的速度可能会慢于 RDB

在一般情况下,每秒 fsync 的性能依然非常高,而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时, RDB 可以提供更有保证的最大延迟时间( latency)。

对比与总结

如何选择使用哪种持久化方式?

一般来说,如果想达到足以媲美 PostgreSQL 的数据安全性,应该同时使用两种持久化功能。

如果非常关心数据,但仍然可以承受数分钟以内的数据丢失,那么可以只使用 RDB 持久化。

由于AOF持久化的实时性更好,即当进程意外退出时丢失的数据更少,因此 AOF是目前 主流的持久化方式。

有很多用户都只使用 AOF持久化,但我们并不推荐这种方式:因为定时生成 RDB 快照( snapshot)非常便于进行数据库备份,并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快。

AOF和RDB之间的相互作用

在版本号大于等于 2.4Redis 中, BGSAVE 执行的过程中,不可以执行 BGREWRITEAOF 。反过来说,在 BGREWRITEAOF 执行的过程中,也不可以执行 BGSAVE。这可以防止两个 Redis 后台进程同时对磁盘进行大量的 I/O 操作。

如果 BGSAVE 正在执行,并且用户显示地调用 BGREWRITEAOF 命令,那么服务器将向用户回复一个 OK 状态, 并告知用户 BGREWRITEAOF 已经被预定执行:一旦 BGSAVE 执行完毕, BGREWRITEAOF就会正式开始。

Redis 启动时,如果 RDB持久化和 AOF 持久化都被打开了, 那么程序会优先使用 AOF 文件来恢复数据集,因为 AOF文件所保存的数据通常是最完整的。

备份redis数据

  • 创建一个定期任务( cron job),每小时将一个 RDB 文件备份到一个文件夹,并且每天将一个 RDB 文件备份到另一个文件夹;
  • 确保快照的备份都带有相应的日期和时间信息,每次执行定期任务脚本时,使用 find 命令来删除过期的快照;
  • 至少每天一次,将 RDB 备份到你的数据中心之外,或者至少是备份到你运行 Redis 服务器的物理机器之外。

性能建议

在实际应用时,因为 RDB文件只用作后备用途,建议只在 slave上持久化 RDB文件,而且只需要15分钟备份一次就够了,只保留 save 900 1这条规则。

如果开启 AOF,好处是在最恶劣情况下也只会丢失不超过2秒数据,启动脚本较简单只 load自己的 AOF文件就可以了。代价一是带来了持续的 IO,二是 AOF rewrite的最后将 rewrite过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。

只要硬盘许可,应该尽量减少 AOF rewrite的频率, AOF重写的基础大小默认值 64M太小了,可以设置到 5G以上。默认超过原大小的100%时重写可以改到适当的数值。

如果不开启 AOF,仅靠 Master-Slave Replication实现高可用性也可以。能省掉一大笔 IO,也减少了 rewrite时带来的系统波动。代价是如果 Master/Slave同时倒掉,会丢失十几分钟的数据,启动脚本也要比较两个 Master/Slave中的 RDB文件,载入较新的那个。

以上就是今天的全部内容了,如果你有不同的意见或者更好的 idea,欢迎联系阿Q,添加阿Q可以加入技术交流群参与讨论呦!

Original: https://www.cnblogs.com/aqsaycode/p/15213228.html
Author: 阿Q说代码
Title: 面试官:你说你精通Redis,你看过持久化的配置吗?

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/570010/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Java如何去除字符串中的HTML标签

    Java如何去除字符串中的HTML标签 使用爬虫爬取网站数据,有时会将HTML相关的标签也一并获取,如何将这些无关的标签去除呢,往下看: 直接写个Test类: @Test void…

    Java 2023年6月15日
    077
  • Idea2019.3 :一直卡在Resolving Maven dependencies

    maven仓库是阿里的 问题 如图,下载jar包挺快,一直卡在解析那一步。。。。导致写注解老是爆红 解决 修改maven Importing的jvm参数, 默认为700多, 直接修…

    Java 2023年6月7日
    070
  • 手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(三)-项目初始化

    项目开发前,请确保已安装好以下开发环境: MySQL 8.0 Redis 7.0 Elasticsearch 8.2.0(选装) RabbitMQ 3.10.2(选装) JDK 1…

    Java 2023年6月8日
    058
  • 项目全局异常处理

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年6月7日
    080
  • Tomcat无法启动:报出Server Tomcat v8.5 Server at localhost failed to start

    昨天晚上写Javaweb练习,突然Tomcat报错(Server Tomcat v8.5 Server at localhost failed to start),启动失败 用to…

    Java 2023年6月9日
    058
  • 人类的规划能力有多强大?

    本文章译自OptaPlanner官网上,Geoffrey De Smet先生的博文,链接如下: https://www.optaplanner.org/blog/2015/06/0…

    Java 2023年6月16日
    090
  • SpringbootTest注入失败

    正确方法: java;gutter:true; /<strong> * <em>@author:sawsh * </em>@date:2021/…

    Java 2023年5月30日
    0103
  • HTML&CSS

    Web概念概述、HTML、CSS web概念概述 1.1 JavaWeb 使用Java语言开发基于互联网的项目 1.2 软件架构 C/S: Client/Server 客户端/服务…

    Java 2023年6月6日
    062
  • 设计模式—原型模式

    类型:创建型 目的:通过拷贝快速创建相同或相似对象。 接下来我们看一个需要改进的案例。 优化案例 话不多说,先来看一个创建相同或相似对象的传统写法。 public class De…

    Java 2023年6月7日
    066
  • Redis学习详解(一):Redis持久化机制之RDB

    Redis的持久化机制有两种:RDB持久化和AOF持久化。因为Redis是一个内存数据库,如果没有合适的持久化机制,那么一旦服务器进程退出,服务器中的数据库状态也会消失。本章介绍R…

    Java 2023年6月7日
    072
  • Java全栈系列笔记

    Java全栈系列笔记 全部文档、项目、源码: github:https://github.com/name365/Blog-Java 码云:https://gitee.com/ya…

    Java 2023年5月29日
    071
  • VMware Data Recovery备份恢复vmware虚拟机

    VMware Data Recovery 是VMware虚拟机备份工具,可创建虚拟机备份,同时不会中断虚拟机的使用或虚拟机提供的数据和服务。Data Recovery 管理现有备份…

    Java 2023年5月30日
    050
  • 【Spring Boot】我的第一个Spring Boot练习

    背景 Spring 在 Java 生态的企业级开发项目中极其常用,通常我们为项目引入一项新技术时,不得不考虑如何将新技术 与 Spring 整合在一起。 我们知道,预研一项新技术,…

    Java 2023年5月29日
    077
  • Web开发静态资源处理

    Web开发静态资源处理 7.1 静态资源处理 我们要引入前端资源,项目中有许多的静态资源,比如css,js等文件,这个SpringBoot是怎么处理呢? 如果我们是一个web应用,…

    Java 2023年6月5日
    057
  • Logistic Regression with a Neural Network mindset

    文章内容为吴恩达深度学习第二周的编程作业 ipynbg格式代码及数据集–>陈能豆 密码: o1bn #!/usr/bin/env python coding: u…

    Java 2023年6月5日
    089
  • Java中private、protected、public和default的区别

    public: 具有最大的访问权限,可以访问任何一个在classpath下的类、接口、异常等。它往往用于对外的情况,也就是对象或类对外的一种接口的形式。 protected: 主要…

    Java 2023年5月29日
    088
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球