redis数据是保存在内存中,如果redis关闭数据就会丢失,为了避免这种情况,所以需要把redis数据进行持久化到磁盘。这样下次启动就可以使用持久化的数据文件将进行恢复了。
RDB
全量持久化
备份命令:
# 同步全量持久化
save
# 异步全量持久化
bgsave
save:同步执行,方法调用后会立即执行持久化方法,由于redis是单线程模型,主线程会阻塞,所以备份过程中是无法为其他客户端提供服务的。
bgsave:持久化过程会fork出一个子进程执行,只有fork时会阻塞主线程,真正的持久化任务是在子进程中进行执行的,所以并不会阻塞主进程执行其他任务,是异步的。
RDB方式的持久化是必然离不开了这两个命令的,不过触发方式可以分为手动触发和自动触发
手动触发:客户端手动执行命令
自动触发:设定相关的策略,在redis的配置文件redis.conf
save 900 1
save 300 10
save 60 10000
save 900 1表示:如果距离上一次创建RDB文件已经过去的900秒时间内,Redis中的数据发生了1次改动,则自动执行BGSAVE命令
save 300 10表示:如果距离上一次创建RDB文件已经过去的300秒时间内,Redis中的数据发生了10次改动,则自动执行BGSAVE命令
save 60 10000表示:如果距离上一次创建RDB文件已经过去了60秒时间内,Redis中的数据发生了10000次改动,则自动执行BGSAVE命令
当三个条件中的任意一个条件被满足时,Redis就会自动执行BGSAVE命令
RDB执行流程
- 执行save、basave、shutdowm命令时触发
- fork持久化子进程开始执行持久化任务。
- 遍历hashtable,利用copy on write,把整个内存dump下来。
rdb中有两个核心概念 fork 和copy-on-write ,执行数据备份的流程如下:
在执行basave的时候,redis首先会fork一个子进程得到一个新的子进程。子进程是共享主进程内存数据的,会将数据写入到磁盘上一个临时的rdb文件中,当子进程写完临时文件后,会将原来的.rdb文件替换掉,这个就是fork的概念。fork时主进程不进行任何磁盘IO操作,保证redis的高性能。
那cow全称就是 copy-on-write,当主进程执行读操作的时候是访问共享内存的,而主进程执行写操作的时候,则会copy一份数据,在新的内存区域中执行写操作。
AOF
增量持久化。
aof的安全性问题
aof会记录每一条数据修改的命令到aof文件中,但这并不意味着aof方式不会丢失数据。
在liunx系统中,系统调用write函数写入文件时,为了提高写入磁盘效率,系统通常不会将数据直接写入磁盘,而是先把数据保存到硬盘的缓冲区中,而当缓冲区中的内容未刷写到磁盘中时,这个时候系统宕机,则缓冲区中数据会丢失。
等缓冲区的数据被填满,或者用户执行fsync和fdatasync调用时,操作系统才会将存储在缓冲区里的内容真正写入到磁盘中。
对aof方式记录日志时,只有当命令记录被真正持久化到磁盘时,这条数据才不会丢失。
因此,aof持久化在宕机时丢失的数据量,取决于命令被写入到硬盘的时间,越早将命令写入到硬盘,写丢失数据的概率越小,越迟写入到磁盘则可能丢失的数据量就越大,而相应的数据存储效率就更慢。
aof执行策略:
为了控制redis 在意外停机时丢失的数据量,redis为aof持久化方式提高了appendfsync方式进行控制,配置的可选值如下:
appendfsync 可选值 | 解释 |
---|---|
always | 每条命令都会刷写到磁盘,但是写入时间是通过事件循环同步到磁盘中的,所以在redis意外宕机时,会丢失一个事件循环中执行的数据。 |
everysec | 每秒记录aof日志刷写到磁盘中,最多只丢失1s中记录的日志数据。 |
no | 服务器不主动调用fdatasync,由操作系统决定将系统缓冲区里面的数据刷写到磁盘中,这种模式下,redis宕机丢失的数据是无法确定的。最多丢失一个缓冲区中记录的日志。 |
从持久化数据的安全性上来讲,aways最安全,但是从数据存储效率上来讲,no方式是存储最快的。而redis的默认设置了折中的方式everysec,合情合理。 |
AOF的配置相关项
配置项 | 可选值 | 释义 |
---|---|---|
appendonly | yes | 开启AOF持久化方式 |
append filename | appendonly.aof | 生成aof日志文件名称 |
appendfsync | everysec | AOF日志刷盘策略:每秒钟刷新日志到磁盘 |
no-appendfsync-no-rewrite | yes no | AOF日志重写时:是否做append操作 yes:不做 no:做 不做append时可能丢失整个rewrite期间所有的AOF日志操作记录。 |
:::info
- 建议把appendfsync选项设定为everysec,进行持久化,这种情况下Redis宕机最多只会丢失一秒 钟的数据。
- 如果使用Redis做为缓存时,即使数据丢失也不会造成任何影响,只需要在下次加载时重新从数据 源加载就可以了。
- 不要占用redis 100%的内存,一般分配服务器60~70%的内存给redis使用,剩余的内存留给持久化的 fork 任务操作。
:::
AOF执行流程
每执行一次数据操作命令,就记录一次,如果appendfsync配置为aways,则至多丢失一次数据记录。
AOF文件重写
为了解决AOF文件体积不断增大的问题,用户可以使用bgrewriteaof命令,将aof文件进行重写压缩,也可以在配置文件中配置,自动触发。
auto-aof-rewrite-precentage 100
auto-aof-rewrite-min-size 64mb
通过append方式写入文件,即使记录过程总宕机,可以通过redis-check-aof工具解决数据一次性问题。
aof机制的rewrite模式,aof文件大小在触发重写机制时,可以重写内存中所有的数据,从而大幅缩小文件体积。
比rdb持久化启动效率低,因为日志文件通常比较大,而且所有命令需要执行,当数据极大时更加明显。
需要定期重写来降低文件体积。
优劣势对比
优势和劣势 | RDB | AOF | 混合方式 |
---|---|---|---|
备份方式 | 某一点的内存数据全量备份。 | 每条数据操作命令的增量备份 | |
优势 | 数据整块备份,整块恢复,备份文件小,数据恢复快。 rdb是一个紧凑的二进制文件,rdb重启时加载的效率比AOF更高,在数据量大时优势更明显。 | 只需记录数据操作,最高可每条记录都刷盘,安全性极高。 | |
劣势 | 备份数据时,需保存内存所有数据,备份耗费cpu,内存资源多,耗时久。因此无法高频率备份。 | 数据频繁操作时,记录日志文件大,存储占用空间大,恢复日志耗时长。 | |
自动触发策略 | save 900 1 save 300 10 save 60 10000 | 1. aways:修改同步 2. everysec:每秒同步 3. no:不主动调用fsync同步 | |
数据恢复流程 | redis server 重启时 1. 优先使用aof日志恢复 2. 不存在aof则使用rdb文件恢复 | 从redis启动之初,记录每一条写操作开始执行,直至执行完所有aof日志,数据恢复很慢 | |
文件保存方式 | dunp.rdb | 保存到appnedonly.aof文件中,具有可读性 | |
数据完整性 | 最后一次持久化之后新增修改的数据会丢失。 | aof利用apendfsync持久化机制,如果采用每秒记录日志的策略,如果一秒将结束时宕机,会丢失1秒钟的数据。 数据完整性要大于RDB方式。 | |
:::info
- 如果能接受分钟及的数据丢失,可以选择使用rdb方式。
- 如果数据都是缓存,可从数据库恢复时,也可以不使用任何持久化方式。
总结:如果想达到数据恢复快速和数据的安全性来说,应该同时使用两种持久化方式。
:::
数据恢复流程
- 如果只配置 AOF ,重启时加载 AOF 文件恢复数据。
- 如果只配置 RDB,启动将加载 dump文件恢复数据。
- 如果同时配置了 RDB 和 AOF ,启动只加载 AOF 文件恢复数据;
Redis 启动时加载数据的流程:
- AOF持久化开启且存在AOF文件时,优先加载AOF文件。
- AOF关闭或者AOF文件不存在时,加载RDB文件。
- 加载AOF/RDB文件成功后,Redis启动成功。
- AOF/RDB文件存在错误时,Redis启动失败并打印错误信息。
混合持久化方式
RDB和AOF都有各自的缺点:
- RDB是每隔一段时间持久化一次, 故障时就会丢失宕机时刻与上一次持久化之间的数据,无法保证数据完整性。
- AOF存储的是指令序列, 恢复重放时要花费很长时间并且文件更大。
因为bg save 会耗费很长时间,不够实时,在redis突然宕机时不能完全备份到所有数据,所以需要AOF的方式来补充全量备份数据之后产生的数据。
Redis 4.0 提供了更好的混合持久化选项:
创建出一个同时包含 RDB 数据和 AOF 数据的 AOF 文件, 其中 RDB 数据位于 AOF 文件的开头, 它们储存了服务器开始执行重写操作时的数据库状态,
至于那些在重写操作执行之后执行的 Redis 命令, 则会继续以 AOF 格式追加到 AOF 文件的末尾, 也即是 RDB 数据之后。
Redis4.0的持久化方式(混合持久化执行流程)
持久化总结
在实际使用中需要根据Redis作为主存还是缓存、数据完整性和缺失性的要求、CPU和内存情况等诸多因素来确定适合自己的持久化方案,一般来说稳妥的做法包括:
- RDB与AOF同时使用:最安全的做法,即使AOF损坏无法修复,还可以用RDB来恢复数据,当然在持久化时对性能也会有影响。
- 只使用RDB:在Redis当简单缓存,没有缓存也不会造成缓存雪崩的情况下可只使用RDB即可。
- 单独使用AOF:不推荐,因为AOF对于数据的恢复载入比RDB慢,所以使用AOF的时候,最好还是有RDB作为备份。
- 采用新版本Redis 4.0的持久化新方案。
本文由博客一文多发平台 OpenWrite 发布!