什么是持久化?简单来讲就是将数据放到断电后数据不会丢失的设备中,也就是我们通常理解的硬盘上。
首先我们来看一下数据库在进行写操作时到底做了哪些事,主要有下面五个过程:
- 客户端向服务端发送写操作(数据在客户端的内存中);
- 数据库服务端接收到写请求的数据(数据在服务端的内存中);
- 服务端调用write这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中);
- 操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中);
- 磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上);
Redis持久化方式分为RDB和AOF。
RDB持久化
RDB(Redis DataBase)持久化是在指定的时间间隔内将内存中的数据集快照写入磁盘。同时也是默认的持久化方式。
工作流程
配置
触发方式
save m n # 表示m秒内数据集存在n次修改时,自动触发bgsave
例如,以下可以同时配置:
# 900秒内执行1次更新
save 900 1
# 300秒内执行10次更新
save 300 10
# 60秒内执行10000次更新
save 60 10000
rdb文件存放目录
# 指定本地数据库文件名,一般采用默认的dump.rdb
dbfilename dump.rdb
# 备份文件存放目录,一般也用默认配置
dir ./
开启数据压缩
配置存储至本地数据库时是否压缩数据,默认为yes
。Redis采用LZF压缩方式,但占用了一点CPU的时间。若关闭该选项,但会导致数据库文件变的巨大。建议开启。
rdbcompression yes
AOF持久化
AOF(Append only file)持久化是以独立日志的方式记录每次命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。
AOF的主要作用是解决了数据持久化的实时性。
AOF直接采用文本协议格式(兼容性好),开启AOF后,所有写入命令都包含追加操作,直接采用文本协议格式,避免了二次处理开销。
工作流程
AOF的工作流程操作:命令写入(append)、文件同步(sync)、文件重写(rewrite)、重启加载(load)。
流程如下:
- 所有的写入命令会追加到aof_buf(缓冲区)中;
- AOF缓冲区根据对应的策略向硬盘做同步操作;
- 随着AOF文件越来越大, 需要定期对AOF文件进行重写, 达到压缩的目的;
- 当Redis服务器重启时, 可以加载AOF文件进行数据恢复;
开启AOF
默认不开启,启用AOF持久化方式
appendonly yes
# AOF文件名称
appendfilename "appendonly.aof"
# 备份文件存放路径,同RDB
dir ./
# 同步频率
appendfsync everysec
appendfsync同步频率配置参考:
- always:命令写入
aof_buf
后调用fsync
操作同步到AOF文件,fsync
完成后线程返回,每个 Redis 命令都要同步写入硬盘,这样会严重降低 Redis 的性能。 - everysec:命令写入
aof_buf
后调用系统write
操作,write
完成后线程返回。fsync
同步文件操作由专门线程每秒调用一次。每秒执行一次同步,显式地将多个写命令同步到硬盘。 - no:命令写入
aof_buf
后调用系统write
操作,不对AOF文件做fsync
同步,同步硬盘操作由操作系统负责,通常周期周长30秒。操作系统同步AOF文件的周期不可控,会加大每次同步硬盘的数据量,数据安全性无法保证。
重写机制
随着命令不断写入AOF,文件会越来越大,为了解决这个问题,Redis引入AOF重写机制压缩文件体积。AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程。
重写后的AOF文件为什么可以变小?有如下原因:
- 进程内已经超时的数据不再写入文件。
- 旧的AOF文件含有无效命令,如
del key1
、hdel key2
、srem keys
、set a1111
、set a222
等。重写使用进程内数据直接生成,这样新的AOF文件只保留最终的数据写入命令。 - 多条写命令可以合并为一个,如:
lpuh list a
、lpush list b
、lpush list c
可以转化为:lpush list a b c
。为了防止单条命令过大造成客户端缓冲区溢出,对于list
、set
、hash
、zset
等类型操作,以64个元素为界拆分为多条。
AOF重写不仅降低了文件占用空间,而且更小的AOF文件可以更快地被Redis加载。
触发方式:
- 手动触发:直接调用
bgrewriteaof
命令; - 自动触发:根据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
流程说明:
- AOF持久化开启且存在AOF文件时, 优先加载AOF文件, 打印如下
日志:
* DB loaded from append only file: 5.841 seconds
- AOF关闭或者AOF文件不存在时, 加载RDB文件, 打印如下日志:
* DB loaded from disk: 5.586 seconds
- 加载AOF/RDB文件成功后, Redis启动成功。
- AOF/RDB文件存在错误时, Redis启动失败并打印错误信息。
RDB-AOF混合持久化
由于RDB持久化和AOF持久化都有各自的优缺点,因此在很长一段时间里,如何选择合适的持久化方式成了很多Redis用户面临的一个难题。为了解决这个问题,Redis从4.0版本开始引入RDB-AOF混合持久化模式,这种模式是基于AOF持久化模式构建而来的。