首页 > 数据库 >redis——P3:持久化

redis——P3:持久化

时间:2024-06-18 19:33:05浏览次数:15  
标签:P3 持久 redis rdb 进程 save 数据

虽然缓存功能已经实现,但是作为对外提供服务的软件开发者,不能只关注是否提供了正确的服务,稳定和快速恢复等等指标是同样非常非常重要的。

考虑这样一个问题,redis确实因为不可抗力宕机了(假设我喜欢黑框框打开,然后手贱按了^C),于是瞬间redis里所有缓存全没了?这对于一个追求高性能、高可用的系统来说是不可容忍的。所以,如果有一个机制可以快速恢复数据,让这些缓存还能用,那是很好的。

下面介绍两个持久化方式,并分别指明它们的优劣。同时值得注意的是,理解持久化方式,尤其是缓冲区,对于redis集群的实现的了解有一定帮助,我会尽力写明。

RDB(Redis Database)

RDB是一种持久化的方式,思路是保存当前内存的快照到磁盘。如果发生宕机,则在再次启动时读rdb文件(安装目录下的dump.rdb),将数据再次加载到内存,以提高缓存命中率。不过,在这一部分我需要提前说明我的观点,我认为这种持久化方式更多在于要生成当前时刻内存中缓存的版本,而非所谓保存最新的数据到磁盘!最新的数据是保存不过来的。过分执着地追求所谓最新的数据,一定会带来性能上的消耗!

一起来看redis的配置文件中的文档:

################################ SNAPSHOTTING  ################################
#
# Save the DB on disk:
#
#   save <seconds> <changes>
#
#   Will save the DB if both the given number of seconds and the given
#   number of write operations against the DB occurred.
#
#   In the example below the behaviour will be to save:
#   after 900 sec (15 min) if at least 1 key changed
#   after 300 sec (5 min) if at least 10 keys changed
#   after 60 sec if at least 10000 keys changed
#
#   Note: you can disable saving completely by commenting out all "save" lines.
#
#   It is also possible to remove all the previously configured save
#   points by adding a save directive with a single empty string argument
#   like in the following example:
#
#   save ""

save 900 1
save 300 10
save 60 10000

可以发现,redis的持久化操作是以配置文件的配置为标准进行的,计算在多少秒内有多少变化(write operations),满足条件即会触发rdb。关于rdb,我认为有几点值得注意:

  • 满足上面的条件触发;
  • 手动执行rdb有两个命令,save和bgsave,save会阻塞主进程,即在主进程中做持久化操作,不会接收任何命令;bgsave和被动触发的逻辑相似,都是会fork一个子线程来执行。另外bgsave 带有一个schedule参数,当有其它子进程在执行的时候这个命令会滞后执行。两个命令之后不再解释;
  • fork出子进程、使用子进程持久化,而不是多线程,想必设计者一定有他的用意,是什么呢?
  • 保存的dump.rdb是一个内存快照,实际会丢失数据或非最新数据;我认为rdb的主要目的就是创建一份内存快照!(下面还会再提到)

从上面的特点可以容易地推断,rdb会缺失一部分数据或不是最新的数据,这一点网上很多地方归结于是redis的rdb的缺点,但是我个人不这样认为。我认为rdb的目的就是创建一份快照,并且尽可能地将最新的数据持久化到硬盘。同时,rdb快照的特性对于集群的数据同步有很大作用,这会在集群的部分再次说明。那么,既然本身目的就不是完全是保存全部数据,那么可能也不能称之缺点。(个人观点,如果从redis在历史版本中默认关闭AOF方式来看,也有可能是一开始的没有很好的持久化设计,不过个人不太敢这么想,还是认为大佬有大佬的想法较好)

被动执行的rdb的流程是什么样的?

比如当监控到如900s内有一次更新时,就会触发被动复制。主进程fork出一个子进程,由子进程去读取内存的全量数据并且写入rdb文件。

但是,我们知道,父子进程之间是会有一些共享的数据的,子进程创建伊始,父子进程内存中指向的都是同一个页帧。当备份时,有请求过来修改缓存的内容时会发生什么呢?这涉及到操作系统虚拟内存的知识,简单介绍一下操作系统的COW(Copy on Write):当创建子进程时,操作系统会让父进程和子进程的内存指向同一片区域,并将这片区域标记为只读,这样不管是谁尝试修改这片内存时都会触发一个异常,那么操作系统的异常处理程序就将复制一个新的页框,修改那个数据,然后将新的页复制给尝试修改的程序,而另外一个进程指向的地址依旧不变。也即当有写操作过来时,主进程即业务进程是会陷入中断的。不过,redis利用这个特性,可以保证最后生成的快照文件一定是开始备份时的数据,并且尽可能地减少开销。其大部分操作为读操作,所以一般需要复制新页的操作较少,不过如果当时的写操作太多,明显地,也会拖垮主线程的性能。如果数据集很大的话,fork()比较耗时,结果就是,当数据集非常大并且CPU性能不够强大的话,redis会停止服务端几毫秒甚至一秒。

可为什么偏偏是多进程?这样的事情交给一个线程去做不好吗?单机的redis影响的确不大,但是涉及到集群时,就会产生误会,这之后再说。不过,即便如此,多线程来缓存数据,有两个事情必须二选一:放弃SNAPSHOT这个特点,遇到修改操作时加锁阻塞主进程直到备份完毕。使用子进程则不存在这两个问题,最多有一些数据不是最新。不过考虑redis的特点我们就会知道,完全保证持久化所有数据是很困难的,都会损失一些数据。所以纠结这一点并没有特别大的意义。

AOF(Append Only File)

标签:P3,持久,redis,rdb,进程,save,数据
From: https://www.cnblogs.com/pidanhub/p/18254983

相关文章

  • redis——基础服务
    首先为什么要做一个redis出来?数据库不够用了吗?考虑到原本的应用程序是客户端访问服务端,服务端访问业务数据需要去数据库去拿,而数据库是个持久化的应用程序,是需要磁盘IO的,这就导致了速度会慢,并且如果存在大量的访问,会导致数据库崩溃。除去导致崩溃这样严重且极端的情况,这点性能虽然......
  • flac格式如何转mp3?7大热门实用音频转换软件大PK
    FLAC是FreeLosslessAudioCodec(免费无损音频编解码器)的缩写,是一种在压缩文件大小的同时保留原始音乐质量的音频格式。不过,大多数音频格式都会在音乐质量和文件大小之间做出权衡。当你使用flac获得更好的音乐质量时,它在电脑所占据的存储空间就会越大。与flac相比,mp3因其文件小......
  • 认识Redis
    认识RedisRedis是目前最受欢迎的NoSQL数据库之一;db-engines排名上,所有数据库类型排名第六,键值对数据库排名第一。Redis是用C语言编写的开源、支持多种数据结构、支持网络、基于内存、可选持久性的键值对内存型数据库,具备以下特征:基于内存运行、效率高单线程运行支持分布式......
  • 【面试八股总结】Redis数据结构及底层实现
    一、五种基本数据结构        Redis提供了丰富的数据类型,常见的有五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合)结构类型结构可存储值结构读写能力使用命令底层数据结构String字符串、整数或浮点数对字符串或字符串的一部分进行操作,对整数或浮点......
  • 采用java语言+Redis+RabbitMQ开发的 门诊his系统源码 一站式的门诊his系统 门诊业务流
    采用java语言+Redis+RabbitMQ开发的门诊his系统源码一站式的门诊his系统门诊业务流程医院信息系统(HIS系统)门诊业务是医院信息化建设的重要组成部分之一,它涵盖了医院门诊部门涉及的各项业务。HIS系统门诊业务的实施,可以实现医院门诊业务的信息化管理和数据化处理,提高医疗服......
  • 探索Redis的运行情况和数据——一次有趣的Redis旅程【GPT生成】
    探索Redis的运行情况和数据——一次有趣的Redis旅程前言Redis,一个高性能的键值对数据库,广泛应用于缓存、会话管理和实时数据处理。如果你正在使用Redis,你可能会好奇如何检查它的运行情况,以及它究竟存储了哪些数据。在这篇博客中,我将带你一起使用Xshell连接到服务器,探索Redis的奥......
  • Redis常见数据类型及其常用命令详解
    文章目录一、Redis概述二、Redis常用命令1.通用命令1.1KEYS:查看符合模板的所有key1.2DEL:删除一个指定的key1.3EXISTS:判断key是否存在1.4EXPIRE:给一个key设置有效期,有效期到期时该key会被自动删除1.5TTL:查看一个key的剩余有效期1.6COPY:复制Redis数据库......
  • C++ Redis 客户端简单使用
    一、准备工作1、Redis语法命令手册:https://c.biancheng.net/redis2/lpush.html2、下载我的RedisDemo示例(包含了redis源码):https://download.csdn.net/download/weixin_45075013/89446384?spm=1001.2014.3001.5503二、Redis客户端连接与使用......
  • 详解Redis 的持久化和主从复制
    在这篇文章,一起了解一下其中一个非常重要的内容:Redis的持久化机制。什么是Redis持久化?Redis作为一个键值对内存数据库(NoSQL),数据都存储在内存当中,在处理客户端请求时,所有操作都在内存当中进行,如下所示:  这样做有什么问题呢?其实,只要稍微有点计算机基础知识的人都知道,存......
  • Redis是一个高性能的键值对数据库,它支持多种数据结构,如字符串、列表、集合、有序集合
    Redis是一个高性能的键值对数据库,它支持多种数据结构,如字符串、列表、集合、有序集合和哈希表。以下是一些Redis命令的实践示例,帮助你了解如何使用Redis。连接Redis服务器首先,使用redis-cli命令连接到Redis服务器:redis-cli-h<hostname>-p<port>基本命令PING:检查Redis......