redis持久化方式分为:RDB持久化和AOF持久化
一、RDB持久化
RBD持久化是把当前进程的数据已快照的形式保存到硬盘的过程。
触发分为手动触发和自动触发。
- 手动触发
命令:
- save:阻塞式,内存较大的实例在执行过程中会造成长时间的阻塞,影响主进程上的正常服务请求。
- bgsave:fork子进程,RDB持久化的过程在子进程中进行,完成后自动结束进程。阻塞发生在fork阶段,时间较短。
- 自动触发
满足RDB持久化条件后会自动执行持久化过程。
触发条件
1、使用save相关配置
配置格式:save <seconds> <changes> 表示<seconds>秒内数据集存在<changes>次修改时,自动触发bgsave
默认配置值
save 900 1
save 300 10
save 60 10000
其他相关配置
当bgsave快照操作出错时停止写数据到磁盘(fork子进程内存不足或rdb文件所在的文件夹没有写入权限)
stop-writes-on-bgsave-error yes
是否对RDB文件进行压缩
rdbcompression yes
配置文件名称,默认dump.rdb
dbfilename dump.rdb
是否对RDB文件进程校验
rdbchecksum yes
配置rdb文件存放的路劲,这个参数比较重要
dir ./
实现原理:serverCron服务定时器没100ms执行一次检查
if(now()-rdb_last_save_time<m(指定秒数) && rdb_changes_since_last_save>n(修改次数)){
bgsave();
}
2、从节点执行全量复制操作
3、debug reload命令
4、shutdown命令,如果没有开启aof自动执行bgsave
RDB持久化步骤:
- 执行bgsave命令,Redis父进程判断当前是否存在正在执行的子进程,如RDB/AOF子进程,如果存在bgsave命令直接返回
- 父进程执行fork操作创建子进程,fork操作过程中父进程会阻塞,通过info stats命令查看latest_fork_usec选项,可以获取最近一个fork操作的耗时,单位为微秒。
- 父进程fork完成后,bgsave命令返回“Background saving started”信息并不再阻塞父进程,可以继续响应其他命令。
- 子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。执行lastsave命令可以获取最后一次生成RDB的时间,对应info统计的rdb_last_save_time选项。
- 进程发送信号给父进程表示完成,父进程更新统计信息,具体见info Persistence下的rdb_*相关选项。
优点
- RDB是一个非常紧凑的(有压缩)的文件,它保存了某个时间点的数据,非常适用于数据的备份,可以很方便传送到另一个远端数据中心,非常适用于灾难恢复。
- RDB在保存文件时父进程唯一需要做的就是fork一个子进程,接下来工作全交由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis性能。
- 与AOF相比 ,在恢复大的数据集的时候,RDB方式会更快一点。
缺点
- redis意外宕机,可能会丢失部分数据。
- 当redis数据里比较大时,fork的过程是非常耗时的,fork子进程是会阻塞的,在这期间redis是不能响应客户端的请求的。
- RDB文件的致命缺点在于其数据快照的持久化方式决定了必然做不到实时持久化,而在数据越来越重要的今天,数据的大量丢失很多时候是无法接受的,因此AOF持久化成为主流。
- RDB文件需要满足特定格式,兼容性差。
二、AOF持久化
开启AOF功能配置(默认不开启)
appendonly yes
AOF文件名设置,默认文件名是appendonly.aof
appendfilename "appendonly.aof"
AOF工作流程
1、命令追加(append):所有的写入命令会追加到aof_buf(缓冲区)中。
2、文件写入(write)和文件同步(sync):AOF缓冲区根据对应的策略向硬盘做同步操作。
3、文件重写(rewrite):随着AOF文件越来越大,需要定期对AOF文件进行重写,达到压缩的目的。
4、当Redis服务器重启时,可以加载AOF文件进行数据恢复。
- 先将写命令追加到缓冲区,而不是直接写入文件,主要是为了避免每次有写命令都直接写入硬盘,导致硬盘IO成为redis负载的瓶颈。
- 命令追加的的格式是redis命令请求的的协议格式,它是一种纯文本格式,具有兼容性好,可读性强,容易处理,操作简单避免二次开销等优点。在AOF文件中,除了用于指定数据库的select命令(如select 0 为选中0号数据库)是由redis添加的,其他都是客户端发过来的请求。
RESP是redis序列化协议简写,结构数据如下:
当行字符串以 + 开头
多行字符串以 $ 开头,后跟字符串长度
整数以 :开头,后跟整数的字符串形式
错误信息以 - 开头。
数组以 * 开头,后面跟数组的长度。
- 文件写入:只是写入到了内存缓冲区,可能还没有写到文件所拥有的磁盘数据块上。
- 文件同步:将内存缓冲区中的内容刷新到磁盘上。
appendfsync配置值 | 效果 |
always | 每次有新命令,就将缓冲区数据写入并同步到AOF文件中 |
everysec(默认) | 每秒将缓冲区的数据写入并同步到AOF文件 |
no | 将缓冲区数据写入AOF文件中,但是同步操作交给操作系统来做 |
AOF重写机制
重写后的AOF文件缩小文件体积有如下原因:
- 进程内已经唾弃的数据不再写入文件
- 旧的AOF文件含有无效命令,如del key1、hdel key2、srem keys、set a 111、set a222等。重写使用 进程内数据直接生成,这样新的AOF文件只保留最终数据的写入命令。
- 多条写命令可以合并为一个,如:lpush list a、lpush list b、lpush list c可以转化为:lpush list a b c。为了防止单条命令过大造成客户端缓冲区溢出,对于list、set、hash、zset等类型操作,以64个元素为界拆分为多条。
-- AOF重写降低了文件占用空间,除此之外,另一个目的是:更小的AOF文件可以更快地被Redis加载。
重写触发机制:
1.手动触发,直接调用bgrewriteaof命令。
2.自动触发,根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机。
·auto-aof-rewrite-min-size:表示运行AOF重写时文件最小体积,默认为64MB。
·auto-aof-rewrite-percentage:代表当前AOF文件空间(aof_current_size)和上一次重写后AOF文件空间(aof_base_size)的比值。
自动触发时机:
aof_current_size>auto-aof-rewrite-minsize&&(aof_current_size- aof_base_size)/aof_base_size>=auto-aof-rewritepercentage
重写工作流程
1、执行AOF重写请求。如果当前进程正在执行AOF重写则不执行重写操作,如果进程在执行bgsave则等待执行完毕后再执行。
2、父进程执行fork创建子进程,开销等同于bgsave过程。
3.1、主进程fork操作完成后,继续响应其他命令。所有修改命令依然写入AOF缓冲区并根据appendfsync策略同步到硬盘,保证原有AOF机制正确性。
3.2、由于fork操作运用写时复制技术,子进程只能共享fork操作时的内存数据。由于父进程依然响应命令,redis使用“AOF重写缓冲区”保存这部分新数据,防止新AOF文件生成期间丢失这部分数据。
4、子进程根据内存快照,按照命令合并规则写入到新的AOF文件。每次批量写入硬盘数据量由配置
aof-rewrite-incremental-fsync控制,默认为32MB,防止单次刷盘数据过多造成硬盘阻塞。
5.1、新AOF文件写入完成后,子进程发送信号给父进程,父进程更新统计信息,具体见info persistence下的aof_*相关统计。
5.2、父进程把AOF重写缓冲区的数据写入到新的AOF文件。
5.3、使用新AOF文件替换老文件,完成AOF重写。
优点
- 支持秒级持久化
- 可用于不同版本的redis服务器,兼容性强。
- AOF文件可读行强,分析容易
缺点
- 文件大,恢复速度慢,对性能影响大。