Redis 笔记
Redis 在生成 RDB 文件时如何处理请求?
RDB 产生自主线程发送的 bgsave 由fork出的子线程执行,主线程会将内存页表复制给子线程一份,子线程通过这个复制品来制作 RDB,写入磁盘,主线程仍然处理用户请求
生成 RDB 文件的时候如何保证一致性?
主线程在 fork 子线程的时候并不是去复制一份完整的内存数据给子线程,这样太浪费空间而且太慢,主线程会复制一份页表给子线程,子线程通过这个页表去遍历内存,还是共享一块内存
但是这样,主线程改,子线程读,还是会被污染,Redis 采用了写时复制技术,如果有写入操作,就复制一份当前内存页的副本出来,主线程在副本上更改,子线程去读旧的内存页,这样效率高,而且也能保证数据就是 fork 那一瞬间的数据,不会被后续操作污染
高峰期使用 RDB 有什么问题?如何优化?
- 首先 RDB 期间,主线程采用写时复制进行写入,极端情况下会造成内存翻倍占用
- 子线程需要将 RDB 文件写入磁盘,如果缓存数据集很大,写入磁盘的时间相当客观,坏情况数分钟不止,磁盘IO跑满,会影响其他的AOF 和其他业务
- fork 子线程的时候主线程也会阻塞,虽然是复制的内存页表,但是在数据量很大的情况下,内存页的大小也相当可观,阻塞时间可能得几十毫秒甚至上百毫秒,这个时候,主线程是不能去工作的
所以一般会去设置 RDB 的时间为低峰时段跑,或者用从节点跑RDB,不耽误主节点处理请求
fork 的时候为什么会阻塞主进程?不是说只复制页表吗?
复制页表也是需要时间的,fork 期间会被阻塞,Redis 使用虚拟内存,每个内存页通常有 4kb,如果一个有 20G 的实例去做 RDB,主线程需要去复制一个差不多几十MB的页表,差不多需要消耗100毫秒了
如果 RDB 生成到一半机器挂了怎么办?
挂了就挂了,并不会造成很大的损失,RDB 操作是先写一份临时的 RDB 文件,然后再由 rename 操作转正为 dump.rdb,rename 是原子性的,如果失败了,就还是去恢复上一次的 RDB 文件。
bgsave 和 save 有什么区别?生产上用哪个?
save 是同步操作,主线程去做备份,期间完全阻塞,bgsave 是交给子线程的,异步操作,生产要用 bgsave,主线程阻塞带来的服务关停是不可承受的
最后更新时间:2026/2/28