Redis源码解析——持久化机制

Redis的持久化包括save和bgsave,后者通过子进程避免阻塞。bgsave期间,客户端的save和bgsave请求会被拒绝,bgrewriteaof则在bgsave完成后执行。脏计数器记录数据库修改次数,lastsave记录上次保存时间。AOF持久化有三种同步策略,影响存储和还原速度。AOF重写用于优化文件大小,确保数据安全性,同时父进程仍能处理请求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Redis有两种持久化机制:rdb持久化以及aof持久化。默认使用rdb持久化方式。
一、rdb持久化
即在指定的时间间隔内将内存中的数据集进行快照并保存在磁盘当中。用户可以复制该磁盘文件到其他redis服务器中以创建相同的服务器副本。
rdb持久化会生成rdb文件。该文件为 压缩过的二进制文件。rdb文件默认为当前工作目录下的dump.rdb。 可在配置文件中的dbfilename和dir来更改默认的文件名和保存路径。
触发rdb持久化:
1)可在client中输入save或者bgsave命令触发rdb持久化。其中:
  • save命令会阻塞redis进程。
  • bgsave命令会fork一个子进程,然后该子进程负责创建和写入rdb文件。
2)配置文件中配置save <second> <changes>指在second秒内发生changes次变化,则执行bgsave。
3)执行flushall命令清空服务器数据时触发
4)执行shutdown命令关闭redis时会触发执行save命令。
在执行bgsave命令期间:
  • 客户端的save、bgsave命令会被拒绝,防止两次rdbsave调用产生竞争。
  • bgrewriteaof命令会被延迟到bgsave命令执行完毕之后执行。
  • 如果bgrewriteaof命令在执行,bgsave命令会被拒绝
dirty计数器和last save属性
  • dirty计数器记录距离上一次成功执行SAVE命令或者BGSAVE命令之后,服务器对数据库状态(服务器中的所有数据库)进行了多少次修改(包括写入、删除、更新等操作)
  • lastsave属性是一个UNIX时间戳,记录了服务器上一次成功执行SAVE命令或者BGSAVE命令的时间。
RDB的间隔性保存就通过这两个属性来判断是否满足条件。
二、AOF持久化
AOF持久化默认不开启
AOF持久化记录Redis的写操作,并将这些操作写入到AOF文件中持久化。
AOF配置:
# 开启aof持久化
appendonly yes
# aof文件名
append filename “appendonly.aof”
# aof文件保存路径
dir ./
#aof 持久化策略
# 每次操作都执行持久化 appendfsync always 会有性能问题
# 每秒执行一次aof持久化。比较折中的方案。
appendfsync everysec
# 何时同步由操作系统决定 appendfsync no
#在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。#设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no
no-appendfsync-on-rewrite no 
#当前AOF文件大小是上次日志重写得到AOF文件大小的二倍时,自动启动新的日志重写过程。
auto-aof-rewrite-percentage 100 
#当前AOF文件启动新的日志重写过程的最小值,避免刚刚启动Reids时由于文件尺寸较小导致频繁的重写。
auto-aof-rewrite-min-size 64mb
AOF持久化分为3个步骤: 追加、写文件、同步文件
1)追加
将redis的 写操作以协议的格式追加到aof缓冲区中。协议为文本协议,CRLF。具体格式为:
*<count>/r/n<element>…<elementN>
element格式为:$<len>/r/n<operation>/r/n
举例:
1. *3\r\n$5\r\nlpush\r\n$4\r\nname\r\n$7\r\ndiaocow  
2. *3\r\n$5\r\nlpush\r\n$4\r\nname\r\n$4\r\njack  
3. *3\r\n$5\r\nlpush\r\n$4\r\nname\r\n$4\r\njobs
2)写文件
指将 aof缓冲区中的数据写入aof文件中。3种策略
  • always: 将aof缓冲区中的全部内容写入aof文件,每执行一次写操作就同步一次到磁盘
  • everysec: 将aof缓冲区中的数据写入aof文件,每秒执行一次同步 同步到磁盘
  • no: 将aof缓冲区中的内容写入aof文件。何时同步到磁盘由操作系统决定。
3)同步文件
关于文件写入和同步: 为了提高文件写入效率,在现代操作系统中,当用户调用 write 函数,将一些数据写入文件时,操作系统通常会将数据暂存到一个 内存缓冲区 里,当缓冲区的空间 被填满或超过了指定时限 后,才真正将缓冲区的数据写入到磁盘里。
这样的操作虽然提高了效率,但也为数据写入带来了 安全问题:如果计算机停机,内存缓冲区中的数据会丢失。为此,系统提供了fsync、fdatasync同步函数,可以强制操作系统立刻将缓冲区中的数据写入到硬盘里,从而确保写入数据的安全性。
AOF载入与数据还原
AOF重写
AOF文件会随着时间的推移,操作的增多而变得越来越大,存在以下问题:
  • 会对Redis服务器的存储造成压力;
  • 通过AOF还原数据库的时间也会增加。
解决方法:Redis通过AOF重写解决该问题。
AOF重写机制
Redis创建一个新的AOF文件:
  1. 该AOF文件与旧的AOF文件 保存的Redis状态一致
  2. 去掉所有冗余的操纵 ,最终使用新生成的AOF文件 替换旧的AOF文件
AOF重写机制的原理
1)从数据库中读取键现在的值,用 一条命令记录键值对,代替之前记录该键值对的多个命令,写入新生成的AOF文件;
2)实际为了避免执行命令时造成客户端输入缓冲区溢出,重写程序在处理list hash set zset时,会检查键所包含的元素的个数, 如果元素的数量超过了redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD常量的值,那么重写程序会使用多条命令来记录键的值,而不是单使用一条命令。该常量 默认值是64,即每条命令设置的元素的个数是最多64个,使用多条命令重写实现集合键中元素数量超过64个的键
3)使用新的AOF文件替换旧的AOF文件;
AOF后台重写
AOF重写过程中会存在大量写入操作,较为耗时。由于redis是单线程运行的,所以如果在Redis主线程中执行AOF重写,redis将阻塞并且无法处理其他客户端请求。通过aof后台重写解决该问题。后台重写流程为:
1)当执行aof后台重写时,Redis除了aof缓冲区外,还会 开辟一块aof重写缓冲区
2)执行aof重写时,redis fork一个子进程 来执行aof重写。子进程读取Redis中所有键的值并在新的aof文件中插入一条写操作。
3)在 执行aof重写时,redis也要处理客户端的写入请求 。此时,redis不仅会将写入操作写到aof缓冲区并同步到磁盘,同时也会将该写入操作写入aof重写缓冲区中。
4)当子进程完成aof重写后,会发送信号通知父进程完成aof重写。父进程会 阻塞客户端请求 ,并将aof重写缓冲区中的数据追加到新的aof文件。并将新的aof文件重命名。此时则完成了后台aof重写。
aof重写的触发方式
1)手动触发。通过在客户端中输入bgrewriteaof命令触发。
Aof后台重写为什么要使用子进程?
  1. 父进程依然可以处理客户端请求
  2. 可以在避免使用锁的情况下,保证数据的安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值