持久化
持久化:将数据从内存同步到硬盘,重启后能够再将数据从硬盘中恢复到内存的过程。
使用场景
redis的数据存储在内存中,有的时候,我们会希望在重启后能够保证数据不会丢失。
例如下列场景:
- 将redis作为数据库
- 将redis作为缓存服务器
持久化方式
RDB方式
通过快照完成
快照:在一定条件下,自动将内存中的数据生成一份副本存储在硬盘上。
触发条件
- 根据条件自动进行快照
# 条件在配置文件中通过下述条件定义
save M N
# 时间窗口M和改动的键的个数N,每当时间M内改动的键的个数大于等于N时,会触发自动快照
# 例如:设置在900秒内改动的键的个数大于等于1个时自动快照
save 900 1
- 手动执行SAVE和BGSAVE生成快照
# 阻塞式的生成快照,期间redis无法响应客户端
SAVE
# 非阻塞的生成快照,期间redis可以正常响应客户端
# 自动快照也是通过BGSAVE来生成快照
BGSAVE
# 获取最近一次成功执行快照的时间(UNIX时间戳)
LASTSAVE
- FLUSHALL命令
# 清除数据库中所有数据
FLUSHALL
# redis在自动快照条件不为空的情况下,执行FLUSHALL也会自动触发快照
- 主从模式下,执行复制会生成快照
快照原理
快照过程:
- redis使用fork函数复制一份当前进程(父进程)的副本(子进程)
- 父进程继续接收客户端的命令,子进程开始将内存中的数据写入硬盘的临时文件
- 当子进程写完所有数据,会用临时文件替换旧的RDB文件
# 类UNIX系统在执行fork命令时,会使用写时复制策略(copy-on-write)
fork函数发生的瞬间,父子进程共享同一片内存数据,当父进程要更改其中某片数据时,操作系统会将该片数据复制一份以保证子进程的数据不受影响。
缺点
一旦redis异常退出,就会丢失最后一次快照生成之后更改的所有数据
注意点
- 内存用量评估时,需要考虑fork时,写入操作带来的内存增多问题
- 需要确保Linux系统允许应用程序申请超过可用内存的空间
- 快照过程中不会修改RDB文件,只有快照完成后才会替换旧的RDB文件
# Linux系统允许应用程序申请超过可用内存的空间
# 1. 在/etc/sysctl.conf 文件中加入
vm.overcommit_memory=1
# 2. 重启系统或执行命令
reboot / sysctl vm.overcommit_memory=1
其他
- 快照恢复速度:通常将记录1000万个字符串类型键、大小为1GB的快照文件载入内存中需要花费20-30秒
- 名称/配置解释
# redis默认的快照文件文件名
dump.rdb
# redis.conf
# 快照存储路径
dir
# 快照文件文件名
dbfilename
AOF方式
在redis执行写操作时,将写命令存储到文本文件(AOF文件)中
开启AOF
# redis默认不开启AOF
appendonly yes
AOF实现
开启AOF之后,redis每次执行更改操作时,都会将操作命令记录在AOF文件中。
AOF文件以纯文本的形式记录redis执行的写命令(记录的是原始通信协议内容)
AOF重写
AOF文件记录的命令会出现很多冗余的命令,例如:
SET wlj 1
SET wlj 2
SET wlj 3
上述命令其实仅需记录 SET wlj 3
这条命令即可。
redis在配置文件中可以通过设置auto-aof-rewrite-percentage
和auto-aof-rewrite-min-size
来进行自动重写。也可以通过BGREWRITEAOF
命令手动执行重写。
同步硬盘数据
由于操作系统的缓存机制,redis将命令写入AOF时,数据并没有直接写到AOF文件中,而是进入硬盘缓存。默认情况下,操作系统每30秒会执行一次同步操作,将数据真正写入硬盘。因此,如果在这30秒之间,系统异常退出,那么硬盘缓存中的数据就会丢失。
redis默认时每秒同步一次,兼顾性能与安全,也可以根据需求通过appendfsync
命令来设置同步的时机。
其他
# redis默认的AOF文件名
appendonly.aof
# redis.conf
# 修改aof文件名
appendfilename appendonly.aof
# 重写AOF参数
# 当前AOF文件大小超过上一次AOF文件大小百分之多少时会重写
auto-aof-rewrite-percentage 100
# 允许重写的最小AOF文件大小
auto-aof-rewrite-min-size 64mb
# AOF同步硬盘频率
# 默认配置,可选:always、no
# always表示每次写入都会执行同步;no表示由操作系统控制(30秒一次)
appendfsync everysec
参考
本文参考自李子骅老师的《Redis 入门指南》