记录一下 redis aof rdb file 非常大

原因

kafka连接有问题,修复这个问题后,巨量数据涌入redis,rdb和aof文件飙到48G

背景

redis 持久化

RDB snapshots of your dataset at specified intervals

  • 适合备份还原

  • RDB 允许更快地重新启动大数据集,与 AOF 相比

  • 可能会丢最新的数据,在不正常停止工作的情况下

  • 需要经常 fork() 才能使用子进程持久保存在磁盘上。如果数据集很大,fork() 可能会非常耗时,并且如果数据集很大并且 CPU 性能不是很好,可能会导致 Redis 停止为客户端提供服务几毫秒甚至一秒。 AOF 还需要 fork() 但频率较低,您可以调整重写日志的频率,而无需牺牲持久性。

AOF

  • 您可以有不同的 fsync 策略:根本不进行 fsync每秒进行 fsync每次查询时进行 fsync。采用每秒fsync的默认策略,写入性能仍然很棒。 fsync 是使用后台线程执行的,当没有 fsync 正在进行时,主线程将努力执行写入,因此您只能丢失一秒钟的写入。
  • AOF 日志是仅追加日志,因此不会出现查找问题,并且在断电时也不会出现损坏问题。即使由于某种原因(磁盘已满或其他原因)日志以半写命令结束,redis-check-aof 工具也能够轻松修复它。
  • 当 AOF 太大时,Redis 能够在后台自动重写 AOF。重写是完全安全的,因为当 Redis 继续追加到旧文件时,会使用创建当前数据集所需的最少操作集生成一个全新的文件,一旦第二个文件准备就绪,Redis 就会切换这两个文件并开始追加到新的那一个。
  • 对于相同的数据集,AOF 文件通常比等效的 RDB 文件大。

  • AOF 可能比 RDB 慢,具体取决于确切的 fsync 策略。
  • played again at server startup
  • reconstructing the original dataset
  • able to rewrite the log in the background when it gets too big

从现在开始,每次 Redis 收到更改数据集的命令(例如SET)时,它都会将其追加到 AOF 中。当您重新启动 Redis 时,它将重新播放 AOF 以重建状态。

从Redis 7.0.0开始,Redis使用多部分AOF机制。即把原来的单个AOF文件拆分为基础文件(最多一个)和增量文件(可能不止一个)。基础文件表示重写 AOF 时存在的数据的初始(RDB 或 AOF 格式)快照。增量文件包含自上次创建基本 AOF 文件以来的增量更改。所有这些文件都放在单独的目录中,并由清单文件跟踪。

image-20210321122017740

image-20210321122104459

错误分析

强制关闭Redis快照导致不能持久化

1
MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error

强制关闭Redis快照导致不能持久化,该方法只能忽略错误

1
config set stop-writes-on-bgsave-error no

AOF fsync 时间太长

具体要看redis日志

1
Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.
  • 磁盘速度慢
  • 短的时间内写入了太多数据
  • 内存不足

LOADING Redis is loading the dataset in memory

输入任何的命令都报这个,aof文件太大导致起来很慢

image-20210313135100731

  • 查看某个key序列化后的长度debug object myhash 计算serializedlength的代价相对高。所以如果要统计的key比较多,就不适合这种方法

连接上redis后执行如下命令 serializedlength(将key保存为rdb文件时使用了该算法)

1
2
3
4
b.redis:1959> hmset myhash k1 v1 k2 v2 k3 v3
OK
b.redis:1959> debug object myhash
Value at:0x7f005c6920a0 refcount:1 encoding:ziplist serializedlength:36 lru:3341677 lru_seconds_idle:2
  • 查看正在写的内容 MONITOR
  • 等redis加载完aof

BGSAVE 和 BGREWRITEAOF

BGSAVE

  • 通常,立即返回OK。后台跑save(持久化到硬盘),不会阻塞客户端服务
  • error 已经有BGSAVE/非后台保存的操作(AOF rewrite)在跑,

默认情况下,Redis 将数据集的快照保存在磁盘上一个名为dump.rdb.如果数据集中至少有 M 个更改,您可以将 Redis 配置为每 N 秒保存一次数据集,或者您可以手动调用SAVEBGSAVE命令。

例如,如果至少有 1000 个键发生更改,此配置将使 Redis 每 60 秒自动将数据集转储到磁盘:

1
save 60 1000

这种策略称为快照

每当 Redis 需要将数据集转储到磁盘时,就会发生以下情况:

  • Redis分叉。我们现在有一个子进程和一个父进程。
  • 子进程开始将数据集写入临时 RDB 文件。
  • 当子进程写完新的 RDB 文件后,它会替换旧的 RDB 文件。

此方法允许 Redis 从写时复制语义中受益。

BGREWRITEAOF

可以缩小aof文件,还没有后台进程进行持久化重写,才会由Redis触发

能够在后台重建 AOF,而不会中断对客户端的服务。每当您发出 时BGREWRITEAOF,Redis 都会写入在内存中重建当前数据集所需的最短命令序列

从Redis 7.0.0开始,当计划进行AOF重写时,Redis父进程会打开一个新的增量AOF文件来继续写入。子进程执行重写逻辑并生成新的基础 AOF。 Redis将使用临时清单文件来跟踪新生成的基础文件和增量文件。当它们准备好时,Redis将执行原子替换操作以使这个临时清单文件生效。为了避免 AOF 重写重复失败和重试时创建大量增量文件的问题,Redis 引入了 AOF 重写限制机制,以确保失败的 AOF 重写以越来越慢的速度重试。