文章图片
Redis 作为一种非常流行的内存数据库 , 通过将数据保存在内存中 , Redis 得以拥有极高的读写性能 。 但是一旦进程退出 , Redis 的数据就会全部丢失 。
为了解决这个问题 , Redis 提供了 RDB 和 AOF 两种持久化方案 , 将内存中的数据保存到磁盘中 , 避免数据丢失 。 本文将重点讨论AOF持久化方案 , 以及其存在的一些问题 , 并探讨在Redis 7.0 (已发布RC1) 中Multi Part AOF(下文简称为MP-AOF , 本特性由阿里云数据库Tair团队贡献)设计和实现细节 。
AOF AOF( append only file )持久化以独立日志文件的方式记录每条写命令 , 并在 Redis 启动时回放 AOF 文件中的命令以达到恢复数据的目的 。
由于AOF会以追加的方式记录每一条redis的写命令 , 因此随着Redis处理的写命令增多 , AOF文件也会变得越来越大 , 命令回放的时间也会增多 , 为了解决这个问题 , Redis引入了AOF rewrite机制(下文称之为AOFRW) 。 AOFRW会移除AOF中冗余的写命令 , 以等效的方式重写、生成一个新的AOF文件 , 来达到减少AOF文件大小的目的 。
AOFRW 图1展示的是AOFRW的实现原理 。 当AOFRW被触发执行时 , Redis首先会fork一个子进程进行后台重写操作 , 该操作会将执行fork那一刻Redis的数据快照全部重写到一个名为temp-rewriteaof-bg-pid.aof的临时AOF文件中 。
由于重写操作为子进程后台执行 , 主进程在AOF重写期间依然可以正常响应用户命令 。 因此 , 为了让子进程最终也能获取重写期间主进程产生的增量变化 , 主进程除了会将执行的写命令写入aof_buf , 还会写一份到aof_rewrite_buf中进行缓存 。 在子进程重写的后期阶段 , 主进程会将aof_rewrite_buf中累积的数据使用pipe发送给子进程 , 子进程会将这些数据追加到临时AOF文件中(详细原理可参考这里) 。
当主进程承接了较大的写入流量时 , aof_rewrite_buf中可能会堆积非常多的数据 , 导致在重写期间子进程无法将aof_rewrite_buf中的数据全部消费完 。 此时 , aof_rewrite_buf剩余的数据将在重写结束时由主进程进行处理 。
当子进程完成重写操作并退出后 , 主进程会在backgroundRewriteDoneHandler 中处理后续的事情 。 首先 , 将重写期间aof_rewrite_buf中未消费完的数据追加到临时AOF文件中 。 其次 , 当一切准备就绪时 , Redis会使用rename 操作将临时AOF文件原子的重命名为server.aof_filename , 此时原来的AOF文件会被覆盖 。 至此 , 整个AOFRW流程结束 。
图1 AOFRW实现原理
AOFRW存在的问题 内存开销
由图1可以看到 , 在AOFRW期间 , 主进程会将fork之后的数据变化写进aof_rewrite_buf中 , aof_rewrite_buf和aof_buf中的内容绝大部分都是重复的 , 因此这将带来额外的内存冗余开销 。
在Redis INFO中的aof_rewrite_buffer_length字段可以看到当前时刻aof_rewrite_buf占用的内存大小 。 如下面显示的 , 在高写入流量下aof_rewrite_buffer_length几乎和aof_buffer_length占用了同样大的内存空间 , 几乎浪费了一倍的内存 。
aof_pending_rewrite:0aof_buffer_length:35500aof_rewrite_buffer_length:34000aof_pending_bio_fsync:0 当aof_rewrite_buf占用的内存大小超过一定阈值时 , 我们将在Redis日志中看到如下信息 。 可以看到 , aof_rewrite_buf占用了100MB的内存空间且主进程和子进程之间传输了2135MB的数据(子进程在通过pipe读取这些数据时也会有内部读buffer的内存开销) 。 对于内存型数据库Redis而言 , 这是一笔不小的开销 。
3351:M 25 Jan 2022 09:55:39.655 * Background append only file rewriting started by pid 68173351:M 25 Jan 2022 09:57:51.864 * AOF rewrite child asks to stop sending diffs.6817:C 25 Jan 2022 09:57:51.864 * Parent agreed to stop sending diffs. Finalizing AOF...6817:C 25 Jan 2022 09:57:51.864 * Concatenating 2135.60 MB of AOF diff received from parent.3351:M 25 Jan 2022 09:57:56.545 * Background AOF buffer size: 100 MB AOFRW带来的内存开销有可能导致Redis内存突然达到maxmemory限制 , 从而影响正常命令的写入 , 甚至会触发操作系统限制被OOM Killer杀死 , 导致Redis不可服务 。
- CPU|100多元的10核处理器怎么组?以及X79小科普
- CPU|情人节立减200,Reno7 Pro再迎最佳入手时机,女友很吃这一套
- CPU|国产处理器新机发布,720p分辨率屏幕支持高刷新,1230元起售!
- 联想|联想旗舰轻薄本用上兆芯x86 CPU:16nm 4核心、频率很特殊
- CPU|成功!vivo S12 Pro挑战专业摄影团队,照片质量一绝
- CPU|Intel要推CPU氪金:花钱解锁额外功能、Linux内核率先支持
- CPU|iPhone SE2:对不起,是时候该说再见了!
- 字节跳动|OPPO亮利刃:7.02英寸超级屏+6050mAh,看完后很满意
- CPU|配置i5-12400F处理器,2GB独显,攀升商睿2代电脑售价3899元
- CPU|商用本处理器选AMD还是英特尔?10项实际应用测试大比拼