Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

0%

# redis 的 rdb 和 COW 介绍

发表于 2021-08-15 分类于 redis 阅读次数： 阅读次数： Disqus：

redis 在使用 rdb 策略进行备份时，rdb 的意思是会在开启备份的时候将开启时间点的内存数据进行备份，并且可以设置时间，这样子就是这个策略其实还是不完全可靠的，如果是在这个间隔中宕机了，或者间隔过长，不过这个不在这次的要说的内容中，如果自己去写这个 rdb 的策略可能就有点类似于 mvcc 的 redolog，需要知道这个时间点之前的数据是怎么样的，防止后面更改的干扰，但是这样一方面需要有比较复杂的 mvcc 实现，另一方面是很占用存储空间，所以 redis 在这里面使用了 COW (Copy On Write) 技术，这个技术呢以前听过，也大致了解是怎么个意思，这次稍微具体地来看下，其实 redis 的 copy-on-write 就是来自于 linux 的 cow

### Linux中的CopyOnWrite

fork()之后，kernel把父进程中所有的内存页的权限都设为read-only，然后子进程的地址空间指向父进程。当父子进程都只读内存时，相安无事。当其中某个进程写内存时，CPU硬件检测到内存页是read-only的，于是触发页异常中断（page-fault），陷入kernel的一个中断例程。中断例程中，kernel就会把触发的异常的页复制一份，于是父子进程各自持有独立的一份。这个操作其实可以类比为写屏障，正常的读取是没问题的，当有写入时就会分裂。

### CopyOnWrite的好处：

1、减少分配和复制资源时带来的瞬时延迟；
2、减少不必要的资源分配；
CopyOnWrite的缺点：
1、如果父子进程都需要进行大量的写操作，会产生大量的分页错误（页异常中断page-fault）;

### Redis中的CopyOnWrite

Redis在持久化时，如果是采用BGSAVE命令或者BGREWRITEAOF的方式，那Redis会fork出一个子进程来读取数据，从而写到磁盘中。
总体来看，Redis还是读操作比较多。如果子进程存在期间，发生了大量的写操作，那可能就会出现很多的分页错误(页异常中断page-fault)，这样就得耗费不少性能在复制上。
而在rehash阶段上，写操作是无法避免的。所以Redis在fork出子进程之后，将负载因子阈值提高，尽量减少写操作，避免不必要的内存写入操作，最大限度地节约内存。这里其实更巧妙了，在细节上去优化会产生大量页异常中断的情况。