论Redis的持久性

持久性一直是Redis使用中的一个重要话题。很多同学在使用Redis的过程中,对于如何选择持久性策略,如何配置持久性都有疑问。本文试图对Redis的持久性进行系统的分析和比较,以期正确认识Redis的持久性,并结合实际应用选择合理的持久性机制。

1.背景知识
持久性是数据存储领域的一个常见话题。持久性可以描述为将相关数据存储在非易失性存储器中的过程。数据持久化后,即使发生一定程度的故障,只要持久化的设备没有损坏,我们就可以使用持久化的数据进行恢复,在一定程度上减少了故障造成的损失。

我们使用的数据存储,无论是传统的关系型数据库,还是类似Redis的所谓NoSQL,都是在运行后运行在操作系统上的程序,应用程序发送的数据需要经过这些数据存储程序的处理,才能以某种格式持久存储。在这个过程中,数据必须通过应用程序的内存,并由CPU操作,然后才能存储在持久设备上。所以要理解坚持,必须要有几个方面的背景知识。
1.1用户空间、内核空间和内核缓冲区
在Linux中,为了保证操作系统稳定高效的运行,内存空间分为用户空间和内核空间。简单来说,每个应用通常位于用户空间,而操作系统内核运行在内核空间。之所以这样划分,是因为调用操作系统的很多功能都会触发敏感资源的操作,比如清空内存,设置时钟等等。为了防止每个程序操作敏感资源而导致系统崩溃,内存空间按上述方式划分。在用户空间,应用程序没有操作敏感资源的权限(相应的指令受到限制),从而避免了可能出现的系统崩溃等异常现象。

众所周知,大多数应用程序都无法避免处理底层资源,如从磁盘读取数据、从网络读取或接收消息等。但是,在划分用户空间和系统空间后,应用程序无权访问系统资源。为了解决这个问题,操作系统为应用程序公开了一系列的系统调用接口(System Call Interface)来与底层资源进行交互,这样应用程序就可以通过调用这些接口来访问资源。我们常见的系统调用有write(),read()等等。

那么当应用程序触发系统调用接口时会发生什么呢?我们以写文件为例。当应用程序调用写操作时,系统不直接访问硬盘写文件,而是先将文件写入内核缓冲区,然后定期将内核缓冲区中的数据批量写入磁盘(这个过程也可以由应用程序通过触发调用fsync()来完成)。显然,内核缓冲区被划分的原因主要是为了解决底层IO读写速度和内存读写速度不匹配的问题。如果频繁同步写入硬盘,会严重降低程序的运行速度。

一般来说,要理解持久化的过程,需要知道在Linux操作系统中,内存分为用户空间和内核空间。当应用程序中的数据需要写入文件时,会依次通过应用程序内存和内核缓冲区写入硬盘。此过程涉及的系统调用包括写操作write()和强制硬盘同步操作fsync()。

1.2写入时复制
众所周知,在linux系统中,您可以通过调用fork()创建一个与父进程完全相同的子进程副本。但是在fork的过程中,如果父进程占用的内存空间太大,可能需要很长时间来复制内存数据,这会使父进程无法响应其他命令,这对于一个面向客户端的服务器程序来说是无法接受的。

为了解决这个问题,大佬们提出了写时复制技术。简单来说,写时复制技术是指在fork的过程中,应用程序的内存没有被完全复制,而是在子进程中创建一个指向父进程对应内存地址的引用,只有在子进程读取内存,发现数据是复制后新写入的时候,才执行实际的复制动作。这样,由于在fork的过程中不需要完成整个数据的复制,因此大大减少了fork()调用的时间消耗。

但实际上,写时复制技术并没有完全解决问题。比如一些大型应用占用了非常大的内存空间(比如一个Redis实例占用了几十G的内存),只指向内存地址需要很长时间。

最后,对于Redis持久化,我们只需要知道持久化过程中会涉及到fork call(发生在RDB模式和AOF重写的时候)。Linux虽然采用了写时复制技术,但是在实例内存占用量较大的情况下,fork调用仍然可能带来长期的阻塞。

前面我们简单讨论了Linux的两个背景知识点:内存空间分区和写时复制(Linux对fork调用的消耗做的一个优化,即使做了这个优化,高内存占用的实例在fork期间可能还是会长时间阻塞)。接下来,我们分析持久化过程中的数据写入过程。

2.持久数据写入的过程
当我们使用某种数据存储来保存应用数据时,数据由应用程序通过网络发送到数据存储程序,然后由数据存储程序进行处理和计算,然后以一定的格式存储在硬盘等持久性设备中。这个过程涉及很多步骤,比如网络调用、程序处理、操作系统写文件等。为了让下面的讨论更清晰,我们对这一步进行了一定程度的分解。简而言之,应用程序数据从生成到存储到永久设备经历了以下步骤:

客户端向数据库服务器发送写入或更新数据的请求,此时数据位于客户端内存中

当服务器接收到写命令时,数据位于服务器数据库的应用程序内存中(从服务器的角度来看,数据位于应用程序(数据库)内存中,即用户模式内存中)

数据库调用系统函数将数据写入硬盘,此时数据位于内核的缓冲区

操作系统将数据从写缓冲区传输到硬盘控制器,而数据位于硬盘缓存中

硬盘控制器实际上将数据写入物理介质

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值