Redis 持久化——学习笔记

Redis 持久化

1. Redis 持久化的取舍和选择

持久化的作用

什么是持久化

  • redis所有数据是保存在内存中的,对数据的更新将异步的保存到磁盘上。

持久化的实现方式

  1. 快照方式
    • MySQL Dump
    • Redis RDB
  2. 写日志方式
    • MySQL Binlog
    • Hbase Hlog
    • Redis AOF

2. RDB 持久化 方式

什么是RDB?

image

触发机制——主要三种方式

1. save(同步)生成RDB文件

image

image

2. bgsave(异步)生成RDB文件

image

image

image

3. 自动生成RDB文件

通过修改配置文件,控制自动生成RDB文件

image

缺点

  • RDB 生成频率太高
  • 不容易控制写入量

配置

save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb  # 生成RDB文件名
dir ./               # 生成RDB文件、日志文件、AOF文件的存储路径
stop-writes-on-bgsave-err yes  # bgsave 发生错误,将停止写入
rdbcompression yes             # RDB 文件是否压缩 默认yes
rdbchecksum yes                # 是否检查 RDB 文件校验和 默认yes

最佳配置

image

触发机制——不容忽略的方式

  1. 全量复制(主从复制会触发生成RDB文件)
  2. debug reload (debug 级别重启 会触发生成RDB文件)
  3. shutdown (关闭 会触发生成RDB文件)

试验

  • 试验 save 是否会阻塞
  • 试验 bgsave fork 过程
  • 自动配置的 save 是否真的有效
  • RDB 文件长什么样子

配置启动试验redis

  1. cd redis # redis 目录的创建 参照redis 安装部分 https://www.cnblogs.com/guohewei/p/16246771.html#_label0_2
  2. mkdir config # 存放配置文件
  3. mkdir data # 存放RDB 文件
  4. cp redis.conf config/ # 复制默认配置文件
    • cat redis.conf | grep -v "#" | grep -v "^$" > redis-6382.conf # 去掉注释和空格
  5. 修改配置文件
    [root@nezha-api config]# vi redis-6382.conf
    port 6379
    daemonize yes
    pidfile /var/run/redis_6379.pid
    logfile 6379.log
    # save 3600 1
    # save 300 100
    # save 60 10000
    stop-writes-on-bgsave-error yes
    rdbcompression yes
    rdbchecksum yes
    dbfilename dump-6379.rdb
    dir /root/Redis/redis/data
    
  6. redis-server redis-6379.conf # 启动redis

验证用例

首先插入大量数据 (use memory 大于 500MB)

  1. 试验 save 是否会阻塞
    • 打开两个 redis-cli, 其中一个执行 save 后,另一个立即执行 'get hello', 查看执行时间,是否阻塞
  2. 试验 bgsave fork 过程
    • 打开两个 redis-cli, 其中一个执行 bgsave 后,另一个立即执行 'get hello', 查看执行时间,是否阻塞
    • 通过命令查看redis 进程 ps aux | grep redis- | grep -v "redis-cli"|grep -v "grep" 查看是否有 fork 进程
    • 查执行 bgsave 后,/root/Redis/redis/data 目录中是否有临时文件生成,等一会临时文件消失,dump-6379.rdb 文件被更新
  3. 自动配置的 save 是否真的有效
    • 修改配置文件
      [root@nezha-api config]# vi redis-6382.conf
      port 6379
      daemonize yes
      pidfile /var/run/redis_6379.pid
      logfile "6379.log"
      # save 3600 1
      # save 300 100
      save 60 5           # 60 秒 5条改变记录,自动执行 bgsave
      stop-writes-on-bgsave-error yes
      rdbcompression yes
      rdbchecksum yes
      dbfilename dump-6379.rdb
      dir /root/Redis/redis/data
      
    • 重启redis redis-cli shutdown && redis-server redis-6379.conf
    • 执行6次修改命令,查看rbd.文件生成、修改时间 ,查看日志文件是否有记录
      14801:M 12 May 2022 16:42:39.099 * 5 changes in 60 seconds. Saving...
      14801:M 12 May 2022 16:42:39.100 * Background saving started by pid 15013
      15013:C 12 May 2022 16:42:39.103 * DB saved on disk
      15013:C 12 May 2022 16:42:39.103 * RDB: 0 MB of memory used by copy-on-write
      14801:M 12 May 2022 16:42:39.201 * Background saving terminated with success
      

总结

  1. RDB 是 Redis 内存到硬盘的快照,用于持久化
  2. save 通常会阻塞 Redis
  3. bgsave 不会阻塞 Redis, 但会fork 新进程
  4. save 自动配置满足任一就会被执行
  5. 有些触发 save 机制不容忽视

3. AOF 持久化 方式

RDB 现存问题

  • 耗时、耗性能

    image

  • 不可控、丢失数据

    image

什么是AOF

  • AOF原理-创建

    image

  • AOF原理-恢复

    image

AOF 三种策略

1. always

image

2. everysec

image

3. no

image

always everysec no 对比

通常使用 everysec 模式

image

AOF 重写

image

AOF 重新作用

  • 减少硬盘占用量
  • 加速恢复速度

AOF 重写实现方式

  1. bgrewriteaof 命令

    image

  2. AOF 重写配置

    • auto-aof-rewrite-min-size: AOF 文件重写需要的尺寸

      就是当 AOF 文件达到多大的时候进行重写

    • auto-aof-rewrite-percentage: AOF 文件增长率

      就是当执行一次重写后,下一次达到多大进行重写(比如第一次达到100M重写,设置为 100%,则第二次达到200M再次重写)

  3. AOF 统计

    • aof_current_size: AOF 当前尺寸(单位:字节)
    • aof_base_size : AOF 上次启动和重写的尺寸(单位:字节)
  4. 重写自动触发时机

    (1) aof_current_size > auto-aof-rewrite-min-size (触发重写)

    (2) (aof_current_size - aof_base_size) / aof_base_size > auto-aof-rewrite-percentage (触发重写)

  5. AOF 重写流程

    image

AOF 配置

appendonly yes                          # 打开 AOF 功能
appendfilename apppendonly-6379.aof     # AOF 文件名
appendfsync everysec                    # AOF 策略
dir /bigdiskpath                        # 存储生成RDB文件、日志文件、AOF文件的路径
no-appendfsync-on-rewrite yes           # AOF 重写的时候,是否做正常的 append 操作
auto-aof-rewrite-min-size 64mb          # 就是当 AOF 文件达到64mb的时候进行重写
auto-aof-rewrite-percentage 100         # AOF 增长率大于 100% 重写
aof-load-truncated yes                  # 重启加载 AOF 时,是否忽略由于AOF不完整,格式等错误 (yes 忽略)

试验

  • AOF 生成
  • AOF 长什么样子
    [root@nezha-api data]# cat appendonly-6379.aof
    REDIS0009�	redis-ver6.2.7�
    �edis-bits�@�ctime���|bused-mem��W
     aof-preamble���counter�worldbigmy_listabcd��
                                                 s�<*2
    $6
    SELECT
    $1
    0
    *3
    $3
    set
    $4
    hehe
    $2
    go
    
  • AOF 配置
    # 基本配置
    port 6379
    daemonize yes
    pidfile /var/run/redis_6379.pid
    logfile "6379.log"
    dir /root/Redis/redis/data
    
    # AOF 配置
    appendonly yes                          # 打开 AOF 功能
    appendfilename apppendonly-6379.aof     # AOF 文件名
    appendfsync everysec                    # AOF 策略
    
    # AOF 重写配置
    no-appendfsync-on-rewrite yes           # AOF 重写的时候,是否做正常的 append 操作
    auto-aof-rewrite-min-size 64mb          # 就是当 AOF 文件达到64mb的时候进行重写
    auto-aof-rewrite-percentage 100         # AOF 增长率大于 100% 重写
    
    # AOF 重载配置
    aof-load-truncated yes                  # 重启加载 AOF 时,是否忽略由于AOF不完整,格式等错误 (yes 忽略)
    

4. RDB 和 AOF 的抉择

(1) RDB 和 AOF 的比较

image

(2) RDB 最佳策略

  • "关" 实际是关不了的(参见上文:"有些触发 save 机制不容忽视")
  • 集中管理 (定期 按天、按星期 等等)
  • 主从,从节点开 RDB

(3) AOF 最佳策略

  • "开": 缓存和存储
    • 建议开启
    • 如果将redis单纯当做缓存使用,可以考虑关闭
  • AOF重新集中管理
    • 单机多部署的情况下,如果 AOF 集中发生,可能都在机器内存爆满
  • 使用 everysec 策略

(4) 最佳策略

  • 小分片 (使用 maxmemory 对redis 进行规划,maxmemory=4GB)
  • 存储和缓存特性决定
  • 监控(硬盘、内存、负载、网络)
  • 保证足够的内存

开发运维常见问题

1. fork 操作

  1. fork 操作是同步操作,大多数情况下速度是非常快的 (只是做内存页的拷贝,不是完全内存的拷贝)
  2. 与内存量息息相关:内存越大耗时越长(与机器类型有关系)
  3. info Persistence 查看latest_fork_usec
    127.0.0.1:6379> info Persistence # 查看持久化信息
    # Persistence
    loading:0
    current_cow_size:0
    current_cow_size_age:0
    current_fork_perc:0.00
    current_save_keys_processed:0
    current_save_keys_total:0
    rdb_changes_since_last_save:0
    rdb_bgsave_in_progress:0
    rdb_last_save_time:1652358920
    rdb_last_bgsave_status:ok
    rdb_last_bgsave_time_sec:0
    rdb_current_bgsave_time_sec:-1
    rdb_last_cow_size:286720
    aof_enabled:1
    aof_rewrite_in_progress:0
    aof_rewrite_scheduled:0
    aof_last_rewrite_time_sec:0
    aof_current_rewrite_time_sec:-1
    aof_last_bgrewrite_status:ok
    aof_last_write_status:ok
    aof_last_cow_size:323584
    module_fork_in_progress:0
    module_fork_last_cow_size:0
    aof_current_size:207
    aof_base_size:153
    aof_pending_rewrite:0
    aof_buffer_length:0
    aof_rewrite_buffer_length:0
    aof_pending_bio_fsync:0
    aof_delayed_fsync:0
    
  4. 改善 fork
    • 优先使用物理机或者高效支持fork操作的虚拟化技术
    • 控制 Redis 实例最大可用内存:maxmemory
    • 合理配置Linux内存分配策略:vm.overcommit_memory=1 (默认是0 当发现没有足够内存分配,就不去分配) 这样会阻塞 fork, 所有设置为 1
    • 降低 fork 频率:如放宽 AOF 重写自动触发时机,不必要的全量复制

2. 子进程开销和优化

  1. CPU

    • 开销: RDB 和 AOF 文件生成,属于CPU密集型
    • 优化: 不做 CPU 绑定,不和 CPU 密集型部署
  2. 内存

    • 开销: fork 内存开销,copy-on-write
    • 优化: echo never > /sys/kernel/mm/transparent_hugepage/enabled (关闭 可以优化内存,redis 用不着)
  3. 硬盘

    • 开销: AOF 和 RDB 文件写入,可以结合 iostat iotop分析
    • 优化:
      • 不要和高硬盘负载部署在一起:存储服务,消息队列
      • 增加配置no-appendfsync-on-rewrite yes: AOF 重写的时候,是否做正常的 append 操作
      • 根据写入量决定磁盘类型:例如ssd
      • 单机多部署持久化文件目录可以考虑分盘

3. AOF 追加阻塞

image

AOF 追加阻塞问题定位

  1. 日志定位

    image

  2. info Persistence 查看latest_fork_usec

    127.0.0.1:6379> info Persistence # 查看持久化信息
    # Persistence
    aof_delayed_fsync:100  # 阻塞会加1,是历史累计值,无法判断那一段事件阻塞
    
  3. 通过硬盘观察

    image

posted @ 2022-05-12 22:07  郭赫伟  阅读(34)  评论(0编辑  收藏  举报