内容简介:RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发。配置
RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发。
触发机制
手动触发分别对应save 和bgsave
- save 阻塞 redis 服务器,直到RDB过程完成,对于内存比较大的实例会造成长时间阻塞,不建议线上环境使用。
- bgsave,fork 子进程完成RDB,阻塞只发生在fork 阶段,一般时间很短。
自动触发
-
save m n m表示秒内数据集存在n次修改时,自动触发bgsave。
-
从节点执行全量复制操作,主节点自动执行bgsave生成RDB文件并发送从节点。
- 执行 debug reload 命令会重新加载redis,会自动触发save操作。
- 默认执行shutdown,如果没有开启AOF 会自动执行bgsave。
流程
-
执行bgsave 命令,父进程判断当前是否存在正在执行的子进程,如RDB/AOF 子进行,如果存在bgsave 直接返回结果。
-
父进程执行fork,fork 过程中会阻塞父进程,通过info stats 查看latest_fork_use 选项,可以获取最近一次fork 的耗时,单位是微秒。
127.0.0.1:6379> INFO stats # Stats …… latest_fork_usec:612 ……
-
父进程fork 完,bgsave 命令会返回
background saveing started
信息,并不在阻塞父进程,可以继续响应其他命令。127.0.0.1:6379> BGSAVE Background saving started
-
子进程创建RDB 文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。执行lastsave 命令可以获取最后一次生成RDB 的时间,对应 info 统计中的rdb_last_save_time 选项。
127.0.0.1:6379> LASTSAVE (integer) 1556158402
- 进程发送信号给父进程表示完成,父进程更新统计信息,具体见 info Persistence下的 rdb_* 相关选项。
127.0.0.1:6379> INFO stats # Persistence loading:0 rdb_changes_since_last_save:0 rdb_bgsave_in_progress:0 rdb_last_save_time:1556158402 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:0 rdb_current_bgsave_time_sec:-1 rdb_last_cow_size:24240128 aof_enabled:0 aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:-1 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok aof_last_write_status:ok aof_last_cow_size:0
配置
RDB 优缺点
RDB的优点:
- RDB是一个紧凑压缩的二进制文件,代表Redis在某个时间点上的数据快照。非常适用于备份,全量复制等场景。比如每6小时执行bgsave备份,并把RDB文件拷贝到远程机器或者文件系统中(如hdfs),用于灾难恢复。
- Redis加载RDB恢复数据远远快于AOF的方式。
RDB的缺点:
- RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作,频繁执行成本过高。
- RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本Redis服务无法兼容新版RDB格式的问题。针对RDB不适合实时持久化的问题,Redis提供了AOF持久化方式来解决。
AOF
AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式。理解掌握好AOF持久化机制对我们兼顾数据安全性和性能非常有帮助。
使用
配置
cat redis.conf | grep ^append appendonly no appendfilename "appendonly.aof" appendfsync everysec
AOF的工作流程操作:命令写入(append)、文件同步(sync)、文件重写(rewrite)、重启加载(load)
流程
- 所有写入追加到 aof_buf 中。
- AOF 缓冲区根据对应的策略向硬盘做同步操作。
- 随着AOF文件的变大,需要定期对AOF 文件进行重写,达到压缩目的。
- 当redis 服务器重启时,可以加载AOF文件进行数据恢复。
为什么采用文本方式写入
AOF 写入采用文本方式,理由如下:
- 兼容性好
- 开启AOF 后,所有写操作都是追加的,避免了二次处理开销。
- 文本协议具有可读性,方便直接修改和处理。
为什么要把命令追加到AOF_BUF
redis 使用单线程响应命令,如果每次写AOF 都直接追加到磁盘,性能会很差,先写入缓存区,然后在同步到磁盘性能会有很大提升。
AOF 的文件同步
可配置值 | 说明 |
---|---|
always | 命令写人aof_ buf 后调用系统fsync操作同步到AOF文件,fsync 完成后线程返回 |
everysec | 命令写入aof_ buf后调用系统write操作,write完成后线程返回。fsync 同步文件操作由专门线程每秒调用- -次 |
no | 命令写人aof_ buf 后调用系统write操作,不对AOF文件做fsync同步,同步硬盘操作由操作系统负责,通常同步周期最长30秒 |
系统调用write和fsync说明:
- write操作会触发延迟写(delayed write)机制。Linux在内核提供页缓冲区用来提高硬盘IO性能。write操作在写入系统缓冲区后直接返回。同步硬盘操作依赖于系统调度机制,例如:缓冲区页空间写满或达到特定时间周期。同步文件之前,如果此时系统故障宕机,缓冲区内数据将丢失。
- fsync针对单个文件操作(比如AOF文件),做强制硬盘同步,fsync将阻塞直到写入硬盘完成后返回,保证了数据持久化。
AOF 重写
随着不断写入AOF 文件不断变大,redis 通过AOF 重写机制压缩文件体积。把进程内的数据转化为写命令同步到新的AOF文件。
重写AOF的优势
- 降低文件占用,提升redis 加载速度。
AOF 分手动和自动触发
- 手动: bgrewriteaof
- 自动,根据配置文件中的下面2个参数确定自动触发时间
# cat redis.conf |grep ^auto-aof auto-aof-rewrite-percentage 100 # 表示当前AOF 文件空间(aof_current_size)和上一次重写后AOF文件空间(aof_base_size)的比 auto-aof-rewrite-min-size 64mb # 表示运行AOF重写时的文件最小体积
自动触发时机=aof_current_size>auto-aof-rewrite-minsize&&(aof_current_size-aof_base_size)/aof_base_size>=auto-aof-rewritepercentage其中aof_current_size和aof_base_size可以在info Persistence统计信息中查。
流程说明
-
执行AOF 重写请求,如果当前有进程正在执行AOF重写,请求不执行并返回
ERR Background append only file rewriting already in progre
如果当前正在执行bgsave,重写命令延迟到bgsave 完成后执行,返回
Background append only file rewriting schedul
-
父进程fork 子进程,开销等同于bgsave。
AOF重写缓冲区
-
子进程根据内存快照,按命令合并规则写入到新的AOF 文件。每次批量写入磁盘数据由配置
置aof-rewrite-incremental-fsync
控制,默认为32MB,防止单次刷盘数据过多造成硬盘阻塞。 - 新AOF 文件写入后,子进程发送信号给父进程,更新统计信息。
- 父进程把AOF 重写缓存区的数据写入到新AOF文件。
- 使用新AOF文件替换老文件,完成AOF重写。
问题定位与优化
fork 操作耗时问题排查
redis 做 RDB 或 AOF 重写时,会进行fork,虽然fork创建的子进程不需要拷贝父进程的物理内存空间,但是会复制父进程的空间内存页表。例如对于10GB的Redis进程,需要复制大约20MB的内存页表,因此fork操作耗时跟进程总内存量息息相关,如果使用虚拟化技术,特别是Xen虚拟机,fork操作会更耗时。
如何改善fork操作的耗时:
1)优先使用物理机或者高效支持fork操作的虚拟化技术,避免使用Xen。
2)控制Redis实例最大可用内存,fork耗时跟内存量成正比,线上建议每个Redis实例内存控制在10GB以内。
3)合理配置 Linux 内存分配策略,避免物理内存不足导致fork失败。
4)降低fork操作的频率,如适度放宽AOF自动触发时机,避免不必要的全量复制等。
子进程开销监控和优化
CPU
-
CPU开销分析。子进程负责把进程内的数据分批写入文件,这个过程属于CPU密集操作,通常子进程对单核CPU利用率接近90%.
-
CPU消耗优化。Redis是CPU密集型服务,不要做绑定单核CPU操作。由于子进程非常消耗CPU,会和父进程产生单核资源竞争。
- 不要和其他CPU密集型服务部署在一起,造成CPU过度竞争。
- 如果部署多个Redis实例,尽量保证同一时刻只有一个子进程执行重写工作。
内存
-
内存消耗分析。子进程通过fork操作产生,占用内存大小等同于父进
程,理论上需要两倍的内存来完成持久化操作,但Linux有写时复制机制(copy-on-write)。父子进程会共享相同的物理内存页,当父进程处理写请求时会把要修改的页创建副本,而子进程在fork操作过程中共享整个父进程内存快照。
-
内存消耗监控。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。