从零开始学Redis(3) -- 持久化:如何选择RDB和AOF

因为redis是基于内存保存数据,如果宕机,就会丢失数据。

因此redis提供了两种持久化机制

  1. RDB,基于快照
  2. AOF,基于日志

什么是RDB

RDB -- redis会将数据集的快照dump到dump.rdb文件,做一个全量备份用于恢复。

Redis如何一边响应请求,一边持久化?

我们知道redis是基于单线程多路复用,因此我们不能同时进行内存快照以及响应请求。

而redis因此在持久化时会fork一个子进程,持久化完全由子进程处理,父进程继续处理客户端请求。

子进程只会对数据结构遍历读取然后序列化到磁盘中,但是父进程会持续修改内存数据结构。

因此redis使用了操作系统的COW(copy on write)机制进行数据段page的共享读写。

它把所有数据按每4k一个page来分割,然后子进程就对每一个page去读取然后序列号写到磁盘,而父进程就响应请求,当出现数据改变时,就将对应的page复制一份分离出来然后修改。当然随着修改增多,page会越来越多,内存也会增长,但是worst case只是原有数据内存的两倍;同时redis作为一个缓存,冷数据比例比较高,因此基本上是小部分页面被复制分离。如下图。

RDB的优点:

dump.rdb是个二进制文件,使用RDB恢复非常快

RDB的缺点:

1.dump的时候比较耗费资源

2.只使用RDB恢复的话,基本上会丢失大量数据,因为我们不可能每时每刻都dump备份下来。

什么是AOF 

AOF就是redis存储顺序指令序列的log,只记录了内存修改的指令记录。

因此我们可以通过执行aof文件来进行指令重放,以此来恢复数据。

PS:和mysql等数据库不同,redis是先执行了指令,然后再写log(可能是因为和mysql等不同,redis只有执行了这个命令才知道这个命令是否有效)。

突然宕机,AOF日志还没写到磁盘怎么办?

实际上程序对AOF日志写操作时,就是将内容写到kernel为fd分配的一个内存缓存,然后kernel会自动异步将数据刷回磁盘。所以突然宕机,可能日志还没刷到磁盘。怎么办?

linux有个fsync函数,可以强制把fd对应的内容从内核缓存刷到磁盘。但是fsync是个磁盘IO操作,所以会很慢。

所以redis一般会每隔1s执行一次fsync去刷到磁盘。

AOF的优点:

基本上不会数据丢失或很少 

AOF的缺点:

1.恢复时是执行日志重放,所以如果日志比较长,就会比较慢。。。

2.fsync是个耗时的IO操作,会增加系统IO负担

混合持久化

没错,大人选择全都要。。

我们选择redis提供的混合持久化模式,rdb快照和增量aof日志同时保存。这里的aof日志就不是全量日志,而是从持久化开始到持久化结束的增量AOF日志,因此这部分AOF日志会很小。

当我们重启redis时,先加载rdb内容,然后再重放增量AOF文件,以此提高效率。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值