Redis持久化整理

1 介绍

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

2 RDB

RDB持久化把当前进程数据生成快照保存到硬盘,代表Redis在某个时间点上的数据快照,RDB有手动和自动触发。
- 手动触发
- save:阻塞服务器,直到RDB完成,已弃用
- bgsave:Redis进程fork出子进程,RDB持久化过程由子进程负责,完成后自动结束。Redis内部的RDB都采用bgsave。
- 自动触发
内部自动触发RDB持久化有:①save m n配置(m秒内存在n次修改,自动触发bgsave);②从节点执行全量复制,主节点自动执行bgsave,生成文件发往从节点;③debug reload自动触发’save’;④默认下shutdown,若没开启AOF,自动执行bgsave

2.1 bgsave是主流的触发RDB持久化方式

流程如下:
bgsave->父进程->fork->子进程->生成RDB文件->父进程

  1. 执行bgsave,Redis父进程判断是否有正在执行的子进程(eg.RDB/AOF子进程),存在则直接返回;
  2. 父进程fork创建子进程,fork过程中父进程会阻塞(info stats查看latest_fork_usec,最近一个fork操作耗时-微秒);
  3. fork完成后,bgsave返回“Background saving started”,不再阻塞父进程,可继续响应其他命令;
  4. 子进程创建RDB文件,根据父进程内存 生成 临时快照文件,完成后对原有文件进行原子替换(lastsave的rdb_last_save_time,最后一次生成RDB的时间);
  5. 信号通知父进程,以更新统计信息。

配置文件的dir:RDB文件保存目录,dbfilename:其文件名。

坏盘或磁盘写满时,在线修改config set dir{newDir}到新的可用磁盘路径,然后bgsave磁盘切换(RDB、AOF都适用)。
同理,可在线config set dbfilename{newFileName}。
Redis默认采用LZF算法压缩RDB文件,远远小于内存数据,消耗CPU但大幅↓文件体积,方便保存或网络传输,线上建议开启(默认开)。(config set rdbcompression{yes|no})

2.2 优缺点

优: ①紧凑压缩的二进制文件,可每X小时执行bgsave备份,灾难恢复;②加载RDB恢复数据远远快于AOF。
缺: ①无法实时持久化(bgsave每次都要fork建子进程,重量级操作);②特定二进制格式,新旧版不兼容。

3 AOF

AOF(append only file)持久化,日志 记录每次写命令,重启时再重新执行AOF文件中的命令,恢复数据。它解决了数据持久化的实时性。理解掌握好其机制,↑兼顾数据安全性和性能。

开启AOF:appendonly yes(默认不开启)
AOF文件名:appendfilename(默认文件名appendonly.aof)
保存路径:dir(同RDB)

3.1 AOF是Redis持久化的主流方式

AOF工作流程:
命令写入(append)->AOF缓冲->文件同步(sync)->AOF文件->文件重写(rewrite)<-重启加载(load)


  1. 所有的写入命令会追加到aof_buf(缓冲区);
  2. AOF缓冲区根据对应的策略向硬盘做同步操作;
  3. 随着AOF文件越来越大,需定期对AOF文件进行重写,达到压缩目的;
  4. 当Redis服务器重启时,可加载AOF文件进行数据恢复。
    • 命令写入
      AOF直接采用文本协议格式

①文本协议兼容性很好;②开启AOF后,所有写入命令都包含追加操作,直接采用协议格式,避免了二次处理开销;③可读性,方便直接修改和处理。
AOF为何把命令追加到aof_buf(缓冲区)?
①Redis单线程响应命令,直接追加到硬盘,性能完全取决于当前硬盘负载;②可提供多种缓冲区同步硬盘的策略,在性能和安全性做平衡。
- 文件同步
Redis提供了多种AOF缓冲区同步文件策略,由参数appendfsync控制。
always:不建议配置。每次写入都要同步,代价高;
no:性能↑,但数据安全性无法保证;
everysec: 建议配置,默认配置。兼顾性能和数据安全性。理论上系统突然宕机会丢失1秒数据。
- 重写机制
随着命令不断写入,AOF文件越来越大,重写机制可压缩文件体积。重写把进程内数据->写命令,同步->新AOF文件。

重写后体积变小,可更快被Redis加载

①已超时不写入;②新AOF文件只保留最终数据的写入命令;③多条写命令合并为一个(eg.lpush list a、lpush list b…->lpush list a b …),防客户端缓冲区溢出。

手动触发:bgrewriteaof
自动触发:auto-aof-rewrite-min-size、auto-aof-rewrite-percentage

bgrewriteaof->父进程->fork->(aof_buf->旧AOF文件,aof_rewrite_buf->新AOF文件子进程->信号通知父进程->新AOF文件

1.执行AOF重写请求,若正在执行bgsave,重写命令延迟到bgsave完成之后;
2.父进程fork子进程;
3.1 fork后,继续响应,写入AOF缓冲区+appendfsync策略同步硬盘,保证正确性; 3.2 fork(写时复制技术),子进程只能共享fork操作时的内存数据。用AOF重写缓冲区保存新数据;
4.子进程根据内存快照,按照命令合并规则写入新AOF文件;
5.1写到新文件后,通知父进程;
5.2父进程把AOF重写缓冲区的数据写入到新AOF文件;
5.3替换老文件,完成重写。
- 重启加载
持久化文件加载流程:

1.AOF持久化开启且存在AOF文件时,优先加载AOF文件;2.AOF关闭或者AOF文件不存在时,加载RDB文件; 3. 加载成功后,Redis启动否则打印失败日志。
- 文件校验
加载损坏的AOF文件时会拒绝启动。此时,先备份,然后后redis-check-aof--fix修复,最后diff-u对比差异,人工修改补全(不完整)。当突然掉电,AOF尾部不全时,aof-load-truncated(默认开启)可忽略并继续启动redis。

3.2 问题定位优化


  • fork

fork会复制父进程的空间内存页表,eg.10GB的Redis,需复制约20MB内存页表,fork耗时跟进程总内存量成正比。
改善:

①优先物理机;②控制Redis实例最大可用内存(单实例10G以内);③合理配置Linux内存分配策略;④降低fork频率,↓全量复制。
  • 子进程开销
    子进程负责AOF|RDB文件的重写,主要涉及CPU、内存、硬盘消耗。
    CPU:
    多个redis实例,保证同一时刻只有一个子进程重写。因为redis本身是CPU密集型服务,子进程又负责进程内数据分批写入文件,非常消耗CPU,单核CPU会和父进程产生资源竞争。
    内存:
    多个Redis实例尽量保证同一时刻只有一个子进程在工作;大量写入时避免子进程重写操作。
    硬盘:
    不部署在高负载的硬盘;AOF重写期间不做fsync操作(默认关闭)。
  • AOF追加阻塞
    主线程->AOF缓冲区->同步线程->同步磁盘,AOF缓冲区->对比上次fsync时间->小于2秒通过,大于2秒阻塞
    优化AOF追加阻塞问题主要是优化系统硬盘负载。

总结

生成RDB开销较大,一般用于数据冷备和复制传输;
AOF文件体积逐渐变大,定期执行重写操作降低文件体积;
AOF重写:auto-aof-rewrite-min-size,auto-aofrewritepercentage参数自动触发,bgrewriteaof手动触发;
子进程执行期间,copy-on-write与父进程共享内存,防内存消耗翻倍。AOF重写期间,维护重写缓冲区,保存新的写入命令避免数据丢失;
持久化阻塞主线程:fork阻塞时间跟内存量和系统有关,AOF追加阻塞说明硬盘资源紧张;
单机多实例,防多个子进程重写,做隔离控制。

参考:
《redis开发与运维》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值