Redis 持久化之 RDB 和 AOF

栏目: 数据库 · 发布时间: 7年前

内容简介: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。

流程

Redis 持久化之 RDB 和 AOF

  • 执行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)

Redis 持久化之 RDB 和 AOF

流程

  • 所有写入追加到 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统计信息中查。

Redis 持久化之 RDB 和 AOF

流程说明

  • 执行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操作过程中共享整个父进程内存快照。

  • 内存消耗监控。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

XML Hacks

XML Hacks

Michael Fitzgerald / O'Reilly Media, Inc. / 2004-07-27 / USD 24.95

Developers and system administrators alike are uncovering the true power of XML, the Extensible Markup Language that enables data to be sent over the Internet from one computer platform to another or ......一起来看看 《XML Hacks》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具