Redis数据持久化

什么是Redis持久化:

持久化:将内存中的数据库状态固化到磁盘的过程。

Redis默认配置包含16个database,dbid介于0和databases-1之间的数字,默认数据库是DB 0,可以使用select <dbid>在每个连接上选择一个不同的数据库,非空数据库以及它们包含的键值对统称为数据库状态。

Redis是内存型数据库,运行时数据均在内存中,如果服务器宕机,那么数据将全部丢失。如何来保证Redis数据的安全性、完整性以及高可用,Redis数据的持久化机制功不可没。

Redis的两个核心流程:文件事件和时间事件

文件事件常见的有:接收连接(accept)、读取(read)、写入(write)、关闭连接(close)等。

时间事件常见的是:serverCron,默认情况下,serverCron每100ms会被触发一次,执行的操作有:清理过期键、RDB的save point检查、AOF后台重写将 aof_buf 内容写到磁盘上等等。

持久化方式:

有3种持久化方式:RDB、AOF及混合持久化。

一、RDB
RDB全称Redis Database Backup file(Redis数据备份文件),也被称为Redis数据快照。Redis会将内存中的数据库状态(数据库键值对等信息)保存到磁盘上,生成的RDB快照文件是一个经过压缩的二进制文件通过该文件,可以还原生成RDB文件时的数据库状态。生成RDB文件的工作在源代码中由src/rdb.c文件中的rdbSave()方法完成。默认条件下,rdb文件会被放置于src/dump.rdb。

命令:SAVE、BGSAVE

Save:前台执行,生成RDB文件的时候,会阻塞整个Redis实例,在RDB生成过程中,无法处理其他请求。对于内存很大的实例,该过程非常耗时,通常不会直接使用该命令。

    伪代码:

void SAVE(){

    rdbSave();

}

Bgsave:后台执行,主进程fork出子进程来生成RDB快照文件,阻塞只会发生在fork出的子进程中,主进程可以正常处理其他请求。但是,当Bgsave命令执行期间,服务器会拒绝客户端发送的所有save、bgsave命令,防止产生竞争。

注意:后面会提到AOF持久化方式中的bgrewriteaof命令,当bgsave执行时,客户端发送的bgrewriteaof命令会被服务器暂时阻塞,等bgsave命令执行完毕后会被调起执行;但是,当bgrewriteaof执行时,客户端发送的bgsave命令会被服务器拒绝

子进程会copy父进程的page table。如果实例占用的内存很大,fork子进程会出现明显的卡顿现象。

伪代码:

void BGSAVE(){

// 创建子进程

pid = fork();

If(pid == 0){

    // 子进程负责创建RDB文件

    rdbSave();

    // 向父进程发送信号

    signal_parent();

} else if(pid > 0) {

    // 父进程继续处理其他请求,并通过轮询等待子进程的信号

    handle_request_and_wait_signal();

} else {

    // fork子进程出错

    handle_fork_error();

}

}

RDB文件载入

Redis服务器启动的时候,当检测到RDB文件存在的时候,会自动将其载入。在载入RDB文件期间,服务器会一直处于阻塞状态。载入RDB文件的工作在源代码中由src/rdb.c文件中的rdbLoad()方法完成。

注意:由于AOF文件的更新频率相对于RDB文件的更高,如果服务器开启了AOF持久化,那么当服务器启动的时候,会优先使用AOF文件还原数据库状态。只有当AOF持久化功能关闭的时候,服务器才会使用RDB文件来还原数据库状态。流程如下:

RDB文件不存在时候,服务启动的打印数据如下:

RDB文件存在时候,服务启动的打印数据如下:

 

 RDB触发配置:

# 最近900秒(15分钟)内 至少产生1次写入

save 900 1

# 最近300秒(5分钟)内 至少产生10次写入

save 300 10

# 最近60秒(1分钟)内 至少产生10000次写入

save 60 10000

可以在所有配置之后加上如下配置,取消RDB触发配置:

Save “”

 服务器在save配置条件被触发时候,输出日志如下:

RDB文件结构

REDIS

db_version

databases

EOF

check_sum

REDIS:5个字节的常量;

db_version:4个字节,记录RDB文件的版本号;

databases:包含0个或者任意多个数据库,以及各个数据库中的键值对数据;

EOF:1个字节的常量,标志着RDB文件正文结束;

check_sum:8字节唱的无符号整数,前面4部分数据计算出的一个校验和,服务器在载入RDB文件的时候,会将载入数据所计算出的校验和与check_sum所记录的校验和进行对比,防止RDB文件出错或者损坏。

分析RDB文件

命令:od -c dump.rdb

优点:

  1. RDB文件是经过压缩的二进制文件,占用空间小;
  2. RDB非常适用于灾难回复,由于结构紧凑,可以将其传输至其他数据中心;
  3. RDB采用fork子进程的方式处理所有的保存工作,父进程无需执行任何磁盘I/O操作;
  4. RDB在恢复大数据集时的速度非常快。

缺点:

  1. RDB保存的是某一时刻的数据快照,容易造成数据丢失。虽然可以通过save point配置持久化频率,但是,RDB是需要保存整个数据集的状态,频率太高容易造成Redis性能问题;
  2. RDB使用fork子进程进行持久化,如果数据集太大,fork子进程copy父进程的page table会非常耗时,也会造成Redis停止服务一段时间;
  3. Linux fork子进程采用copy-on-write方式。主进程在修改的同时,需要copy一份出来共子进程写入RDB文件,极端情况下,所有的page都被修改,此时内存占用是原来的2倍。

适用场景:

  1. 主从全量同步数据;
  2. 数据备份,Redis主从全量同步数据就是使用的RDB文件进行的;

数据丢失不敏感的场景,可以用来进行实例宕机后恢复数据。

二、AOF

AOF全称Append Only File(追加日志文件),AOF记录的是每一个命令的详细信息,包括完整的命令类型、参数等。只要产生写命令,就会实时写入到AOF文件中。

开启AOF持久化之后,服务启动的打印数据如下:

AOF实现步骤:

命令追加、文件写入、文件同步(刷盘)。

命令追加:当AOF持久化功能打开时,服务器执行完一个命令,会以协议格式将被执行的写命令追加到服务器状态的aof_buf缓冲区的末尾。

例如,客户端向服务器发送如下命令:

 会将以下协议内容追加到aof_buf缓冲区的末尾:

文件写入与同步:

文件写入:将append的命令,写入aof_buf缓冲区;

文件同步:将aof_buf缓冲区中的所有命令,持久化到磁盘。

文件写入与同步的效率和安全性,取决于AOF持久化刷盘方式配置appendfsync,下文详细讲解。

AOF触发配置:

# 开启AOF

appendonly yes

# AOF文件名

appendfilename "appendonly.aof"

# 文件刷盘方式

appendfsync everysec

AOF持久化默认是关闭的,可以通过配置appendonly yes开启。

AOF刷盘方式

1、appendfsync always

每次写入都刷盘,对性能影响最大,占用磁盘IO比较高,数据安全性最高。

2、appendfsync everysec

默认配置,1秒刷一次盘,对性能影响相对较小,节点宕机时最多丢失1秒的数据。

3、appendfsync no

按照操作系统的机制刷盘,对性能影响最小,数据安全性低,节点宕机丢失数据取决于操作系统刷盘机制。

AOF文件在载入与数据还原

  1. 创建不带网络连接的伪客户端;
  2. 从AOF文件分析并读取一条写命令;
  3. 使用伪客户端执行被读取出的写命令;
  4. 重复执行步骤2和步骤3,知道AOF文件所有命令都被处理完毕位置。

流程图如下:

优点:

  1. AOF数据文件更新比较及时,可以降低数据丢失的风险,在RDB和AOF同时开启的情况下,Redis会优先使用AOF文件进行数据恢复;
  2. AOF文件是一个纯追加的日志文件,即使由于某些原因包含了未写入完整的命令,也可以通过redis-check-aof工具修复;
  3. AOF文件有序的保存了对数据执行的所有写入操作,文件内容易懂。

缺点:

  1. AOF文件一般会比RDB文件大;
  2. 默认情况下,AOF的速度会比RDB慢;
  3. AOF文件刷盘会增加磁盘IO的负担,可能影响Redis的性能(开启每秒刷盘时);
  4. 随着时间增长,AOF文件会越来越大。

AOF重写

AOF文件太大的时候,Redis会自动在后台进行重写,重写后的AOF文件包含了恢复当前数据集所需的最小命令集合(这个重写过程会消耗大量的CPU资源)。

AOF 重写由两个参数共同控制,auto-aof-rewrite-percentage 和 auto-aof-rewrite-min-size,同时满足这两个条件,则触发 AOF 后台重写 BGREWRITEAOF。

// 当前AOF文件比上次重写后的AOF文件大小的增长比例超过100

auto-aof-rewrite-percentage 100

// 当前AOF文件的文件大小大于64MB

auto-aof-rewrite-min-size 64mb

auto-aof-rewrite-percentage 0,指定0的百分比,以禁用自动AOF重写功能。

AOF重写的实现

Redis的AOF文件重写并不是对现有AOF文件进行读取、分析和写入,它是通过读取服务器当前的数据库状态来实现的。

适用场景:

对于丢失数据较敏感的场景。

  • 混合持久化

混合持久化并不是一种全新的持久化方式,而是对已有方式的优化。其本质是通过 AOF 后台重写(bgrewriteaof 命令)完成的,不同的是当开启混合持久化时,fork 出的子进程先将当前全量数据以 RDB 方式写入新的 AOF 文件,然后再将 AOF 重写缓冲区(aof_rewrite_buf_blocks)的增量命令以 AOF 方式写入到文件,写入完成后通知主进程将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的 AOF 文件。

优点:

结合 RDB 和 AOF 的优点, 更快的重写和恢复。

缺点:

AOF 文件里面的 RDB 部分不再是 AOF 格式,可读性差。

总结:

RDB

AOF

持久化方式

生成某一时刻的数据快照文件

实时记录每一个写命令到文件

数据完整性

不完整,取决于备份周期

相对完整性高,取决于文件刷盘方式

文件大小

压缩二进制写入,文件较小

原始的操作命令,文件大

宕机恢复时间

恢复优先级

持久化代价

高,消耗大量CPU和内存

低,只占用磁盘IO资源

使用场景

数据备份、主从全量复制、对丢数据不敏感的业务场景快速数据恢复

对于丢失数据敏感的场景,例如涉及金钱交易相关的业务

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值