深入理解Redis持久化
一、快照 RDB
1.1 bgsave触发情景:
- 使用save相关配置,如“save m n”。表示m秒内数据集存在n次修改时,自动触发bgsave
- 全量复制
- 执行shutdown 时,如果没有开启AOF持久化功能则自动执行bgsave。
- 执行flushall 清空所有缓存时
1.2 bgsave原理:
二、AOF
2.1 开启方式:
在配置文件中将 appendonly no 中的no 改为yes。
2.2 工作流程:
1. 将写入命令保存到AOF缓冲区。原因:redis是单线程的,如果直接保存到硬盘会影响性能。
2. AOF缓冲区根据对应的策略向硬盘做同步操作,策略由配置文件中的 appendfsync 参数决定,有以下三种策略:
种类 |
说明 |
特点 |
always |
写入aof_buf后调用fsync同步到AOF文件。 |
安全、低效 |
everysec |
写人aof_buf后返回,由其他线程每秒调用fsync进行文件同步。 |
折中,默认配置 |
no |
写人aof_buf后返回,同步的操作交给操作系统决定。 |
高效,不安全 |
3. 当AOF文件过大时执行重写,达到压缩的目的。
2.3 bgrewriteaof 重写原理
2.3.1 自动触发机制:
由以下两个参数决定:
auto-aof-rewrite-min-size:重写时AOF的最小大小,默认64M
auto-aof-rewrite-percentage:当前AOF文件大小(current_size)和上次重写后AOF文件大小(base_size)的比值
触发条件:auto-aof-rewrite-min-size && (current_size - base_size) / base_size>=auto-aof-rewrite-percentage
2.3.2 如何起到压缩效果:
由于AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程,因此可以对下面这些命令进行优化:
del key 删除命令直接不保存
set key val ,set key val2 对同一个key进行多次赋值的命令,只需保存最后一次赋值
lpush list a、lpush list b、lpush list c 可以将多条命令合并为:lpush list a b c。 (合并命令的长度会有限制)
2.3.3 重写流程:
三、RDB-AOF混合持久化
3.1 概述
redis4.0开始,为了解决aof加载缓慢这一问题,而提出了RDB-AOF混合持久化,并通过修改 bgrewriteaof 过程实现:
1. 在保存aof快照的时候使用 rdb格式进行保存
2. 把aof重写缓冲区中的增量数据以aof格式追加到AOF文件后面。
3.2 开启方式:
把配置文件中的aof-use-rdb-preamble 参数配置为yes,5.0版本默认是开启的。
四、重启加载流程
五、总结
1. RDB使用一次性生成内存快照的方式,产生的文件紧凑压缩比更高,因此读取RDB恢复速度更快。由于每次生成RDB开销较大,无法做到实时持久化,一般用于数据冷备和复制传输。
2. fork 过程会阻塞父进程,不要轻易执行持久化操作
3. fork耗时跟内存量成正比,应控制Redis实例最大可用内存,最好10G以内。(fork子进程虽然不需要拷贝父进程的物理内存空间,但是会复制父进程的空间内存页表。例如对于10GB的Redis进程,需要复制大约20MB的内存页表,耗时大概200ms。)
4. Redis单线程架构导致无法充分利用CPU多核特性,因此某些情况下可能会在一台机子上部署多个实例,此时为了防止出现多个子进程同时执行,建议做隔离控制,避免CPU和IO资源竞争。
5. 不要和其他高硬盘负载的服务部署在一起。如:存储服务、消息队列服务等。因为磁盘IO资源竞争激烈的情况下,容易导致AOF 在同步文件的时候阻塞父线程。原因如下: