Hits

Redis 持久化

Redis 持久化

Redis 虽然是一种内存型数据库,一旦服务器进程退出,数据库的数据就会丢失,为了解决这个问题,redis 提供了两种持久化的方案,将内存中的数据保存到硬盘中,避免数据的丢失。

Redis的持久化有两种机制,第一种是快照(rdb),第二种是AOF日志。快照是全量备份,AOF日志是连续的增量备份。

redis_rdb.png

RDB 持久化

RDB 持久化可以将redis在内存中的状态保存到硬盘中,可以手动执行也可以在 redis.conf 中配置 save <seconds> <changes> 定期执行。

rdb持久化产生的rdb文件是一个经过压缩的二进制文件,保存在硬盘指定目录 dir dirfilename 文件中,redis可以通过该文件还原数据库当时的状态。

RDB的创建与载入

RDB 文件可以通过下面两个命令产生:

  • save 阻塞redis的服务器进程,直到 rdb 文件被创建完毕
  • bgsave 派生(fork)一个子进程来创建新的 rdb 文件,记录接收到 bgsave 当时的数据库状态,父进程继续处理接收到的命令。子进程完成文件的创建后,会发送信号给父进程,此时,父进程处理命令的同时,通过轮询来接收子进程的信号。

rdb文件的载入一般情况下是自动的,redis服务器启动的时候,检测对应配置下的rdb文件是否存在,存在则会自动载入这个文件

如果服务器开启了 AOF持久化,那么服务器会优先使用AOF文件来还原数据库的状态。

rdb是通过保存键值对来记录数据库状态的,采用 copy on write的模式,每次都是全量的备份

自动保存间隔

bgsave 可以在不阻塞进程的情况下完成数据的备份。可以通过 redis.conf 中设置多个自动保存文件,只要有一个条件被满足,服务器就会执行 bgsave 命令。

# 服务器在900秒之内被修改了1次
save 900 1
# 服务器在300秒之内被修改了10次
save 300 10
# 服务器在60秒之内被修改了10000次
save 60 10000

AOF持久化

Append only file, AOF持久化是通过保存redis服务器所执行的写状态来记录数据库的,具体来说,rdb是备份数据库状态,AOF是备份数据库接收到的命令,所有被写入AOF的命令都是以redis的协议格式来保存的。

在APF持久化的文件中,数据库会记录所有变更数据库状态的命令,这些命令以append的形式保存到文件中。

// SELECT 0
*2
$6
SELECT
$1
0

// set xunleistring 123
*3
$3
set
$12
xunleistring
$3
123

服务器有一项 appendfsync 这个配置会影响服务器多久完成一次命令的记录:

#如果AOF开启,启动redis时会加载aof文件,这些文件能够提供更好的保证。 
appendonly yes

# no: 表示等操作系统进行数据缓存同步到磁盘。一般而言为了提高效率,操作系统会等待缓存区被填满,才会开始同步数据到磁盘。这个永不 是根据系统刷新输出缓冲区的时间来决定的,一般来说是30s(快)
# always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
# everysec:表示每秒同步一次(折中,默认值)
appendfsync everysec

redis在载入AOF文件的时候,会创建一个虚拟的client,把AOF中每个命令都执行一遍,最终还原回数据库的状态,它的载入是自动的,在rdb喝AOF都有的情况下,优先载入AOF备份文件。

AOF文件可能会随着服务器运行时间越来越大,可以利用AOF重写的功能,来控制AOF文件的大小。AOF重写功能会首先读取数据库中现有的键值对状态,然后根据类型使用一条命令来替代之前的键值对多条命令。

AOF重写 功能有大量写入操作,所以redis才用子进程来处理AOF重写。在AOF重写期间,redis还设置了一个重写缓冲区,这个缓冲区在子进程被创建开始之后使用,这个期间的所有命令会被存两份,一份在AOF缓存空间,一份在AOF重写缓冲区。AOF重写完成之后,子进程发送信号给主进程,通知主进程将AOF重写缓冲区的内容添加到AOF文件中。

# 设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入.官方文档建议如果你有特殊的情况可以配置为'yes'。但是配置为'no'是最为安全的选择。
no-appendfsync-on-rewrite no  

# 自动重写只增文件。  
# redis可以自动盲从的调用‘BGREWRITEAOF’来重写日志文件,如果日志文件增长了指定的百分比。  
# 当前AOF文件大小是上次日志重写得到AOF文件大小的二倍时,自动启动新的日志重写过程。
auto-aof-rewrite-percentage 100  

# 当前AOF文件启动新的日志重写过程的最小值,避免刚刚启动Reids时由于文件尺寸较小导致频繁的重写。
auto-aof-rewrite-min-size 64mb

对比两种持久化

  • AOF 更安全,可将数据及时同步到文件中,但需要较多的磁盘IO,AOF尺寸较大,文件内容恢复相对较慢,也更完整。AOF 的 fsync 是一个耗时的 IO 操作,它会降低 Redis 性能,同时也会增加系统 IO 负担
  • RDB 持久化,安全性较差,它是正常时期数据备份及 master-slave 数据同步的最佳手段,文件尺寸小,恢复速度较快。遍历整个内存,大块写磁盘会加重系统负载

Redis 4.0 混合持久化

重启 Redis 时,我们很少使用 rdb 来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 rdb 来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。

Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。将 rdb 文件的内容和增量的 AOF 日志文件存在一起。这里的 AOF 日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量 AOF 日志,通常这部分 AOF 日志很小。

redis_rdb2.png

于是在 Redis 重启的时候,可以先加载 rdb 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,重启效率因此大幅得到提升。

本文链接:参与评论 »

--EOF--

提醒:本文最后更新于 124 天前,文中所描述的信息可能已发生改变,请谨慎使用。

专题「数据库相关知识」的其它文章 »

Comments