持久化:将内存中的数据保存到硬盘中,常用的持久化方式有快照和写日志

  • 快照:MySQL Dump、Redis RDB
  • 写日志:MySQL Binlog、Hbase HLog、Redis AOF

Redis官方提供了两种不同的持久化方法来将数据存储到硬盘里面分别是:

持久化:将数据从内存保存到硬盘中

  • 快照(Snapshot):保存某一时刻的数据状态
  • AOF (Append Only File)只追加日志文件:将redis的所有写入命令记录到日志文件中

快照

特点:
redis 持久化 - 图1
这种方式可以将某一时刻的所有数据都写入硬盘中,这是redis默认的持久化方式,保存的文件以 .rdb 形式结尾,因此也称为 rdb 方式

快照生成方式:

  1. 客户端方式:BGSAVE 和 SAVE 命令
  2. 服务端配置自动触发

BGSAVE:客户端可以使用BGSAVE命令来创建一个快照,当接受到客户端的BGSAVE命令时,redis会fork来创建一个子进程,然后子进程负责将快照写入磁盘中,而父进程则继续处理命令请求

  • 文件策略:如果存在老的 RDB 文件,新替换老
  • 时间复杂度:O(n)

    fork:当一个进程创建子进程时,底层的操作系统会创建该进程的一个副本,在类unix系统中创建子进程的操作会进行优化;在开始的时候父子进程共享相同内存,直到父进程或子进程对内存进行了写操作后,对被写入的内存的共享才会结束


redis 持久化 - 图2

SAVE:客户端调用SAVE命令来创建一个快照,接收到SAVE命令的redis服务器在创建快照完毕之前不再响应任何其他的命令(redis服务端会被阻塞

  • 文件策略:如果存在老的 RDB 文件,新替换老
  • 时间复杂度:O(n)

redis 持久化 - 图3

服务端配置满足条件触发:

  • 如果用户在redis.conf中设置了save配置选项,redis会在save选项条件满足之后自动触发一次BGSAVE命令,如果设置多个save配置选项,当任意一个save配置选项条件满足,redis也会触发一次BGSAVE命令
  • 服务端接受客户端 shutdown 命令会触发一个 save 命令
  • 全量复制(分布式)
  • debug reload
  • 默认开启: ```bash

    save seconds changes

    save 900 1 # 15min 一次修改 save 300 10 # 5min 10次修改 save 60 10000 # 1min 10000次修改

dbfilename dump-${port}.rdb dir /var/redis stop-writes-on-bgsave-error yes #bgsave出错则停止写入 rdbcompression yes #进行压缩 rdbchecksum yes

  1. <a name="FBLDs"></a>
  2. #### AOF
  3. 特点:<br />![](https://cdn.nlark.com/yuque/0/2020/png/750131/1606885769824-3b84b2c1-e5ce-4545-814c-315a95949dd2.png#align=left&display=inline&height=232&margin=%5Bobject%20Object%5D&originHeight=232&originWidth=885&size=0&status=done&style=none&width=885)<br />AOF:这种方式可以将客户端执行的**写命令**记录到日志文件中,AOF持久化会将被执行的写命令写到AOF的文件末尾,以此来记录数据发生的变化,因此只需要redis从头到尾执行一次AOF文件所包含的所有写命令,就可以恢复AOF文件的记录的数据集
  4. 开启AOF持久化:在redis的默认配置中,AOF持久化机制是没有开启的,需要在配置中开启
  5. > 修改 redis.conf 开启AOF持久化:
  6. > - 开启持久化:appendonly yes
  7. > - 指定生成文件名称:appendfilename "appendonly.aof"
  8. > - 文件位置和快照位于同一位置:dir /var
  9. >
  10. 日志写入频率:
  11. > - appendfsync always:谨慎使用
  12. > - appendfsync everysec:推荐
  13. > - appendfsync no:不推荐
  14. 日志频率说明:<br />1、always:每个redis**写命令**都要同步写入硬盘,严重降低redis速度
  15. > - 优点:always选项会将每个redis写命令同步写入硬盘,能够将发生系统崩溃时出现的数据丢失减少到最少
  16. > - 缺点:这种同步策略需要对硬盘进行大量的写入操作,会受到硬盘性能的限制,转盘式硬盘在这种频率下200左右个命令/s,固态硬盘(SSD)几百万个命令/s【注意:在always这种不断写入少量数据的做法可能导致SSD产生严重的写入放大问题,从而降低SSD的使用寿命】
  17. 2、everysec:每秒执行一次同步显示的将多个写命令同步到磁盘【建议,性能影响小,数据丢失小】<br />3、no:由操作系统决定何时同步
  18. > - 优点:不会影响性能
  19. > - 缺点:
  20. > - 当系统崩溃时,丢失的数据不确定
  21. > - 当用户硬盘处理写入速度不够快时,当缓冲区被等待写入硬盘数据填满时,redis会处于阻塞状态,导致redis处理命令请求的速度变慢
  22. AOF 文件的重写:
  23. - AOF 带来的问题:持久化文件会变得庞大,如调用incr test 100次,文件中必须保存全部的100条命令,而需要恢复数据库保存一条 set test 100就够了,为了压缩 aof 的持久化文件,Redis 提供了AOF重写机制
  24. - AOF 重写:在一定程度上减小 AOF 文件的体积
  25. 触发 AOF 重写的方式:
  26. - 客户端命令:执行 BGREWRITEAOF 命令,不会阻塞redis服务
  27. - 服务端配置:配置 redis.conf 中的 auto-aof-rewrite-percentage 选项和 auto-aof-rewrite-min-size
  28. ```bash
  29. auto-aof-rewrite-percentage 100 # AOF文件增长率
  30. auto-aof-rewrite-min-size 64mb # AOF文件第一次触发重写的大小
  31. // 即第一次 64mb 重写,重写后假如为 30mb
  32. // 设置为100%,即第二次重写为 30*2=60mb时重写
  33. // 假设重写后为40mb,则第三次重写为80mb,以此类推...
  34. # 统计
  35. aof_current_size:AOF文件当前大小(单位:字节)
  36. aof_base_size:AOF文件上次启动和重写的大小(单位:字节)

上述配置,如果启用AOF持久化时,那么当AOF文件体积大于64mb且AOF文件的体积比上一次重写之后体积大了至少一倍(100%)时,会自动触发,如果重写过于频繁,那么用户可以考虑将auto-aof-rewrite-percentage设置更大

AOF 重写原理:重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写写了一个新的aof文件,替换了原有的文件,这点和快照类似

  • redis调用fork产生子进程,子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令
  • 父进程继续处理client请求,除了把写命令写入到原来的aof中,同时把收到的写命令缓存起来,这样就能保证如果子进程重写失败的话并不会出问题
  • 当子进程把快照内容以命令方式写到临时文件后,子进程发信号通知父进程,然后父进程把缓存的写命令也写入到临时文件
  • 现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加

redis 持久化 - 图4

AOF 完整配置:

  1. appendonly yes #开启aof
  2. appendfilename "appendonly-${port}.aof" #aof文件命名
  3. appendfsync everysec #日志频率
  4. dir /var/redis #日志文件保存位置
  5. no-appendfsync-on-rewrite yes #在重写时不调用fsync()操作,此时Redis的持久化策略相当于appendfsync none
  6. auto-aof-rewrite-percentage 100 #增长率
  7. auto-aof-rewrite-min-size 64mb #发生第一次重写的aof文件日志大小

AOF 修复:redis-check-aof —fix

其他设置:

  • aof-load-truncated:在Redis节点启动的时候,如果发现AOF文件已经损坏了,其处理逻辑与该参数的设置有关,若为yes,则会忽略掉错误,尽可能加载较多的数据,若为no,则会直接报错退出。默认为yes。需要注意的是,该参数只适用于Redis启动阶段,如果在Redis运行过程中,发现AOF文件corrupted,Redis会直接报错退出。
  • aof-use-rdb-preamble:是否启用Redis 4.x提供的AOF+RDB的混合持久化方案,若为yes,在重写AOF文件时,Redis会将数据以RDB的格式作为AOF文件的开始部分。在重写之后,Redis会继续以AOF格式持久化写入操作。默认值为no

总结

RDB 和 AOF 对比:

命令 RDB AOF
启动优先级
体积
恢复速度
数据安全性 丢数据 根据策略决定
轻重 重量级 轻量级

RDB 最佳策略:

  • 主从模式,主关从开
  • 集中管理

AOF 最佳策略:

  • 开:缓存和存储
  • AOF 重写集中管理
  • everysec

最佳策略:

  • 小分片
  • 缓存或者存储
  • 监控(硬盘、内存、负载)

优化:
image.png
硬盘优化:
image.png
AOF 追加阻塞:
image.png
AOF 阻塞定位:
image.png
image.png
image.png

两种持久化方案既可以同时使用(aof),又可以单独使用,在某种情况下也可以都不使用,具体用哪种持久化方案取决于用户的数据和应用;
无论使用AOF还是快照机制持久化,将数据持久化到硬盘都是很有必要的,除了持久化外,用户还应该对持久化的文件进行备份,最好备份在多个不同地方