热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Redis怎么防止数据丢失?面试必问!

Redis要想实现高可用,主要有以下方面来保证:数据持久化主从复制自动故障恢复集群化这篇文章我们先介绍Redis的高可用保障的基础:数据持

Redis要想实现高可用,主要有以下方面来保证:

  • 数据持久化

  • 主从复制

  • 自动故障恢复

  • 集群化

这篇文章我们先介绍Redis的高可用保障的基础:数据持久化

因为Redis的主从复制和自动故障恢复,都需要依赖Redis持久化相关的东西。同时,Redis的数据持久化也可以用来做数据备份,用来保障数据的安全性。

Redis是一个内存数据库,它的数据都保存在内存中,如果实例宕机,那么数据则全部丢失。如何保证数据的完整性和安全性也是提高服务高可用的重要机制之一。

Redis提供了完善的持久化机制,可以把内存中的数据持久化到磁盘上,方便我们进行备份数据和快速恢复数据。

这篇文章我们就来分析Redis的数据持久化是如何实现的?我们经常听的RDB和AOF有什么区别?以及它们不同的使用场景。

持久化方式

Redis提供的数据持久化方式主要有2种:

  • RDB:产生一个数据快照文件

  • AOF:实时追加命令的日志文件

它们分别对应了不同的使用场景,下面我们就来依次分析。

RDB

介绍

RDB全称Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。

我们可以通过执行savebgsave命令让Redis在本地生成RDB快照文件,这个RDB文件包含了整个实例接近完整的数据内容。

它的优点如下:

  • RDB文件数据是被压缩写入的,因此RDB文件的体积要比整个实例内存要小

  • 当实例宕机恢复时,加载RDB文件的速度很快,能够在很短时间内迅速恢复文件中的数据

它的缺点也很明显:

  • 由于是某一时刻的数据快照,因此它的数据并不全

  • 生成RDB文件的代价是比较大的,它会消耗大量的CPU和内存资源

因此RDB比较适用于以下场景:

  • 主从全量同步数据

  • 数据库备份

  • 对于丢失数据不敏感的业务场景,实例宕机后快速恢复数据

Redis主从全量同步数据就是使用RDB文件进行的,我们会在后面的文章详细讲到,关注公众号Java技术栈第一时间推送。

由此可以看出,RDB非常适合做数据备份,我们可以定时让Redis生成RDB文件,然后备份这个快照文件即可。

定时生成RDB

Redis也提供了定时触发生成RDB文件的配置项:

# 最近15分钟内 至少产生1次写入  
save 900 1  
# 最近5分钟内 至少产生10次写入  
save 300 10  
# 最近1分钟内 至少产生10000次写入  
save 60 10000  

如果达到以上任意条件,则Redis会自动生成新的RDB文件,降低RDB数据内容与实例数据的差异。

Copy On Write

在Redis上执行savebgsave命令都可以生成RDB文件,但前者是在前台执行的,也就是说在生成RDB文件时,会阻塞整个实例,在RDB未生成之前,任何请求都是无法处理的,对于内存很大的实例,生成RDB文件非常耗时,显然这是我们不能接受的。

所以通常我们会选择执行bgsave让Redis在后台生成RDB文件,这样Redis依旧可以处理客户端请求,不会阻塞整个实例。

但不是说后台生成RDB就是没有代价的,Redis为了实现后台把内存数据的快照写入文件,采用了操作系统提供的Copy On Write技术,也就是我们熟知的fork系统调用。

fork系统调用会产生一个子进程,它与父进程共享相同的内存地址空间,这样子进程在这一时刻就能拥有与父进程的相同的内存数据。

虽然子进程与父进程共享同一块内存地址空间,但在fork子进程时,操作系统需要拷贝父进程的内存页表给子进程,如果整个Redis实例内存占用很大,那么它的内存页表也会很大,在拷贝时就会比较耗时,同时这个过程会消耗大量的CPU资源。在完成拷贝之前父进程也处于阻塞状态,无法处理客户端请求。

fork执行完之后,子进程就可以扫描自身所有的内存数据,然后把全部数据写入到RDB文件中。

之后父进程依旧处理客户端的请求,当在处理写命令时,父进程会重新分配新的内存地址空间,从操作系统申请新的内存使用,不再与子进程共享,这个过程就是Copy On Write(写实复制)名字的由来。这样父子进程的内存就会逐渐分离,父进程申请新的内存空间并更改内存数据,子进程的内存数据不受影响。

由此可以看出,在生成RDB文件时,不仅消耗CPU资源,还有需要占用最多一倍的内存空间。

我们在Redis执行info命令,可以看到fork子进程的耗时,可以通过这个耗时来评估fork时间是否符合预期。同时我们应该保证Redis机器拥有足够的CPU和内存资源,并合理设置生成RDB的时机。

AOF

介绍

AOF全称为Append Only File(追加日志文件)。它与RDB不同的是,AOF中记录的是每一个命令的详细信息,包括完整的命令类型、参数等。只要产生写命令,就会实时写入到AOF文件中。

我们可以通过配置文件开启AOF:

# 开启AOF  
appendonly yes  # AOF文件名  
appendfilename "appendonly.aof"  # 文件刷盘方式  
appendfsync everysec  

刷盘方式

开启AOF后,Redis会把每个写操作的命令记录到文件并持久化到磁盘中,为了保证数据文件的安全性,Redis还提供了文件刷盘的时机:

  • appendfsync always:每次写入都刷盘,对性能影响最大,占用磁盘IO比较高,数据安全性最高

  • appendfsync everysec:1秒刷一次盘,对性能影响相对较小,节点宕机时最多丢失1秒的数据

  • appendfsync no:按照操作系统的机制刷盘,对性能影响最小,数据安全性低,节点宕机丢失数据取决于操作系统刷盘机制

以上可以看出AOF相对于RDB的优点是,AOF数据文件更新比较及时,比RDB保存更完整的数据,这样在数据恢复时能够恢复尽量完整的数据,降低丢失数据的风险。

如果同时存在RDB文件和AOF文件,Redis会优先使用AOF文件进行数据恢复。

但它的缺点也很易见:

  • 随着时间增长,AOF文件会越来越大

  • AOF文件刷盘会增加磁盘IO的负担,可能影响Redis的性能(开启每秒刷盘时)

AOF重写

针对第一种情况,Redis提供了AOF瘦身的功能,可以设置在AOF文件很大时,自动触发AOF重写,Redis会扫描整个实例的数据,重新生成一个AOF文件达成瘦身的效果。但这个重写过程也需要消耗大量的CPU资源。

# AOF文件距离上次文件增长超过多少百分比则触发重写  
auto-aof-rewrite-percentage 100  
# AOF文件体积最小多大以上才触发重写  
auto-aof-rewrite-min-size 64mb  

由于AOF可以最大可能降低丢失数据的风险,所以它一般适用于对丢失数据很敏感的业务场景,例如涉及金钱交易的业务。

性能影响

如果AOF的刷盘时机设置为每次写入都刷盘,那么会大大降低Redis的写入性能,因为每次写命令都需要写入文件并刷到磁盘中才会返回,当写入量很大时,会增加磁盘IO的负担。

性能与数据安全不能兼得,虽然Redis提供了实时刷盘的机制,但是在真正场景中使用的不多。

通常我们会选择每秒刷盘这种方式,既能保证良好的写入性能,在实例宕机时最多丢失1秒的数据,做到性能和安全的平衡。

总结

我们对RDB和AOF的总结如下表。

我们需要针对不同的业务场景选择合适的持久化方式,也可以根据RDB和AOF的优点配合使用,保证Redis数据的安全性,又可以兼顾它的性能。

作者:Kaito
链接:kaito-kidd.com/2020/06/29/redis-persistence-rdb-aof/

IT技术分享社区

个人博客网站:https://programmerblog.xyz

文章推荐程序员效率:画流程图常用的工具程序员效率:整理常用的在线笔记软件远程办公:常用的远程协助软件,你都知道吗?51单片机程序下载、ISP及串口基础知识硬件:断路器、接触器、继电器基础知识



推荐阅读
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 先看一段错误日志:###Errorqueryingdatabase.Cause:com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransie ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 背景应用安全领域,各类攻击长久以来都危害着互联网上的应用,在web应用安全风险中,各类注入、跨站等攻击仍然占据着较前的位置。WAF(Web应用防火墙)正是为防御和阻断这类攻击而存在 ... [详细]
author-avatar
xin丶儿_462
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有