Redis技术指南-3-redis持久化机制

Redis技术指南-3-redis持久化机制

    • RDB
      • 描述:
      • 触发机制:
    • AOF
      • 概念:
      • 使用AOF:
      • 重写流程:
      • 重启加载
    • 问题定位和优化

上一节:
Redis技术指南-2-redis基础数据类型

上一节聊了Redis几个基本数据类型,这一节我们来看看Redis具体如何持久化数据?

Redis 支持RDB 和 AOF两种持久化方式,有效避免因进程退出造成的数据丢失问题,
下次重启时利用之前持久化的文件即可实现数据恢复

RDB

描述:

RDB持久化是把当前进程数据生成快照保存到硬盘的过程,其持久化过程为手动触发、自动触发。
redis重启时,会自动把rdb文件加载到内存中
DB loaded from disk: 0.000 seconds

触发机制:

手动:

  • save 命令: 阻塞当前Redis服务器,直到RDB过程完成为止,对于内存较大的实例会造成长时间的阻塞。一般线上不建议使用。
  • bgsave命令(流行使用):Redis进程fork创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。

自动触发:

  • 使用save相关配置: 如save m n, 表示m 秒内数据集存在n次修改时,自动触发bgsave 在redis.conf中就有
  • 如果从节点执行全量复制操作,主节点自动执行bgsave命令生成RDB文件并发送给从节点。
  • 执行debug reload 命令重新加载Redis时,也会自动触发save操作。
  • 默认情况下执行shutdown命令时,如果没有开启AOF持久化功能则自动执行bgsave

执行流程(bgsave):
Redis技术指南-3-redis持久化机制_第1张图片
分为一下几步:

  • 执行bgsave命令,Redis父进程判断当前是否存在正在执行的子进程,如RDB/AOF子进程,如果存在bgsave命令直接返回。
  • 父进程执行fork操作创建子进程,fork操作过程中父进程会阻塞,通过info stats命令查看latest_fork_usec选项,可以获取最近一个fork操作的耗时,单位为微秒。
  • 父进程fork完成后,bgsave命令返回"Background saving started" 信息并不再阻塞父进程,可以继续响应其他命令。
  • 子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换。执行lastsave 可以获取最后一次生成RDB的时间(s), 对应info统计的rdb_last_save_time选项。
  • 子程发送信号给父进程表示完成,父进程更新统计信息,具体间info Persistence下的rdb_*相关选项。

RDB文件的处理:

  • 保存: 一般在redis.conf中 dbfileame {newFileName} -> dump.rdb
    • config set dir {new Dir} 和 config set dbfilename {newFileName}
  • 压缩: 默认采用LZF算法进行压缩
  • 校验: redis-check-dump工具检测RDB文件是否损坏。

RDB的优缺点:

  • 优点: RDB是一个紧凑压缩的二进制文件,代表Redis在某个时间点上数据快照。适合备份、全量复制场景。6小时bgsave 一份到异地机房,易于容灾备份。
    • Redis加载RDB_恢复数据_远快于AOF的方式。
  • 缺点:
    • 数据没办法实时持久化、秒级持久化。每次bgsave fork子进程,属于一个重量级操作,频繁执行有成本。
    • rdb文件二进制保存,如果有新的rdb版本,无法向后兼容

由于RDB不适合实时持久化,故提出了AOF方式。

AOF

概念:

append only file:以独立日志等方式记录每次写命令,重启时重新执行AOF文件中的命令达到数据恢复目的。主要是解决数据持久化的实时性。

使用AOF:

appendonly yes, 默认不开启。文件名appendonly.aof。
Redis技术指南-3-redis持久化机制_第2张图片

  • 命令写入 --写入到aof_buf中
    • 直接文本协议: 理由:好兼容性,可读性
    • 多种缓冲区同步硬盘,避免每次一个命令同步一次,性能和安全平衡。
  • 文件同步 --同步到磁盘
    • 由参数appendfsync控制, 下面是配置值
    • always: 命令写入aof_buf后, 调用系统fsync同步到aof文件,完成后线程返回。但是取决于硬盘写速度。
    • no: 命令写入aof_buf后,调用系统write,不对aof做fsync同步,同步硬盘由操作系统决定(30s),有安全问题。
    • everysec: 写入aof_buf后,调系统write,完成后返回。fsync同步文件操作由专门线程每秒执行一次。
    • 实际上操作系统中write会触发延迟读写能力,每次写入linux缓冲区,write返回,什么时候把linux缓冲区同步到磁盘由系统调度决定。如果buf有数据,但是系统宕机,还未来及同步到磁盘,就会有buf中数据丢失问题。 建议everysec模式。
  • 文件重写 --定时对aof文件进行重写,减少文件大小
    • 重写后的AOF文件为什么可以变小?
      • 进程内已经超时的数据不在写入文件
      • 旧的AOF文件含有无效的命令,del key1, set aa等
      • 多条写命令合成一个 lpush list 1, lpush list b
    • 重写分为手动和自动触发:
      • 手动: 直接调用bgrewriteaof 命令
      • 自动:auto-aof-rewrite-min-size(运行AOF重写时文件的最小体积 默认64m) 和 auto-aof-rewrite-percentage (当前AOF文件空间 aof_current_size ) / 上一次重写后AOF文件空间(aof_base_size)比值。
      • 触发时机:aof_current_size > auto-aof-rewrite-min-size && (aof_current_size-aof_base_size) / aof_base_size >= auto-aof-rewrite-percentage.
    • Redis技术指南-3-redis持久化机制_第3张图片

重写流程:

  1. 执行aof重写请求
    1. 如果当前进程正在执行aof重写,请求不执行直接返回
    2. 如果。。。。。。。。rdb重写,等待bgsave命令返回后,继续执行。
  2. 父进程执行fork创建子进程
  3. 主进程继续响应命令,所有修改命令亦然写入AOF缓冲区并依据appendfsync策略同步到disk
    1. 由于fork操作运用写时复制技术,子进程只能共享fork操作时的内存数据。父响应命令,Redis使用AOF重写缓冲区保存这一部分数据,防止新的AOF文件生成期间丢失这部分数据。
  4. 子进程根据内存快照,按照命令写入到新的aof文件中。每次批量写入disk数据被aof-rewrite-incremental-fsync控制,默认32MB,防止单次刷盘数据过多造成硬盘阻塞。
  5. 新AOF文件写入完成后,子进程发送信号给父进程,父进程更新统计信息,具体见info persistence下 aof_*信息。
    1. 父进程把aof重写缓冲区的数据写入新的aof文件
    2. 使用aof文件替换老文件,完成aof重写。

重启加载

Redis技术指南-3-redis持久化机制_第4张图片

问题定位和优化

  • 子进程执行期间使用copy-on-write机制与父进程共享内存,避免内存消耗翻倍。AOF重写期间还需要维护重写缓冲区,保存新的写入命令避免数据丢失。
  • 持久化阻塞主线程场景有:fork阻塞和AOF追加阻塞。fork阻塞时间 跟内存量和系统有关,AOF追加阻塞说明硬盘资源紧张。
  • 单机下部署多个实例时,为了防止出现多个子进程执行重写操作, 建议做隔离控制,避免CPU和IO资源竞争

下一节
Redis技术指南-1-redis基础概念

你可能感兴趣的:(redis,数据库,缓存)