redis持久化

2023-11-13  本文已影响0人  墨线宝

redis持久化

为了防止数据丢失,redis需要将数据从内存dump到磁盘,也就是redis持久化,redis持久化有两种方式RDB和AOF

注意:我使用的版本是6.0.10,不同版本可能略有差别

RDB

RDB是指Redis DataBase,在指定的时间间隔内,将内存中数据的快照写入到磁盘dump.rdb的文件中,恢复时通过载入rdb文件来还原数据库状态。

rdb文件是一个经过压缩的二进制文件

redis会单独创建(fork)一个子线程来进行持久化,会先将数据写入到临时文件,持久化结束之后,将临时文件替换上次持久化好的文件(保存在dump.rdb文件中),RDB方式比AOF更加高效,但是可能会丢失最后一次持久化的数据

在这里fork的线程是根据当前线程fork的,包含了当前线程的所有数据、变量等

Redis启动后会读取RDB快照文件,将数据从硬盘载入到内存。

RDB配置

关于RDB的配置是在redis.conf中的快照(SNAPSHOTTING)模块中

#
# Save the DB on disk:
#
#   save <seconds> <changes>
#
# 保存触发条件 多个条件之间是或的关系
save 900 1
save 300 10
save 60 10000

#后台保存出错,停止写入
stop-writes-on-bgsave-error yes

#使用LZF压缩算法压缩
rdbcompression yes

#存储快照后,redis使用CRC64算法进行数据检验,会增加性能损耗
rdbchecksum yes

#持久化文件的名称
# The filename where to dump the DB
dbfilename dump.rdb


rdb-del-sync-files no

# 持久化文件的目录
dir /usr/local/var/db/redis/

rdb文件会存储在执行redis-cli的当前目录下的dump.rdb文件中,默认触发条件是

save 900 1 #15分钟内修改了1次
save 300 10 #5分钟内修改了10次
save 60 10000 #1分钟内修改了10000次

当达到条件时会触发bgsave命令

这个我测试了一下 save 300 3表示的是自上次生成rdb快照后,300s内如果有3次更改,在300s的时间节点时会触发一次bgsave命令,而不是写入3次后就立马触发

也可以使用save或者bgsave命令来直接立即备份。

save命令是由主线程来做的,其他操作都会阻塞,直到rdb文件创建完毕,但是不会消耗额外的内存,如果数据比较多的话,会导致redis较长时间不响应,所以要尽量避免在生产环境中使用

bgsave是后台线程做的,其他操作可以正常执行,不会阻塞客户端命令,如果想要知道快照是否完成,可以通过lastsave命令获取最近一次成功执行快照的时间,返回结果是一个时间戳

可以使用命令来检测rdb文件是否存在问题

redis-check-rdb

重启之后会直接加载本目录下的dump.rdb文件

bgsave命令

使用fork创建子进程;父进程继续接收并处理客户端发来的命令,子进程将内存数据写入临时文件;子进程写入所有数据后会用临时文件替换旧RDB文件

在进行快照过程中不会修改RDB文件,只有快照结束后才会将旧的文件替换掉

bgsave命令在执行时,服务器处理save、bgsave、bgrewriteaof这三个命令会与平时不同

原理

使用fork()+copyonwrite

fork()

fork()是linux和unix的底层api,会fork出来一个子进程,共享那一刻的内存数据,且修改互相不可见

copyonwrite

写时复制策略,主进程fork子进程之后,内核会把主进程中所有的内存页权限设置为read-only,当主进程写数据时,read-only会发生中断,将触发中断的内存页复制一份主进程来操作修改,其余的还是在共享内存内

优缺点

优点
缺点

动态停止RDB持久化的方式

redis-cli config set save ""

在进行rdb持久化是将内存数据完整的写入磁盘,并不是使用增量的方式,如果数据量大的话可能会有大量的磁盘IO操作

查看rdb是否打开

redis-cli config get save

如果结果返回是空的话,则为关闭

AOF

AOF是指Append Only File,以日志的形式记录写操作,只许追加文件内容,不许修改,redis启动时会读取该文件来根据日志文件内容重新将写指令执行一次以完成数据恢复(日志文件名称为appendonly.aof)

默认该方式没有开启

AOF配置

关于AOF的配置是在redis.conf中的APPEND ONLY MODE模块中

############################## APPEND ONLY MODE ###############################


# 默认使用的是RDB,所以aof默认是关掉的,改为yes打开
# 如果AOF和RDB并存的话,优先加载AOF
appendonly no

# The name of the append only file (default: "appendonly.aof")
# 持久化文件名称
appendfilename "appendonly.aof"


# 同步写入日志文件 有三个策略 always、everysec、no
# always 每执行一个事件就把AOF缓冲区的内容强制性的写入硬盘的aof文件中,保证了数据持久化的完整性,效率最慢但是最安全
# everysec 每隔一秒进行一次文件同步把内存缓冲区里的aof缓存数据真正写入到aof文件里,兼顾了效率和完整性,只会损失1秒内的数据
# no 使用默认系统的缓存区写入磁盘的机制
# appendfsync always
appendfsync everysec
# appendfsync no

#重写时是否同步追加日志文件
no-appendfsync-on-rewrite no

#重写触发机制  比上次rewrite的aof文件大小扩增一倍且重写的最小大小为64m
# 超过上次重写时的AOF文件的百分之百
auto-aof-rewrite-percentage 100
# 允许重写的最小AOF文件大小
auto-aof-rewrite-min-size 64mb


aof-load-truncated yes


aof-use-rdb-preamble yes

如果aof文件中存在一些错误的指令(由于网络原因等问题导致命令没有写完),可以使用命令进行修复aof文件

redis-check-aof --fix

aof比rdb具有更好的持久化性,在使用aof持久化方式时,redis会将每一个收到的写命令通过write函数追加到文件中,在redis重启时会将aof文件中的命令重新执行一遍

AOF实现

AOF持久化方式打开之后,服务器执行写命令会写在缓冲区的末尾(server.c中的redisServer中有一个aof_buf字段来作为缓冲区),serverCron函数会定时将aof_buf缓冲区中的数据写入到文件

重写机制

由于AOF采用的是日志追加,可能会导致日志文件越来越大,为了避免此情况,增加了重写机制,当AOF文件超过所设定的阈值之后,redis会启动AOF文件的压缩,只保留可以恢复数据的最小指令集,可以使用命令bgrewriteaof来执行

重写之后减少了磁盘占有量,而且可以加速数据恢复

redis在进行重写时会占用大量的cpu和内存资源

no-appendfsync-on-rewrite no 这个配置是指是否在每次fsync的时候都进行重写,但是这样会造成大量的磁盘IO,还有可能会造成对写操作的阻塞,所以一般该值不推荐修改为yes

重写步骤:

AOF文件修复

服务器可能在程序正在对AOF文件进行写入时停机,造成AOF文件出错,可以使用redis-check-aof --fix readonlu.aof来进行修复

优缺点

优点
缺点

aof文件远大于rdb文件,恢复速度慢

由于aof方式比rdb方式的更新频率高,所以如果开启了aof,那么在启动时会优先使用aof文件来还原数据库状态

动态关闭AOF持久化的方式

redis-cli config set appendonly no

混合模式

在redis4.0之后出现了rdb和aof混合模式,而且默认开模式是开启的

aof-use-rdb-preamble yes

这个是基于aof开启的时候才会生效

开启后,AOF在重写时会直接读取RDB中的内容
运行过程:
通过bgrwriteaof完成,不同的是当开启混合持久化后,子进程会把内存中的数据以RDB的方式写入aof中,把重写缓冲区中的增量命令以AOF方式写入到文件,将含有RDB格式和AOF格式的AOF数据覆盖旧的AOF文件
新的AOF文件中,一部分数据来自RDB文件,一部分来自Redis运行过程时的增量数据

定时任务

在server.c中的serverCron函数是redis的一个定时任务,该函数处理了很多定时处理的命令。可以在配置文件中配置hz的值来配置每秒执行多少次,默认是10,即1秒执行10次,表示100ms一次

/* This is our timer interrupt, called server.hz times per second.
 * Here is where we do a number of things that need to be done asynchronously.
 * For instance:
 *
 * - Active expired keys collection (it is also performed in a lazy way on
 *   lookup).
 * - Software watchdog.
 * - Update some statistic.
 * - Incremental rehashing of the DBs hash tables.
 * - Triggering BGSAVE / AOF rewrite, and handling of terminated children.
 * - Clients timeout of different kinds.
 * - Replication reconnection.
 * - Many more...
 *
 * Everything directly called here will be called server.hz times per second,
 * so in order to throttle execution of things we want to do less frequently
 * a macro is used: run_with_period(milliseconds) { .... }
 */

https://zhhll.icu/2021/数据库/非关系型数据库/redis/基础/4.redis持久化/

本文由mdnice多平台发布

上一篇下一篇

猜你喜欢

热点阅读