Redis设计与实现2.2:数据持久化
数据持久化
这是《Redis设计与实现》系列的文章,系列导航:Redis设计与实现笔记
RDB持久化
RDB 持久化功能所生成的 RDB 文件是一个经过压缩的二进制文件,通过该文件可以还原生成 RDB 文件时的数据库状态。
基本使用

另外,由于AOF文件更新更频繁,所以:
优先使用AOF进行还原
只有AOF关闭时才会进行RDB备份
BGSAVE 虽然是非阻塞的,但是在进行时会拒绝掉 SAVE、BGSAVE命令,BGREWRITEAOF 会被推迟到执行完再执行。
而如果 BGREWRITEAOF 正在执行,则 BGSAVE 会被拒绝。
自动保存功能
设置
save 900 1
save 300 10
只要满足如下条件的一个,BGSAVE就会被执行:
- 900s内,对数据库至少进行了1次修改
- 300s内,对数据库至少进行了10次修改
原理
上述的配置信息保存的结构如下图所示:1

另外,程序还需要记录对应这两个配置在数据库中对应的信息:
- dirty计数器:记录距离上一次成功执行 SAVE 命令或者 BGSAVE 命令之后,服务器对数据库状态进行了多少次修改
- lastsave:记录上一次成功执行备份的UNIX时间戳
Redis服务器周期性操作函数 serverCron 默认每 100 毫秒执行一次,用于对正在运行的服务器进行维护,其中一项工作就是检查 save 选项保存的条件是否满足。
RDB文件结构

这里只给出了一个简单的关系图,如果想要了解具体的内容请阅读原书。
AOF持久化
AOF 持久化是通过保存 Redis 服务器所执行的写命令来记录数据库的状态的。
写入AOF的步骤
三步骤:
- 命令追加:服务器执行完一个写命令后,会追加到服务器状态的
aof_buf缓冲区的末尾 - 文件写入:serverCron 函数在定时运行的时候会调用
flushAppendOnlyFile函数,考虑是否将上述缓冲区的内容写入和保存到 AOF 文件中 - 文件同步
写入和同步:
为了提高文件的写入效率,在现代操作系统中,当用户调用 write 函数时会先将数据保存在一个内存缓冲区里,等超过一定的时限或空间被填满再写入磁盘。
这样虽然提高了效率,但是可能会影响安全性。
为此,系统提供了
fsync和fdatasync可以强制让操作系统立刻同步到硬盘中。
appendfsync 参数配置:
- always:总是写入并同步
- everysec:每秒进行写入并同步
- no:写入但不同步
载入AOF的步骤
(很直观的步骤)
- 创建一个不带网络连接的伪客户端
- 从AOF文件中分析并读取一条写命令
- 使用伪客户端执行该命令
- 重复上述步骤,直到所有命令完成
AOF 重写
为什么?
由于 AOF 时通过保存被执行的写命令来记录数据库状态的,所以随着服务器运行时间的流逝,AOF 文件的内容会越来越多,文件体积也会越来越大,需要加以控制,以免对 Redis 服务器、甚至整个宿主机造成影响。
怎么做?
BGREWRITEAOF 命令进行 AOF 重写。
重写的实现?
最简单的方法是通过分析 Redis 中的数据,然后生成相应的插入指令,而不是通过分析之前的命令来判断哪些可以被跳过。
后台重写
为了在重写过程中也能处理请求,可以采用后台重写的方式。当然在重写的过程中数据也可能发生变化,所以要设置一个 AOF 重写缓冲区。(类似主从复制时的操作)

当子进程完成 AOF 重写工作后,他会向父进程发送一个信号,父进程在接到该信号之后,就会调用一个信号处理函数(阻塞),并执行如下工作:
- 将 AOF 重写缓冲区的内容写入到新的 AOF 文件中
- 对新的 AOF 文件进行改名,原子地覆盖现有的 AOF 文件
Redis设计与实现2.2:数据持久化的更多相关文章
- redis启动加载过程、数据持久化
背景 公司一年的部分业务数据放在redis服务器上,但数据量比较大,单纯的string类型数据一年就将近32G,而且是经过压缩后的. 所以我在想能否通过获取string数据的时间改为保存list数据类 ...
- Redis 设计与实现 (三)--持久化
RDB 持久化 一.生成RDB cmd:SAVE --阻塞进程,执行完,才能有效接收客户端命令. cmd: BGSAVE --非阻塞,开启子进程保存. 客户端如果发送SAVE和BGSAVE命令直 ...
- 【笔记】《Redis设计与实现》chapter10 RDB持久化
chapter10 RDB持久化 10.1 RDB文件的创建和载入 有两个Redis命令可以用于生成RDB文件,SAVE和BGSAVE SAVE阻塞服务器进程进行RDB文件的创建,BGSAVE则创建服 ...
- 【笔记】《Redis设计与实现》chapter11 AOF持久化
11.1 AOF持久化的实现 命令追加 当AOF持久化处于开启状态时,服务器执行完一个写命令之后,会以协议格式将被执行的写明了追加到服务器状态的aof_buf缓冲区 struct redisServe ...
- redis 配置文件 append only file(aof)部分---数据持久化
############################## 仅追加方式 ############################### #默认情况下Redis会异步的将数据导出到磁盘上.这种模式对许 ...
- Redis学习笔记(5)——Redis数据持久化
出处http://www.cnblogs.com/xiaoxi/p/7065328.html 一.概述 Redis的强大性能很大程度上都是因为所有数据都是存储在内存中的,然而当Redis重启后,所有存 ...
- redis学习——数据持久化
一.概述 Redis的强大性能很大程度上都是因为所有数据都是存储在内存中的,然而当Redis重启后,所有存储在内存中的数据将会丢失,在很多情况下是无法容忍这样的事情的.所以,我们需要将内存中的数据持久 ...
- redis学习(九)——数据持久化
一.概述 Redis的强大性能很大程度上都是因为所有数据都是存储在内存中的,然而当Redis重启后,所有存储在内存中的数据将会丢失,在很多情况下是无法容忍这样的事情的.所以,我们需要将内存中的数据持久 ...
- Redis 中的数据持久化策略(AOF)
上一篇文章,我们讲的是 Redis 的一种基于内存快照的持久化存储策略 RDB,本质上他就是让 redis fork 出一个子进程遍历我们所有数据库中的字典,进行磁盘文件的写入. 但其实这种方式是有缺 ...
- 探索Redis设计与实现11:使用快照和AOF将Redis数据持久化到硬盘中
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
随机推荐
- js技术之拖动table标签
一.js技术之拖动table标签 起因:前几天公司,突然安排一个任务 任务描述:要求尺码table列表要像Excel表中一样可以直接移动整行尺码到任意行位置 技术点:采用ui的sortable技术来h ...
- 定常系统(时不变系统)和时变系统&& 动态系统和静态系统
根据系统是否含有参数随时间变化的元件,自动控制系统可分为时变系统与定常系统两大类. 定常系统又称为时不变系统,其特点是:系统的自身性质(所研究物体的本质属性例如:质量.转动惯量等)不随时间而变化.具体 ...
- Chrome 53 Beta一些有意思的改动
原文链接: http://blog.chromium.org/2016...译者:Icarus邮箱:xdlrt0111@163.com 如果没有特殊说明的话,以下都是应用在Android,Chrome ...
- 文档声明(Doctype)和<!Doctype html>有何作用? 严格模式与混杂模式如何区分?它们有何意义?
文档声明的作用: 文档声明是为了告诉浏览器,当前HTML文档使用什么版本的HTML来写的,这样浏览器才能按照声明的版本来正确的解析. <!doctype html> 的作用就是让浏览器进入 ...
- Mybatis分页查询total中的坑
写在前面 今天用mybatis进行分页查询,大家应该都用过pageHelper这个插件,但是在计算总的数据数的时候,page.getTotal()总是返回0,要么就是返回pageSize(),今天给大 ...
- C#多线程下的调优
一.原子操作 先看一段问题代码 /// <summary> /// 获取自增 /// </summary> public static void GetIncrement() ...
- MySQL5.6复制技术
mysql复制功能介绍 我们可以通过为服务器配置主从即一个或多个备库的方式,以及主主结构来进行数据同步,将MySQL的数据分布到多个系统上去.复制过程中一台主库(master)服务器可以数据被同步到多 ...
- docker基础容器中bash: vi: command not found问题解决
安装即可 1.apt-get update 2.apt-get install vim
- Unity通过脚本创建Mesh(网格)
##1.创建一个带Mesh的物体 Unity中的网格作为组件不能脱离物体单独存在 新建脚本CreateMesh public class CreateMesh: MonoBehaviour { voi ...
- 学生管理系统(python实现)
# 定一个列表,用来存储所有的学生信息(每个学生是一个字典) info_list = [] def print_menu(): print("------------------" ...