持久化:解决单机备份问题。Redis是内存数据库,数据都是存储在内存中,为了避免进程退出导致数据的永久丢失,所以定期将Redis中的数据或写命令从内存保存到硬盘,重启时利用持久化文件实现数据恢复。
Redis持久化方式有两种:
- RDB持久化:保存当前内存数据到硬盘;
- AOF持久化:保存执行的每条写命令到硬盘(类似于MySQL的binlog);AOF持久化的实时性高,当进程意外退出时丢失的数据更少,因此AOF是目前主流的持久化方式。
一、RDB持久化(Redis DataBase)
RDB持久化是将当前进程中的全量数据生成快照保存到硬盘,也称作快照持久化,保存的文件后缀是rdb;当Redis重新启动时,可以读取快照文件恢复数据。
1、触发条件
RDB持久化的触发分为两种:手动触发、自动触发。
手动触发:
1.save命令:阻塞Redis服务器主进程,服务器不能处理任何命令请求,直到RDB文件创建完。
2.bgsave命令:会创建一个子进程,由子进程负责创建RDB文件,父进程(即Redis主进程)继续处理请求。只有创建子进程时会阻塞服务器,后面过程不阻塞;自动触发RDB持久化时,Redis也是使用bgsave。
命令 |
save |
bgsave |
IO类型 |
同步 |
异步 |
阻塞 |
整个流程阻塞 |
只有在fork子进程时阻塞 |
复杂度 |
O(n) |
O(n) |
优点 |
不会消耗额外内存 |
不阻塞客户端命令 |
缺点 |
阻塞客户端命令 |
需要fork,消耗内存 |
自动触发:
1.在redis.conf配置文件中配置触发条件save m n(当m秒内发生n次变化时则会触发bgsave)。可配置多个,当满足任意一个条件时都会触发bgsave。
https://github.com/redis/redis/blob/3.2/redis.conf#L202
# save <seconds> <changes>
// 可配置多个
// 当时间到900秒时,如果redis数据发生了至少1次变化,则执行bgsave
save 900 1
save 300 10
save 60 10000
2.主从复制场景下,从节点需要全量复制,则主节点会执行bgsave命令,并将rdb文件发送给从节点;
3.debug reload提供debug级别的重启,不清空内存的一种重启,这种方式也会触发RDB文件的生成;
4.执行shutdown命令时,自动执行rdb持久化,如下图日志:
save m n 配置的实现原理:
通过serverCron函数、dirty计数器、和lastsave时间戳来实现的。Redis会每隔100ms执行serverCron函数,会检查所有save m n的配置,只要满足一个save m n则执行bgsave。
- 当前时间-lastsave > m
- dirty >= n
serverCron函数:Redis服务器的周期性操作函数,默认每隔100ms执行一次,来对各种状态进行维护,如检查save m n配置是否满足条件,满足就执行bgsave;判断当前user_memory和user_memory_peak大小来设置内存使用峰值等等;函数源码地址:redis/server.c at 3.2 · redis/redis · GitHub
dirty计数器:Redis服务器维持的一个状态,记录执行bgsave/save命令后,进行了多少次修改(包括增删改);而当save/bgsave执行完成后,会将dirty重新置为0。
// dirty记录的是服务器进行了多少次修改,而不是客户端执行了多少条修改数据的命令。
set mykey helloworld
// 则dirty+1
sadd myset v1 v2 v3
// 则dirty+3
lastsave时间戳:也是Redis服务器维持的一个状态,记录上一次成功执行save/bgsave的时间。
2、执行流程
Redis源码剖析(十)--RDB持久化 - 不学习就没有梦想 - 博客园
- Redis父进程