Skip to content

1. AOF重写期间命令可能会写入两次,会造成什么影响?

为什么会写入两次?

  1. AOF重写线程:Redis在重写AOF文件时,会根据当前内存数据生成一个“精简版”AOF文件(比如只保存SET k v而不是每次INCR)。
  2. 命令缓冲:在重写期间,客户端还在持续发送新的写命令。为了避免数据丢失,这些命令:
    • 一边正常写入现有AOF文件(老AOF继续追加)
    • 一边被缓存在内存中,待AOF重写完成时,这些缓冲命令会追加到新AOF文件的末尾。

结果:这些命令在老AOF文件新AOF文件中都存在一次,相当于“写入了两次”,但对数据效果是幂等的

好处:但可以防止在 AOF 重写尚未完成时,Redis 发生崩溃,导致数据丢失。即使重写失败,旧的 AOF 文件仍然是完整的。


这种行为的影响

影响点说明
数据一致性没问题,Redis设计保证重放AOF时,重复命令也不会改变最终状态(幂等)
⚠️ 磁盘I/O重写期间,AOF同时重写+追加新命令,磁盘写入压力增大
⚠️ 内存占用命令缓冲区可能会消耗更多内存,尤其是高并发写入时
⚠️ 延迟抖动重写完成时,可能导致轻微延迟抖动,尤其在磁盘I/O瓶颈时

总结

AOF重写期间命令可能写入两次,这属于设计特性,对最终数据无害,但确实可能带来I/O压力上升、内存临时增长这些副作用。

如果你的系统写入量特别大,可以通过:

  • 调整 auto-aof-rewrite-min-sizeauto-aof-rewrite-percentage
  • 监控 aof_rewrite_buffer_length 和磁盘I/O 来减轻影响。

2. Redis 4.0 混合持久化机制

Redis原来有两种持久化方式:

  • RDB(快照式持久化):快速恢复,磁盘空间小,但有丢数据风险。
  • AOF(追加式持久化):数据几乎不丢,但写盘大且恢复慢。

问题:RDB快,但数据不够新;AOF新,但加载慢(需要重放大量命令)。

什么是混合持久化?

混合持久化 = RDB数据快照 + AOF增量命令 合并在一个 AOF 文件里。

流程是这样:

  • 当Redis触发AOF重写时(或第一次启动开启AOF时):
    1. 先将RDB格式的内存快照写到新的AOF文件开头
    2. 然后把最近的写命令(从开始重写到现在)追加到后面

最终的新AOF文件长这样:

plain
sql


复制编辑
|   RDB格式的数据   |  后续的AOF增量命令(如SET, INCR, RPUSH等)  |

而不是全是RDB,也不是全是AOF指令。


带来了什么好处?

优点说明
加载速度更快启动时只需要恢复一次RDB + 少量命令,比传统AOF(可能重放几千万条命令)快很多。
文件大小更合理RDB压缩比好,前段占用小。增量命令也不会太大。
数据新鲜度高因为后面有最近的增量命令,比纯RDB更接近真实状态。

有没有缺点?

缺点说明
⚠️ 格式更复杂一个AOF文件中包含了两种不同格式(RDB + AOF),需要Redis内部特殊处理。
⚠️ 兼容性老版本Redis(4.0以下)无法直接识别这种混合AOF文件。
⚠️ 磁盘占用在极端写入高峰下,混合文件大小仍可能膨胀,需要定期重写。