redis专题笔记 - 持久化

本文介绍Redis的两种持久化方式:RDB快照和AOF日志。RDB通过子进程利用COW机制进行全量备份,减少内存开销。AOF记录所有写指令,支持不同fsync策略确保数据安全性。

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

RDB快照持久化

  1. Redis使用独立子进程进行快照持久化工作
    • Redis是单线程程序,该线程负责监听多个客户端套接字的读写操作和内存数据的维护。快照持久化需要将内存数据全量写入磁盘,涉及大量的IO操作,如果仍然使用主线程进行,则必定阻塞正常请求
  2. RDB快照是一次全量备份,记录持久化开始那个时刻的内存数据,是内存数据的二进制序列化形式
  3. Redis的快照持久化是基于linux系统的copy-on-write功能实现的

COW

传统的fork()

传统的创建子进程操作,创建出的子进程和父进程共享代码段,复制数据段、堆、栈,这样会造成大量内存复制;传统fork()的内存复制情况如下图:
在这里插入图片描述

支持写时复制的fork()

支持写时复制的创建子进程操作,在子进程被创建的瞬间,内核只为子进程创建虚拟空间,不分配物理内存;父进程和子进程共享物理内存,此时内存分布如图:

在这里插入图片描述

当父进程中有更新数据的行为时,才将更新涉及到的数据页拷贝出来独立物理空间给子进程

redis的写时复制

Redis是基于内存的缓存,主线程中有大量内存数据,如果创建子进程时使用传统的fork(),物理内存占用必定加倍,服务器为了支持快照持久化,日常内存使用率只能在50%以下,这显然是不合理的。

所以需要使用操作系统的cow机制来进行父子进程数据页的共享和分离

  1. 在子进程被创建瞬间,服务器的内存增长几乎忽略不计(仅子进程必要的数据结构),父子进程共享物理内存
  2. 父进程继续提供服务,子进程则进行内存快照写入磁盘工作
  3. 当父进程需要修改数据时,则将修改数据涉及的数据页(每个数据页4KB)复制一份进行修改,此时子进程仍然看到快照时的数据

快照持久化配置

RDB持久化配置位于redis.conf文件中,SNAPSHOTTING对应的内容:

# 快照触发条件,命中某一个条件就会执行一次快照持久化BGSAVE
# 服务器在900s内,对数据库进行了至少1次修改
# 服务器在300s内,对数据库进行了至少10次修改
# 服务器在60s内,对数据库进行了至少10000次修改
save 900 1 
save 300 10
save 60 10000

# 快照文件存放路径及文件名
# 文件名默认
# 文件路径默认当前目录下
dbfilename dump.rdb  
dir ./  

# RDB快照持久化被激活并且持久化失败,Redis则停止接受更新操作
stop-writes-on-bgsave-error yes  

# 生成.rdb文件时是否压缩
rdbcompression yes  

# RDB快照文件加载时是否进行CRC64校验
rdbchecksum yes  

AOF持久化

  1. AOF日志记录对内存进行修改的指令记录
  2. Redis对修改指令先进行逻辑处理,再写入AOF日志

fsync

Redis对AOF文件的写操作,是先写入AOF日志文件对应文件描述符的内存缓存中,然后再异步将脏数据刷回磁盘,这种机制导致如果服务器宕机,可能存在内存缓存中的日志记录会丢失;

linux提供了fsync()函数,可以将指定文件描述符对应的内存缓存强制写入磁盘;但fysnc()是一个耗时久的磁盘IO操作,因此,redis提供了三种执行fsync()的方式:

  1. redis每隔1s执行一次fsync();redis的默认策略
    • 这就意味着AOF日志最多可能丢失1s的日志数据
  2. redis完全不执行fsync(),AOF日志落磁盘的操作完全交给操作系统管理
    • 不可靠
  3. redis每次执行修改命令,都执行fsync()
    • 耗时较久,相当于每次修改指令都要强制写入磁盘

AOF重写

AOF文件时增量写入的,所以如果长时间不处理AOF文件,其容量巨大,出现问题重新加载会非常耗时,因此

Redis提供了bgrewriteaof指令执行AOF重写,对AOF文件进行瘦身,其方式大致如下:

  1. 开辟子进程对内存进行遍历
  2. 将遍历的内存数据,转换成对应的Redis操作指令
  3. 将扫描期间增量的日志追加到新的AOF文件后面
  4. 新的AOF文件替换旧的AOF文件

AOF持久化配置

RDB持久化配置位于redis.conf文件中,APPEND ONLY MODE对应的内容:

# 是否开启AOF日志,默认不开启,线上一般需要打开 => yes
appendonly no

# AOF日志文件名
appendfilename "appendonly.aof"

# AOF日志执行fsync策略,默认每秒执行一次fsync,还可以
# appendfsync always => 每条修改指定执行一次fsync
appendfsync everysec
# appendfsync no      => 不执行fsync

# 当后台执行BGSAVE或者BGREWRITEAOF时,主线程不执行fsync
# 主要考虑到当子进程进行“RDB快照”或者“AOF重写”时,会产生大量I/O,
# 可能影响主线程的fsync()操作,导致阻塞时间增加,redis性能下降;
# 所以,可以设置此时主线程不执行fsync(),
# 但这样也意味着可能会丢失更久的AOF日志数据(最长达30s,根据linux的默认配置)
no-appendfsync-on-rewrite no

# AOF文件重写时机配置
# 当前AOF日志大小 大于auto-aof-rewrite-min-size,且比上次rewrite后(或者启动后)的日志大小增长auto-aof-rewrite-percentage,则触发AOF重写;
# auto-aof-rewrite-percentage 设为0时,关闭AOF重写功能
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 在redis启动并加载AOF日志时,发现从AOF日志不全(truncated),这个时候怎么办呢?
# yes => redis可以正常重启,并会告知用户AOF文件不全
# no => redis重启失败,直接抛错
aof-load-truncated yes

# AOF重写时,是否使用rdb作为AOF日志的基
# yes => 重写时会指定rdb文件,并在此文件上增量生成aof,如果发生重启需要重新加载,也是使用rdb + 增量aof
# 感觉像是混合持久化的开关
aof-use-rdb-preamble yes

混合持久化

RDB快照 + 自RDB快照后的增量AOF日志

可以实现快速全量的数据恢复

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值