新闻资讯  快讯  焦点  财经  政策  社会
互 联 网   电商  金融  数据  计算  技巧
生活百科  科技  职场  健康  法律  汽车
手机百科  知识  软件  修理  测评  微信
软件技术  应用  系统  图像  视频  经验
硬件技术  知识  技术  测评  选购  维修
网络技术  硬件  软件  设置  安全  技术
程序开发  语言  移动  数据  开源  百科
安全防护  资讯  黑客  木马  病毒  移动
站长技术  搜索  SEO  推广  媒体  移动
财经百科  股票  知识  理财  财务  金融
教育考试  育儿  小学  高考  考研  留学
您当前的位置:首页 > IT百科 > 数据库 > Redis

一文深度揭开Redis的磁盘持久化机制

时间:2019-12-02 13:10:28  来源:  作者:

redis内存数据库,数据都是存储在内存中,为了避免进程退出导致数据的永久丢失,需要定期将 Redis 中的数据以数据或命令的形式从内存保存到本地磁盘。当下次 Redis 重启时,利用持久化文件进行数据恢复。Redis 提供了 RDB 和 AOF 两种持久化机制,前者将当前的数据保存到磁盘,后者则是将每次执行的写命令保存到磁盘(类似于 MySQL 的 Binlog)。本文将详细介绍 RDB 和 AOF 两种持久化方案,包括操作方法和持久化的实现原理。

正文

Redis 是一个基于 K-V 存储的数据库服务器,下面先介绍 Redis 数据库的内部构造以及 K-V 的存储形式,有助于我们更容易理解 Redis 的持久化机制。

一文深度揭开Redis的磁盘持久化机制

 

1. Redis数据库结构

一个单机的 Redis 服务器默认情况下有 16 个数据库(0-15号),默认使用的是 0 号数据库,可以使用 SELECT 命令切换数据库。

一文深度揭开Redis的磁盘持久化机制

 

Redis 中的每个数据库都由一个 redis.h/redisDb 结构表示,它记录了单个 Redis 数据库的键空间、所有键的过期时间、处于阻塞状态和就绪状态的键、数据库编号等等。

typedef struct redisDb {
 // 数据库键空间,保存着数据库中的所有键值对
 dict *dict;
 // 键的过期时间,字典的键为键,字典的值为过期事件 UNIX 时间戳
 dict *expires;
 // 正处于阻塞状态的键
 dict *blocking_keys;
 // 可以解除阻塞的键
 dict *ready_keys;
 // 正在被 WATCH 命令监视的键
 dict *watched_keys;
 struct evictionPoolEntry *eviction_pool;
 // 数据库编号
 int id;
 // 数据库的键的平均 TTL,统计信息
 long long avg_ttl;
} redisDb;
复制代码

由于 Redis 是一个键值对数据库(key-value pairs database), 所以它的数据库本身也是一个字典,对应的结构正是 redisDb。其中,dict 指向的是一个记录键值对数据的字典,它的键是一个字符串对象,它的值则可以是字符串、列表、哈希表、集合和有序集合在内的任意一种 Redis 类型对象。 expires 指向的是一个用于记录键的过期时间的字典,它的键为 dict 中的数据库键,它的值为这个数据库键的过期时间戳,这个值以 long long 类型表示。

一文深度揭开Redis的磁盘持久化机制

 

2. RDB持久化

RDB 持久化(也称作快照持久化)是指将内存中的数据生成快照保存到磁盘里面,保存的文件后缀是 .rdb。rdb 文件是一个经过压缩的二进制文件,当 Redis 重新启动时,可以读取 rdb 快照文件恢复数据。RDB 功能最核心的是 rdbSave 和 rdbLoad 两个函数, 前者用于生成 RDB 文件并保存到磁盘,而后者则用于将 RDB 文件中的数据重新载入到内存中:

一文深度揭开Redis的磁盘持久化机制

 

RDB 文件是一个单文件的全量数据,很适合数据的容灾备份与恢复,通过 RDB 文件恢复数据库耗时较短,通常 1G 的快照文件载入内存只需 20s 左右。Redis 提供了手动触发保存、自动保存间隔两种 RDB 文件的生成方式,下面先介绍 RDB 的创建和载入过程。

 

2.1. RDB的创建和载入

2.1.1. 手动触发保存

Redis 提供了两个用于生成 RDB 文件的命令,一个是 SAVE,另一个是 BGSAVE。而触发 Redis 进行 RDB 备份的方式有两种,一种是通过 SAVE 命令、BGSAVE 命令手动触发快照生成的方式,另一种是配置保存时间和写入次数,由 Redis 根据条件自动触发保存操作。

1. SAVE命令

SAVE 是一个同步式的命令,它会阻塞 Redis 服务器进程,直到 RDB 文件创建完成为止。在服务器进程阻塞期间,服务器不能处理任何其他命令请求。

  • 客户端命令
127.0.0.1:6379> SAVE
OK
复制代码
  • 服务端日志
6266:M 15 Sep 2019 08:31:01.258 * DB saved on disk
复制代码

执行 SAVE 命令后,Redis 在服务端进程(PID为6266)执行了 SAVE 操作,这个操作发生期间会一直阻塞 Redis 客户端的请求处理。

 

2. BGSAVE命令

BGSAVE 是一个异步式的命令,和 SAVE 命令直接阻塞服务器进程的做法不同,BGSAVE 命令会派生出一个子进程,由子进程负责创建 RDB 文件,服务器进程(父进程)继续处理客户的命令。

  • 客户端命令
127.0.0.1:6379> BGSAVE
Background saving started
复制代码
  • 服务端日志
6266:M 15 Sep 2019 08:31:22.914 * Background saving started by pid 6283
6283:C 15 Sep 2019 08:31:22.915 * DB saved on disk
6266:M 15 Sep 2019 08:31:22.934 * Background saving terminated with success
复制代码

通过服务端输出的日志,可以发现Redis 在服务端进程(PID为6266)会为 BGSAVE 命令单独创建(fork)一个子进程(PID为6283),并由子进程在后台完成 RDB 的保存过程,在操作完成之后通知父进程然后退出。在整个过程中,服务器进程只会消耗少量时间在创建子进程和处理子进程信号量上面,其余时间都是待命状态。

BGSAVE 是触发 RDB 持久化的主流方式,下面给出 BGSAVE 命令生成快照的流程:

一文深度揭开Redis的磁盘持久化机制

 

  1. 客户端发起 BGSAVE 命令,Redis 主进程判断当前是否存在正在执行备份的子进程,如果存在则直接返回
  2. 父进程 fork 一个子进程 (fork 的过程中会造成阻塞的情况),这个过程可以使用 info stats 命令查看 latest_fork_usec 选项,查看最近一次 fork 操作消耗的时间,单位是微秒
  3. 父进程 fork 完成之后,则会返回 Background saving started 的信息提示,此时 fork 阻塞解除
  4. fork 创建的子进程开始根据父进程的内存数据生成临时的快照文件,然后替换原文件
  5. 子进程备份完毕后向父进程发送完成信息,父进程更新统计信息

3. SAVE和BGSAVE的比较

命令SAVEBGSAVEIO类型同步异步是否阻塞全程阻塞fork时发生阻塞复杂度O(n)O(n)优点不会消耗额外的内存不阻塞客户端缺点阻塞客户端fork子进程消耗内存

2.1.2. 自动触发保存

因为 BGSAVE 命令可以在不阻塞服务器进程的情况下执行,所以 Redis 的配置文件 redis.conf 提供了一个 save 选项,让服务器每隔一段时间自动执行一次 BGSAVE 命令。用户可以通过 save 选项设置多个保存条件,只要其中任意一个条件被满足,服务器就会执行 BGSAVE 命令。 Redis 配置文件 redis.conf 默认配置了以下 3 个保存条件:

save 900 1
save 300 10 
save 60 10000
复制代码

那么只要满足以下 3 个条件中的任意一个,BGSAVE 命令就会被自动执行:

  • 服务器在 900 秒之内,对数据库进行了至少 1 次修改。
  • 服务器在 300 秒之内,对数据库进行了至少 10 次修改。
  • 服务器在 60 秒之内,对数据库进行了至少 10000 次修改。

Redis 服务器会周期性地操作 serverCron 函数,这个函数每隔 100 毫秒就会执行一次,它的一项任务就是检查 save 选项所设置的保存条件是否满足,如果满足的话,就自动执行 BGSAVE 命令。

2.1.3. 启动自动载入

和使用 SAVE 和 BGSAVE 命令创建 RDB 文件不同,Redis 没有专门提供用于载入 RDB 文件的命令,RDB 文件的载入过程是在 Redis 服务器启动时自动完成的。启动时只要在指定目录检测到 RDB 文件的存在,Redis 就会通过 rdbLoad 函数自动载入 RDB 文件。

下面是 Redis 服务器启动时打印的日志,倒数第 2 条日志是在成功载入 RDB 文件后打印的。

$ redis-server /usr/local/etc/redis.conf
6266:C 15 Sep 2019 08:30:41.830 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=6266, just started
6266:C 15 Sep 2019 08:30:41.830 # Configuration loaded
6266:M 15 Sep 2019 08:30:41.831 * Increased maximum number of open files to 10032 (it was originally set to 256).
6266:M 15 Sep 2019 08:30:41.832 # Server initialized
6266:M 15 Sep 2019 08:30:41.833 * DB loaded from disk: 0.001 seconds
6266:M 15 Sep 2019 08:30:41.833 * Ready to accept connections
复制代码

由于 AOF 文件属于增量的写入命令备份,RDB 文件属于全量的数据备份,所以更新频率比 RDB 文件的更新频率高。所以如果 Redis 服务器开启了 AOF 持久化功能,那么服务器会优先使用 AOF 文件来还原数据库状态;只有在 AOF 的持久化功能处于关闭状态时,服务器才会使用优先使用 RDB 文件还原数据库状态。

一文深度揭开Redis的磁盘持久化机制

 

2.2. RDB的文件结构

RDB 文件是经过压缩的二进制文件,下面介绍关于RDB文件的一些细节。

2.2.1. 存储路径

SAVE 命令和 BGSAVE 命令都只会备份当前数据库,备份文件名默认为 dump.rdb,可通过配置文件修改备份文件名 dbfilename xxx.rdb。可以通过以下命令查看备份文件目录和 RDB 文件名称:

$ redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> CONFIG GET dir
1) "dir"
2) "/usr/local/var/db/redis"
127.0.0.1:6379> CONFIG GET dbfilename
1) "dbfilename"
2) "dump.rdb"
复制代码

RDB 文件的存储路径既可以在启动前配置,也可以通过命令动态设定。

  • 配置项:通过 dir 配置指定目录,dbfilename 指定文件名
  • 动态指定:Redis 启动后也可以动态修改 RDB 存储路径,在磁盘损害或空间不足时非常有用,执行命令为:
config set dir {newdir}
config set dbfilename {newFileName}
复制代码


Tags:Redis   点击:()  评论:()
声明:本站部分内容来自互联网,内容观点仅代表作者本人,如有任何版权侵犯请与我们联系,我们将立即删除。
▌相关评论
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
▌相关推荐
Redis 是内存数据库,数据都是存储在内存中,为了避免进程退出导致数据的永久丢失,需要定期将 Redis 中的数据以数据或命令的形式从内存保存到本地磁盘。当下次 Redis 重启时,利用...【详细内容】
2019-12-02   Redis  点击:(0)  评论:(0)  加入收藏
我先说下结果。我现在还不敢放线上去测,这是本地测的数据,我4g内存的电脑本地开redis,一次都没写完过全部数据,都是写一半后不是redis挂就是测试程序挂。可以肯定的是总记录数是以千万为单位的。O(log(n千万/range))的时间...【详细内容】
2019-12-02   Redis  点击:(0)  评论:(0)  加入收藏
慢查询,大家可能已经接触到了MySQL的慢查询。我们配置一个时间,如果查询时间超过了我们设置的时间,我们就认为这是一个慢查询. 如上图所示:Redis客户端一条命令执行分4个步骤: 发...【详细内容】
2019-11-29   Redis  点击:(7)  评论:(0)  加入收藏
ip192.168.1.111 主192.168.1.112 从192.168.1.113 从安装redis 安装依赖yum install gcc gcc-c++ -y 下载redis-4.0.11.tar.gzcd /usr/localwget http://download.redis.i...【详细内容】
2019-11-28   Redis  点击:(2)  评论:(0)  加入收藏
常用的 SQL 数据库的数据都是存在磁盘中的,虽然在数据库底层也做了对应的缓存来减少数据库的 IO 压力。 图片来自 Pexels由于数据库的缓存一般是针对查询的内容,而且粒度也...【详细内容】
2019-11-27   Redis  点击:(2)  评论:(0)  加入收藏
概念:Redis是用C语言开发的一个开源的高性能键值对数据库。特征: 数据间没有必然的联系 内部采用单线程机制进行工作 高性能 多数据类型支持字符串类型 String列表类型 List散...【详细内容】
2019-11-27   Redis  点击:(3)  评论:(0)  加入收藏
本文实例讲述了php+redis实现注册、删除、编辑、分页、登录、关注等功能。分享给大家供大家参考,具体如下:主要界面 连接redisredis.php<?php //实例化 $redis = new Redis();...【详细内容】
2019-11-26   Redis  点击:(1)  评论:(0)  加入收藏
客户端的连接的建立Redis通过在TCP端口上进行监听,或者Unix socket(如果启用)的方式来接受客户端的连接。当一个新的客户端连接被接受执行以下操作: 当Redis使用非阻塞I/O复用,...【详细内容】
2019-11-25   Redis  点击:(5)  评论:(0)  加入收藏
最近忙于业务开发、交接和游戏,加上碰上了不定时出现的犹豫期和困惑期,荒废学业了一段时间。天冷了,要重新拾起开始下阶段的学习了。之前接触到的一些数据搜索项目,涉及到请求模...【详细内容】
2019-11-22   Redis  点击:(8)  评论:(0)  加入收藏
MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。...【详细内容】
2019-11-22   Redis  点击:(13)  评论:(0)  加入收藏
一、项目介绍Rotter是禧云自主研发的跨机房Redis双向同步解决方案(下文简称为方案),具有零侵入、高吞吐量、低延时、高堆积能力等特点。当前版本支持Sentinel模式和单点模式Red...【详细内容】
2019-11-20   Redis  点击:(7)  评论:(0)  加入收藏
适合的读者:初级程序员前言虽然现在大多数后端服务都是部署在linux服务器上的,代码开发工作很多人是在windows下进行的,由于redis官方没有windows下的版本,所以大家第一次使用的...【详细内容】
2019-11-15   Redis  点击:(9)  评论:(0)  加入收藏
Redis以内存数据库而闻名。但是,某些系统将它用作消息队列管理工具。Pub/Sub 和 RPOPLPUSH 是用于实现这样一个系统的两组命令。在这篇文章中,我将分享一些关于这两个命令集的...【详细内容】
2019-11-14   Redis  点击:(6)  评论:(0)  加入收藏
压缩列表ziplist的zset内部有两种存储结构,一种是ziplist,另一种是跳跃列表skiplist。为了彻底理解zset的内部结构,我们就再来介绍一下skiplist。skiplist介绍顾名思义,skiplist...【详细内容】
2019-11-13   Redis  点击:(12)  评论:(0)  加入收藏
Jedis api 在线网址:http://tool.oschina.net/uploads/apidocs/redis/clients/jedis/Jedis.htmlredisson 官网地址:https://redisson.org/redisson git项目地址:https://githu...【详细内容】
2019-11-11   Redis  点击:(43)  评论:(0)  加入收藏
一、Redis简介Redis是一个开源的使用ANSI C语言编写的Key-Value数据库,是一种应用非常广泛的NoSQL数据库,性能极高,拥有出色的读写速度,适用性非常的广。因此也被广泛应用在中大...【详细内容】
2019-11-01   Redis  点击:(13)  评论:(0)  加入收藏
1、系统架构 2、服务器情况 服务器 1:nginx(80)、redis(6379) 服务器 2:tomcat1(8080)、tomcat2(8080) 服务器 3:mysql(3306)3、Nginx 主要配置http { ...... upstream tomcat { ip_hash;...【详细内容】
2019-10-30   Redis  点击:(15)  评论:(0)  加入收藏
redis在现在的系统中用的越来越多了,分布式锁,缓存,附近的人,排行榜,简易版的消息队列,发布订阅等。redis中有很多命令,每个命令又有很多参数,如果让我们全部记住很不现实,今天就推...【详细内容】
2019-10-30   Redis  点击:(13)  评论:(0)  加入收藏
Redis支持主从复制功能,用户可以通过执行slaveof命令或者在配置文件中设置slaveof选项来开启复制功能。例如,现在有两台服务器—127.0.0.1:6379和127.0.0.1:7000,向服务器...【详细内容】
2019-10-28   Redis  点击:(14)  评论:(0)  加入收藏
redis存储类型主要提供了5种数据结构:字符串(String)、哈希(hash)、列表(list)、集合(set)、有序集合(short set);redis底层实现的8种数据结构SDS simple synamic string:支持自...【详细内容】
2019-10-28   Redis  点击:(14)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条