持久化

什么是持久化?简单来讲就是将数据放到断电后数据不会丢失的设备中,也就是我们通常理解的硬盘上。

首先我们来看一下数据库在进行写操作时到底做了哪些事,主要有下面五个过程:

  • 客户端向服务端发送写操作(数据在客户端的内存中);
  • 数据库服务端接收到写请求的数据(数据在服务端的内存中);
  • 服务端调用write这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中);
  • 操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中);
  • 磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上);

Redis持久化方式分为RDBAOF

RDB持久化

RDB(Redis DataBase)持久化是在指定的时间间隔内将内存中的数据集快照写入磁盘。同时也是默认的持久化方式。

img

工作流程

1

配置

触发方式
1
save m n # 表示m秒内数据集存在n次修改时,自动触发bgsave

例如,以下可以同时配置:

1
2
3
4
5
6
# 900秒内执行1次更新 
save 900 1
# 300秒内执行10次更新
save 300 10
# 60秒内执行10000次更新
save 60 10000
rdb文件存放目录
1
2
3
4
# 指定本地数据库文件名,一般采用默认的dump.rdb 
dbfilename dump.rdb
# 备份文件存放目录,一般也用默认配置
dir ./
开启数据压缩

配置存储至本地数据库时是否压缩数据,默认为yes。Redis采用LZF压缩方式,但占用了一点CPU的时间。若关闭该选项,但会导致数据库文件变的巨大。建议开启。

1
rdbcompression yes

AOF持久化

AOF(Append only file)持久化是以独立日志的方式记录每次命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。

AOF的主要作用是解决了数据持久化的实时性

AOF直接采用文本协议格式(兼容性好),开启AOF后,所有写入命令都包含追加操作,直接采用文本协议格式,避免了二次处理开销。

工作流程

AOF的工作流程操作:命令写入(append)、文件同步(sync)、文件重写(rewrite)、重启加载(load)。

12155333

流程如下:

  1. 所有的写入命令会追加到aof_buf(缓冲区)中;
  2. AOF缓冲区根据对应的策略向硬盘做同步操作;
  3. 随着AOF文件越来越大, 需要定期对AOF文件进行重写, 达到压缩的目的;
  4. 当Redis服务器重启时, 可以加载AOF文件进行数据恢复;

开启AOF

默认不开启,启用AOF持久化方式

1
2
3
4
5
6
7
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 key1hdel key2srem keysset a1111set a222等。重写使用进程内数据直接生成,这样新的AOF文件只保留最终的数据写入命令。
  • 多条写命令可以合并为一个,如:lpuh list alpush list blpush list c可以转化为:lpush list a b c。为了防止单条命令过大造成客户端缓冲区溢出,对于listsethashzset等类型操作,以64个元素为界拆分为多条。

AOF重写不仅降低了文件占用空间,而且更小的AOF文件可以更快地被Redis加载。

触发方式:

  • 手动触发:直接调用bgrewriteaof命令;
  • 自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机;
1
2
3
4
5
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

1515sd2

流程说明:

  • AOF持久化开启且存在AOF文件时, 优先加载AOF文件, 打印如下

日志:

1
* DB loaded from append only file: 5.841 seconds
  • AOF关闭或者AOF文件不存在时, 加载RDB文件, 打印如下日志:
1
* DB loaded from disk: 5.586 seconds
  • 加载AOF/RDB文件成功后, Redis启动成功。
  • AOF/RDB文件存在错误时, Redis启动失败并打印错误信息。

RDB-AOF混合持久化

由于RDB持久化和AOF持久化都有各自的优缺点,因此在很长一段时间里,如何选择合适的持久化方式成了很多Redis用户面临的一个难题。为了解决这个问题,Redis从4.0版本开始引入RDB-AOF混合持久化模式,这种模式是基于AOF持久化模式构建而来的。