AOF好处是每次执行只需要记录操作命令,记录量不大。但在故障恢复时,需要逐一执行AOF的操作命令,如果日志很大,恢复就很慢。

今天学习另一种持久化方式:内存快照。内存快照,是Redis某一时刻的状态,以文件的形式保存在磁盘上。这个快照文件就称为RDB文件,其中RDB就是Redis Database的缩写。

当故障恢复时,只要把RDB文件读入内存即可,恢复速度很快。但是内存快照并不是最优选项,为什么呢?

我们还需要考虑两个问题:

  • 对哪些数据做快照?这关系到快照的执行效率;
  • 做快照时,数据还能被增删改吗?这关系到Redis是否被阻塞,能否同时正常处理请求。

对哪些数据做快照?

Redis的数据都在内存中,为了提供所有数据的可靠性保证,它执行的是全量快照。

Redis提供两个命令生成RDB文件:

  • save:在主线程中执行,但会导致阻塞;
  • bgsave:创建一个子进程,专门用于写入RDB文件,避免了主线程的阻塞。也是Redis RDB文件生成的默认配置。

做快照时,数据还能被增删改吗?

如果快照执行期间数据不能被修改,是会有潜在问题的。假如做快照的20s时间里,如果数据不能被修改,Redis就不能处理对这些数据的写操作,那无疑就会给业务服务造成巨大影响。

Redis借助操作系统提供的写时复制技术(Copy-On-Write,COW),在执行快照的同时,正常处理写操作。

bgsave子进程是由主线程fork生成的,可以共享主线程的所有内存数据。

当主线程要修改数据时,通过COW复制一份副本出来给bgsave子进程。

这既保证快照的完整性,也允许主线程同时对数据进行修改,避免了对正常业务的影响。

可以每秒做一次快照吗?

如果内存快照每隔几分钟执行一次,这样就可能出现丢失数据的风险。那么是否可以每秒做一次快照吗?

如果频繁地执行全量快照,会带来两方面开销:

  • 一是频繁将全量数据写入磁盘,会给磁盘带来很大压力。
  • 二是bgsave子进程需要从主线程fork出来,fork创建过程本身会阻塞主线程,而且主线程的内存越大,阻塞时间越长。

既然频繁执行全量快照不行,那还有什么其他好方法吗?

第一个方法是做增量快照

在第一次做完全量快照后,T1和T2时刻如果再做快照,只需要将被修改的数据写入快照文件就行了。如下图所示:

第二个方法是Redis 4.0提出一个混合使用AOF日志和RDB快照的方法:RDB快照以一定的频率执行,在两次快照之间,使用AOF日志记录这期间的所有命令操作。

T1和T2时刻的修改,用AOF日志记录,等到第二次做全量快照时,就可以清空AOF日志,因为此时的修改都已经记录到快照中了。如下图所示:

拓展

使用一个2核CPU、4GB内存、500GB磁盘的云主机运行Redis,Redis数据库的数据量大小差不多是2GB,使用了RDB做持久化保证。当时Redis的运行负载以修改操作为主,写读比例差不多在8:2左右,也就是说,如果有100个请求,80个请求执行的是修改操作。在这个场景下,用RDB做持久化有什么风险吗?

主要有两方面风险:内存资源风险CPU资源风险

内存资源风险

Redis fork子进程做RDB持久化,由于写的比例为80%,那么在持久化过程中,“写时复制”会重新分配整个实例80%的内存副本,大约需要重新分配1.6GB内存空间,这样整个系统的内存使用接近饱和。

如果此时父进程又有大量新key写入,很快机器内存就会被吃光,如果机器开启了Swap机制,那么Redis会有一部分数据被换到磁盘上。

当Redis访问这部分在磁盘上的数据时,性能会急剧下降,已经达不到高性能的标准。

如果没有开启Swap,会直接触发OOM,父子进程会面临被系统kill掉的风险。

CPU资源风险

虽然子进程在做RDB持久化,但生成RDB快照过程会消耗大量的CPU资源。

虽然Redis处理请求是单线程的,但Redis Server还有其他线程在后台工作,例如AOF每秒刷盘、异步关闭文件描述符这些操作。

由于机器只有2核CPU,这也就是意味着父进程占用了超过一半的CPU资源。

此时子进程做RDB持久化,可能会产生CPU竞争,导致的结果是父进程处理请求延迟增大,子进程生成RDB快照的时间也会变长,整个Redis Server性能下降。

如果Redis进程绑定了CPU,那么子进程会继续父进程的CPU亲和性属性,子进程必然会与父进程争夺同一个CPU资源,整个Redis Server的性能必然会受到影响。

因此如果Redis需要开启定时RDB和AOF重写,进程一定不要绑定CPU。

参考资料

Redis基础篇(四)持久化:内存快照(RDB)的更多相关文章

  1. Redis持久化——内存快照(RDB)

    最新:Redis持久化--如何选择合适的持久化方式 最新:Redis持久化--AOF日志 最新:Redis持久化--内存快照(RDB) 一文回顾Redis五大对象(数据类型) Redis对象--有序集 ...

  2. Redis基础学习(四)—Redis的持久化

    一.概述      Redis的强大性能很大程度上都是因为数据时存在内存中的,然而当Redis重启时,所有存储在内存中的数据将会丢失,所以我们要将内存中的数据持久化. Redis支持两种数据持久化的方 ...

  3. Redis的两种持久化方式-快照持久化(RDB)和AOF持久化

    Redis为了内部数据的安全考虑,会把本身的数据以文件形式保存到硬盘中一份,在服务器重启之后会自动把硬盘的数据恢复到内存(redis)的里边,数据保存到硬盘的过程就称为“持久化”效果. redis有两 ...

  4. Redis基础篇(三)持久化:AOF日志

    Redis是内存数据库,但是一旦服务器宕机,内存中的数据将会全部丢失. 最简单的恢复方式是从后端数据库恢复,但这种方式有两个问题: 频繁访问数据库,会给数据库带来巨大的压力: 从数据库中读取相比从Re ...

  5. Redis基础篇(五)AOF与RDB比较和选择策略

    RDB和AOF对比 关于RDB和AOF的优缺点,官网上面也给了比较详细的说明redis.io/topics/pers- RDB 优点: RDB快照是一个压缩过的非常紧凑的文件,保存着某个时间点的数据集 ...

  6. Redis 中的数据持久化策略(RDB)

    Redis 是一个内存数据库,所有的数据都直接保存在内存中,那么,一旦 Redis 进程异常退出,或服务器本身异常宕机,我们存储在 Redis 中的数据就凭空消失,再也找不到了. Redis 作为一个 ...

  7. redis基础篇

    1.redis常见的数据结构 redis是一种以键值对存储的高性能内存数据库,有五种常用的数据类型,string,list,hash,set,zset. 2.redis的过期时间 redis中的key ...

  8. Redis的两种持久化方式-快照持久化和AOF持久化

    Redis为了内部数据的安全考虑,会把本身的数据以文件形式保存到硬盘中一份,在服务器重启之后会自动把硬盘的数据恢复到内存(redis)的里边,数据保存到硬盘的过程就称为"持久化"效 ...

  9. docker+k8s基础篇四

    Docker+K8s基础篇(四) pod控制器 A:pod控制器类型 ReplicaSet控制器 A:ReplicaSet控制器介绍 B:ReplicaSet控制器的使用 Deployment控制器 ...

随机推荐

  1. C语言是如何诞生的?地位怎样?未来发展趋势?

      C语言的历史 C语言的原型是A语言(ALGOL 60语言). 1963年,剑桥大学将ALGOL 60语言发展成为CPL(Combined Programming Language)语言. 1967 ...

  2. 【线程池】自己声明临时线程池一定要shutdown!

    场景: 某个定时任务需要多线程执行,执行时间较久且每天只跑一次,想单独拉出一个线程池和其他业务隔离开,交给spring会导致核心线程一直存在 浪费线程资源,因此想单独拉一个池子用完就丢,原本想的是,在 ...

  3. HTTP系列(一)URI、URL、URN的区别

    ​1.URI.URL.URN关系图 1)URI Uniform Resource Identifier 统一资源标识符 每个web服务器资源都有一个名字,服务器资源名被统称为统一资源标识符:URI就像 ...

  4. 第8.1节 Python类的构造方法__init__深入剖析:语法释义

    一.    引言 凡是面向对象设计的语言,在类实例化时都有构造方法,很多语言的构造方法名与类名一致,Python中类的构造方法比较特殊,必须是__init__特殊方法. 二.    语法释义 1.   ...

  5. 转:Cookie详解

    没怎么坐过客户端相关的工作,所以写爬虫的时候,很多概念都很模糊,学习起来很困难.现在想攻坚一下,所以找了一下cookies相关的内容. HTTP cookies,通常又称作"cookies& ...

  6. Python字符串学习相关问题

    Python中format_map与format字符串格式化的区别 Python中使用f字符串进行字符串格式化的方法 Python中使用百分号占位符的字符串格式化方法中%s和%r的输出内容有何不同? ...

  7. 记阿里云 RDS MySQL 的一个大坑

    花了一个下午的时间,终于把一个阿里云 RDS MySQL 的一个大坑填上了,解决方法令人匪夷所思!绝对会让各位看官感到大吃一惊,阿里云 RDS MySQL 居然有这样 xx 的大坑! 问题 最近应业务 ...

  8. Number.isNaN和isNaN

    isNaN会通过Number方法,试图将字符串"测试"转换成Number类型,但转换失败了,因为 Number('测试') 的结果为NaN ,所以最后返回true. 而Number ...

  9. datagrip2020最新安装破解教程方法激活码安装参数

    现在,datagrip的版本已更新至2020.3,尚未升级的用户请赶快升级. 本文教您如何安装datagrip2020.3版本并破解它. 此方法可以100%永久激活datagrip2020.3(低版本 ...

  10. BJOI2017 机动训练

    落谷.Loj. Description 定义机动路径为: 没有自环 路径至少包含两个格子 从起点开始每一步都向不远离终点的方向移动 相同地形序列指路径上顺序经过的地形序列. 定义机动路径的权值为相同地 ...