Redis 的持久化

Posted Astral

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis 的持久化相关的知识,希望对你有一定的参考价值。

一、持久化简介

 

  Redis 的数据全部存储在内存中,如果突然出现宕机,数据将全部丢失。为保证数据的安全性,需要将内存中的数据保存到硬盘中,这种保存数据的机制就叫做持久化。持久化使得在 Redis 服务器重启时,可以通过存储在硬盘中的数据恢复到 Redis 服务器关闭前的状态。

  根据存储数据的形式,Redis 的持久化机制可以分为两种,即 RDB 和 AOF 。

  RDB 将当前数据以快照形式进行保存,存储格式简单,关注点在数据 。

  AOF 将数据的操作过程以日志形式存储,存储格式复杂,关注点在操作过程。

 

 二、RDB

   触发 Redis 创建 rdb 文件主要有三种方式。

1、通过 save 指令手动执行一次保存操作

(1)save 指令工作原理:客户端向 Redis 服务端发送 save 指令,服务端把当前数据库中的所有数据同步保存到 RDB 文件中。由于 Redis 单线程的特点,在执行 save 指令过程中(也就是即时创建RDB文件的过程中),Redis 服务端将被阻塞,无法处理客户端发送的其他命令请求,只有在 save 命令执行完毕后(也就时RDB文件创建完成之后), 服务器才会重新开始处理客户端发送的命令请求(2((

(2)配置文件内容

dbfilename "dump-6380.rdb"
rdbcompression yes
rdbchecksum yes

 

dbfilename rdb文件名  设置本地数据库文件名,默认值为 dump.rdb ,通常设置为dump-端口号.rdb 

rdbcompression yes  设置存储至本地数据库时是否压缩数据,默认为 yes,采用 LZF 压缩 。通常默认为开启状态,如果设置为no,可以节省 CPU 运行时间,但会使存储的文件变大

rdbchecksum yes   设置是否进行 rdb 文件格式校验,该校验过程在写文件和读文件过程均进行 。通常默认为开启状态,如果设置为no,可以节约读写性过程约10%时间消耗,但是存储一定的数据损坏风险 

(3)示例

a、Redis 客户端操作:添加数据并执行 save 指令

 

b、Redis 服务端操作:查看 rdb 文件内容,可见 Redis 服务器内容已成功被持久化 

c、杀死 Redis-server 进程,并重启 Redis 服务器

 

 d、Redis 客户端操作:获取 Redis 服务器关闭前的数据

 

 

注意:save 指令的执行会阻塞当前 Redis 服务器, 直到当前RDB过程完成为止, 有可能会造成长时间阻塞,线上环境不建议使用。 

 

 

 2、通过 bgsave 指令手动执行一次保存操作

  bgsave 指令是针对 save 指令阻塞问题所做的优化。 Redis内部所有涉及到 rdb 操作都采用 bgsave 指令的方式,save 指令可以放弃使用。 

 

 

(1)bgsave 指令工作原理:

a、Redis 客户端向 Redis 服务端发送 bgsave 指令;

b、Redis 服务端返回一条“Background saving started”命令给客户端,同时调用 fork 函数生成一个名叫 redis-rdb-bgsave 的子进程,由该子进程完成 rdb 文件的创建,而 Redis 主线程继续处理客户端请求;

c、当该子进程完成 rdb 文件的创建,会向 Redis 主线程发送一个信号,然后该子进程退出;

d、Redis 主进程接手 子进程创建的 rdb 文件,至此,bgsave 命令执行完毕。

(2)配置文件内容

stop-writes-on-bgsave-error yes 

 

stop-writes-on-bgsave-error yes  后台存储过程中如果出现错误现象,是否停止保存操作 。通常默认为开启状态 

3、通过配置文件自动生成 rdb 文件

 

(1)配置文件内容

save second changes  满足限定时间范围内 key 的变化数量达到指定数量即进行持久化

second:监控时间范围

changes:监控key的变化量

  例如,save 300 10  表示上一次创建 rdb 文件之后的300秒内,Redis 中的变量影响数量达到10次,则自动执行 bgsave 指令。

  每次执行 bgsave 指令创建 rdb 文件后,服务器为实现自动持久化而设置的时间计数器和次数计数器就会被清零,并重新开始计数,所以多个保存条件的效果不会叠加。此外,用户可以通过配置多个 save 选项来设置自动保存条件。

save 900 1
save 300 10
save 60 10000

 

注意:

a、save配置要根据实际业务情况进行设置,频度过高或过低都会出现性能问题,结果可能是灾难性的

b、save配置中对于second与changes设置通常具有互补对应关系,尽量不要设置成包含性关系

c、save配置启动后执行的是bgsave操作 

4、save 指令与 bgsave 指令的对比

命令 save bgsave
IO 类型 同步  异步
主进程是否阻塞
优点 不会额外消耗内存 不阻塞客户端命令
缺点 阻塞客户端命令 开启子进程,需要额外内存消耗

 

 

 

 

5、RDB 特殊启动形式

(1)全量复制

(2)服务运行过程中重启

debug reload

 

(3)关闭服务器时指定保存数据

  默认情况下执行 shutdown 命令时, 自动执行 bgsave (如果没有开启AOF持久化功能)

 

shutdown save

6、RDB 优缺点

(1)RDB 优点

 

a、RDB 是一个紧凑压缩的二进制文件, 存储效率较高

 

b、RDB 内部存储的是 redis 在某个时间点的数据快照, 非常适合用于数据备份,全量复制等场景

c、RDB 恢复数据的速度要比 AOF 快很多

应用:服务器中每X小时执行 bgsave 备份,并将RDB文件拷贝到远程机器中,用于灾难恢复

(2)RDB 缺点

a、RDB 方式无论是执行指令还是利用配置,无法做到实时持久化,具有较大的可能性丢失数据

b、bgsave 指令每次运行要执行 fork操作创建子进程, 要牺牲掉一些性能

c、Redis 的众多版本中未进行 RDB 文件格式的版本统一,有可能出现各版本服务之间数据格式无法兼容现象 

 

三、AOF

 1、RDB 的弊端

(1)每次读写都是全部数据,当数据量特别大时,效率会特别低

(2)基于 fork 函数创建子进程,产生额外开销

(3) 无法做到实时持久化,有较大数据丢失分线

  争对以上问题,不同的持久化策略:

(1)不读写全部数据,仅记录部分数据

(3)降低区分数据是否改变的难度,改记录数据为记录操作过程

(2)对所有操作均进行记录,排除数据丢失的风险

2、AOF 概念

  AOF 时 append only file 的缩写,以独立日志的方式记录每次命令,Redis 服务器重启时再重新执行 AOF 文件中的命令达到恢复数据的目的。与 RDB 相比可简单描述为:改记录数据为记录数据产生的过程。

  AOF 的主要作用是解决了数据持久化的实时性问题,目前已经是 Redis 持久化的主流方式。

3、AOF 的安全性问题

  虽然服务器执行一次修改数据库的命令,执行的命令就会被写入到 AOF 文件中,但这并不意味着 AOF 持久化方式不会丢失任何数据。

  在 linux 系统中,系统调用 write 函数,将一些数据保存到某文件时,为了提高效率,系统通常不会直接将内容写入硬盘里面,而是先把数据保存到硬盘的缓冲区之中。等到缓冲区被填满,或者用户执行

fsync 调用和  fdatasync 调用时,操作系统才会将储存在缓冲区里的内容真正的写入到硬盘里。

  对于 AOF 持久化来说,当一条命令真正的被写入到硬盘时,这条命令才不会因为停机而意外丢失。因此,AOF 持久化在遭遇停机时丢失命令的数量,取决于命令被写入硬盘的时间。越早将命令写入到硬

盘,发生意外停机时丢失的数据就越少,而越迟将命令写入硬盘,发生意外停机时丢失的数据就越多。

 

 

 

4、AOF 写数据的三种策略

(1)always:每次写操作都同步到 AOF 文件中,数据零误差,性能较低,不建议使用。

 

(2)everysec:每秒将缓冲区中的指令同步到 AOF 文件中,数据准确性较高,性能较高,是默认配置中,建议使用。(在系统突然宕机的情况下丢失1秒内的数据)

(3)no(系统控制):由操作系统控制每次同步到 AOF 文件的周期,整体过程不可控。

5、AOF 相关配置

appendonly yes|no   是否开启 AOF 持久化功能,默认为不开启状态

appendfsync always|everysec|no   AOF 写数据策略 

appendfilename filename     AOF 持久化文件名,默认文件名未 appendonly.aof,建议配置为 appendonly-端口号.aof

6、AOF 重写

(1)随着命令不断写入 AOF,文件会越来越大,为了解决这个问题, Redis引入了AOF重写机制压缩文件体积。AOF 重写简单来说就是将同一数据的若干条指命令简化为一条指令进行记录。

 

(2)AOF 重写的作用

a、降低磁盘占用量,提高磁盘利用率

b、降低持久化写时间,提高持久化效率

c、降低数据恢复用时,提高数据恢复效率

(3)AOF 重写规则

a、进程内已超时的数据不再写入文件 ;

b、忽略不对数据产生影响的指令,如 get 指令、多个 set 指令前面被覆盖的那些指令等;

c、对同一数据的多条写命令合并为一条命令,如 lpush list a、 lpush list b、 lpush list c 可以转化为: lpush list a b c 。(为防止数据量过大造成客户端缓冲区溢出,对 list、 set、 hash、 zset 等类型, 每个指

令最多写入64个元素

(4)AOF 重新的两种方式

a、手动重写

指令:bgrewriteaof

b、自动重写

配置文件内容:

  auto-aof-rewrite-min-size   触发 AOF 重写所需的最小体积:只要在 AOF 文件的大小超过设定的 size  时,Redis会进行 AOF 重写,这个选项用于避免对体积过小的 AOF 文件进行重写

  auto-aof-rewrite-percentage   指定触发重写所需的 AOF 文件体积增长率:当AOF文件的体积大于 auto-aof-rewrite-min-size 指定的体积,并且超过上一次重写之后的 AOF 文件体积的 percent% 时,就会

触发AOF 重写,如果服务器刚启动不久,还没有进行过 AOF 重写,那么使用服务器启动时载入的 AOF 文件的体积来作为基准值。将这个值设置为0表示关闭自动 AOF 重写功能。

 

涉及的两个统计项:

  aof_current_size   AOF当前尺寸(单位:字节)

  aof_base_size   AOF上次启动和重写的尺寸(单位:字节)

auto-aof-rewrite-min-size size
auto-aof-rewrite-percentage percentage

  只有当上面两个条件同时满足时才会触发 Redis 的 AOF 重写功能

 

(5)AOF 重写流程

 

  以基于 everysec 开启重写为例:

a、

 

 

四、RDB 与 AOF 的选择

1、RDB 与 AOF 的对比

 

启动优先级解释: 如果两者都选择了情况下,重启 redis 服务器加载数据会先选择 AOF

 

2、对数据非常敏感, 建议使用默认的 AOF 持久化方案

(1)AOF持久化策略使用 everysec,每秒钟 fsync 一次。该策略下 redis 仍可以保持很好的处理性能, 当出现问题时,最多丢失0-1秒内的数据。

(2)注意:由于AOF文件存储体积较大,且恢复速度较慢

3、数据呈现阶段有效性,建议使用 RDB 持久化方案

(1)数据可以良好地做到阶段内无丢失(该阶段是开发者或运维人员手工维护的),且恢复速度较快,阶段点数据恢复通常采用 RDB 方案 

(2)注意:利用 RDB 实现紧凑的数据持久化会使 Redis 效率降的很低

4、综合对比

a、RDB 与 AOF 的选择实际上是在做一种权衡,每种都有利有弊

b、如不能承受数分钟以内的数据丢失,对业务数据非常敏感, 选用 AOF

c、如能承受数分钟以内的数据丢失, 且追求大数据集的恢复速度, 选用 RDB

d、灾难恢复选用 RDB

e、双保险策略, 同时开启 RDB 和 AOF, 重启后, Redis 优先使用 AOF 来恢复数据,降低丢失数据的量

以上是关于Redis 的持久化的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud系列十一:SpringCloudStream(SpringCloudStream 简介创建消息生产者创建消息消费者自定义消息通道分组与持久化设置 RoutingKey)(代码片段

redis数据持久化——AOF重写

Redis的增删改查持久化你会了吗

Redis的增删改查命令总结与持久化方式

深入浅出 Redis 持久化机制

Redis学习缓存持久化哨兵模式