" name="sm-site-verification"/>
侧边栏壁纸
博主头像
PySuper 博主等级

千里之行,始于足下

  • 累计撰写 206 篇文章
  • 累计创建 14 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

Redis 高可用 -- 数据持久化(RDB/AOF)

PySuper
2021-11-30 / 0 评论 / 0 点赞 / 4 阅读 / 0 字
温馨提示:
本文最后更新于2024-06-12,若内容或图片失效,请留言反馈。 所有牛逼的人都有一段苦逼的岁月。 但是你只要像SB一样去坚持,终将牛逼!!! ✊✊✊

数据持久化

  • redis 运行时单线程模式运行,所以一次执行 运行一条命令
    • 内存处理速度极快,纳秒级别
    • 非阻塞 IO,IO 多路复用基于事件完成读写
    • 避免线程切换与资源竞争

谨慎使用慢命令:--keys/flushall/flushdb/exec/save/bgsave/...

有效地避免因进程退出造成的数据丢失问题,当下次重启时利用之前持久化的文件即可实现数据恢复

为防止由于系统宕机导致内存数据丢失,需要定时进行数据持久化,写入到硬盘中

  • 快照(RDB),保存当前状态
  • 写日志(AOF),操作流水账,需要恢复时将所有操作执行一遍

RDB

把当前进程数据生成快照保存到硬盘的过程

创建二进制 rdb 文件,第二次会进行覆盖,只有一个文件

在启动 redis 的时候会加载 rdb 文件

触发 RDB 的两种方式:手动触发自动触发

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

手动触发

建议在系统不忙的时候进行

  • save(会阻塞,一个亿的数据会执行三分钟,因为 redis 是单线程模式)
  • bgsave(非阻塞–fork,在后台执行,在后台开启子进程进行保存,还是三分钟)–比较适合线上的维护操作

自动保存

配置文件定时自动保存 redis.conf

执行 debug reload 命令重新加载 Redis 时,也会自动触发 save 操作

默认情况下执行 shutdown 命令时,如果没有开启 AOF 持久化功能则 自动执行 bgsave

# RDB的配置项 #

# 自动保存策略,60 秒内有 1 个 key 发生变化就自动保存
save 60 1

# rdb 文件名
dbfilename dbdump.rdb

# rdb 文件保存目录
dir ./

# 发生错误中断写入,建议开启
stop-writes-on-bgsave-error yes

# 数据文件压缩,建议开启
rdbcompression yes

# 开启crc64错误校验.建议开启
rdbchecksum yes

实现原理

redis-save-1.png

1、执行bgsave,Redis 父进程判断当前是否存在正在执行的子进程

  • 如 RDB/AOF 子进程,如果存在 bgsave 命令直接返回

2、父进程执行 fork 操作创建子进程:

  • fork 操作过程中父进程会阻塞
  • 通过 info stats 命令查看 latest_fork_usec 选项,可以获取最近一个 fork 操作的耗时,单位为微秒

3、父进程 fork 完成后,bgsave 命令返回“Background saving started”

  • 信息并不再阻塞父进程,可以继续响应其他命令

4、子进程创建 RDB 文件,根据父进程内存生成临时快照文件,完成后,对原有文件进行原子替换

  • 执行 lastsave 命令可以获取最后一次生成 RDB 的 时间,对应 info 统计的 rdb_last_save_time 选项

5、进程发送信号给父进程表示完成,父进程更新统计信息,具体见 info Persistence 下的 rdb_* 相关选项

文件处理

  • RDB 文件保存在 dir 配置指定的目录下,文件名通过 dbfilename 配 置指定
  • 可以通过执行 config set dir {newDir} 和 config set dbfilename {newFileName} 运行期动态执行
  • 当下次运行时 RDB 文件会保存到新目录

优缺点

  • 优点
    • RDB 是一个紧凑压缩的二进制文件,代表Redis 某个时间点上的数据快照,非常适用于备份、全量复制等场景
    • 比如每 6 小时执行 bgsave 备份, 并把 RDB 文件拷贝到远程机器或者文件系统中(如 hdfs),用于灾难恢复
    • Redis 加载 RDB 恢复数据远远快于 AOF 的方式
  • 缺点
    • RDB 方式数据没办法做到实时持久化 / 秒级持久化
      • 因为 bgsave 每次运 行都要执行 fork 操作创建子进程,属于重量级操作,频繁执行成本过高
    • RDB 文件使用特定二进制格式保存,Redis 版本演进过程中有多个格式 的 RDB 版本
      • 存在老版本 Redis 服务无法兼容新版 RDB 格式的问题。

针对 RDB 不适合实时持久化的问题,Redis 提供了 AOF 持久化方式来解决

AOF

AOF 日志追加(AppendOnly File)

保存操作的流水账,在宕机重启时,将 AOF 日志重新加载执行,对数据盘压力小

以独立日志的方式记录每次写命令, 重启时再重新执行 AOF 文件中的命令达到恢复数据的目的

AOF 的主要作用是:解决了数据持久化的实时性,目前已经是 Redis 持久化的主流方式

追加策略

命令 always everysec no
写入 随时写入 每秒写入 依赖os规则写入
优点 不丢失数据 每秒一次fsync 不用管
缺点 IO开销大 丢1s数据 不可控
使用 不推荐 推荐 不推荐

重写压缩

就是将对相同 key 进行设置的日志,只保存最后的结果操作

实现方式

手动执行

-> bgrewriteaof

redis-save-2.png

自动执行

配置 redis.conf 文件,配置开启 AOF,记录日志的策略,重写日志策略

  • 根据参数确定自动触发时机:
    • auto-aof-rewrite-min-size:表示运行 AOF 重写时文件最小体积,默认 为 64MB
    • auto-aof-rewrite-percentage:代表当前 AOF 文件空间 (aof_current_size)和上一次重写后 AOF 文件空间(aof_base_size)的比值
  • 自动触发时机 = aof_current_size>auto-aof-rewrite-minsize&&(aof_current_size-aof_base_size)/aof_base_size>=auto-aof-rewritepercentage
# AOF 配置 #

# 开启 aof
appendonly yes

# aof 日志文件名
appendfilename aof-6666.aof

# 每秒记录一次日志,建议everysec
appendfsync everysec

# 重写过程中是否向日志文件写入
# yes 代表 rewrite 过程中,不向 aof 文件中追加信息, rewrite 结束后再写入
# no 代表 rewrite 执行的同时,也向 aof 追加信息
no-appendfsync-on-rewrite yes

# 触发重写文件增长百分比,默认100%
auto-aof-rewrite-percentage 100

# 触发重写最小 aof 文件尺寸
auto-aof-rewrite-min-size 64mb

实现原理

命令写入 (append)、文件同步(sync)、文件重写(rewrite)、重启加载 (load)

redis-save-3.png

1、所有的写入命令会追加到 aof_buf(缓冲区)中

2、AOF 缓冲区根据对应的策略向硬盘做同步操作

3、随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的

4、当 Redis 服务器重启时,可以加载 AOF 文件进行数据恢复

redis-save-4.png

总结

Redis 提供了两种持久化方式:RDB 和 AOF

  • RDB
    • 使用一次性生成内存快照的方式,产生的文件紧凑压缩比更高,因此读取 RDB 恢复速度更快
    • 由于每次生成 RDB 开销较大,无法做到实时持久化,一般用于数据冷备和复制传输
    • save 命令会阻塞主线程不建议使用,bgsave 命令通过 fork 操作创建子 进程生成 RDB 避免阻塞
  • AOF
    • AOF 通过追加写命令到文件实现持久化,通过 appendfsync 参数可以 控制实时 / 秒级持久化
    • 因为需要不断追加写命令,所以 AOF 文件体积逐渐变大,需要定期执行重写操作来降低文件体积
    • AOF 重写可以通过两个 参数控制自动触发,也可以使用 bgrewriteaof 命令手动触发
    • 子进程执行期间使用 copy-on-write 机制与父进程共享内存,避免内 存消耗翻倍
    • AOF 重写期间还需要维护重写缓冲区,保存新的写入命令避免数据丢失
  • 持久化阻塞主线程
    • fork 阻塞:跟内存量和系统有关
    • AOF 追加阻塞:说明硬盘资源紧张
  • 选择
    • 当RDB与AOF都开启后,Redis官方默认采用AOF恢复数据
    • 在日常开发中,也推荐AOF来持久化数据
    • Redis主从数据同步的底层采用RDB实现
  • 单机下部署多个实例时,为了防止出现多个子进程执行重写操作, 建议做隔离控制,避免 CPU 和 IO 资源竞争


0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区