Redis作为内存键值对数据库,特性之一就是持久化机制。参考关系型数据库(Mysql)的持久化机制,你可以想到他们肯定都是采用类似日志的形式记录数据修改变动,然后系统宕机时,通过重做日志的形式恢复数据。
在Redis的设计哲学中,一切的可靠性 *** 作应尽可能少地侵入redis的设计出发点——快。也就是说,持久化机制应尽可能少地侵入redis主进程能力,这一点也是整个redis学习过程中都应该考虑到的。
Redis主要提供了两种持久化机制:
1,RDB持久化RDB(Redis DataBase),即快照持久化,通过快照的方式将数据dump入一个dump.rdb
文件中,文件中存储的是二进制数据,,紧凑型压缩。这样恢复数据只是版本切换的问题了,速度较快。也是redis的默认持久化方式。
RDB流程:主进程通过fork一个子进程来实现快照工作,fork的方式避免了主进程的阻塞。
快照期间,通过写时复制(Copy-On-Write,COW)技术,使得frok期间主进程仍然可以接受写入 *** 作。也就是说,写时复制使得子进程能够感知到主进程中的数据变化,对于修改的数据,子进程会先写入该数据副本,然后主进程仍然可以对数据修改。
快照机制:第一次快照是全量快照机制,会快照内存中的所有数据,然后后面就采用增量快照的机制,只需要对两次快照期间变动的数据做快照即可。这也就意味着需要记录下来变动的数据,如果变动的数据较多,这个记录文件势必就会过大,这对内存资源珍贵的redis来说必然会有影响。为此,redis提供了解决机制,我们后面讲到。
快照频率:快照有手动触发快照和自动触发两种形式:
- save:在主进程中快照,会阻塞主进程;
- bgsava:后台异步快照,此时仍然可以响应客户端请求。
配置文件的形式:save second changes:每秒内至少有多少个key发生变化触发。
2,AOF持久化AOF(Append Of File),redis主进程写入命令后,再将 *** 作记录写入aof文件中,可以看到这里aof记录的是 *** 作命令,可读性来说比较友好。不同于mysql日志的写前日志(Write Ahead Log,WAL),aof是写后日志。这样设计的原因:(但是,这样就会有丢失数据的风险)
- 写入日志的都是执行成功的命令,确保没有记录错误命令的情况;
- 避免当前写入的阻塞
由于追加写的原因和可靠性机制,aof文件是需要落盘的。落盘策略,由appendfsync 控制:
当aof文件过大时,就会触发重写机制,通过bgrewriteaof触发,默认是64MB,下次触发时是当原来文件重写后的2倍。
重写流程:(一次拷贝两次重写)
- 主线程fork一个子进程实行重写;
- 重写期间,主进程会将当前 *** 作同时写入到aof缓存区和aof重写缓存区,以保证重写期间aof文件的完整性以及新的数据修改不会丢失;
- 子进程写完后会通知主进程,然后主进程把aof重写缓存区数据写入新的aof文件
- 新的AOF文件覆盖旧的AOF文件,完成AOF重写。
可能的阻塞:
- fork时,主进程内存越大,阻塞越长。
- 主线程有写入时,会阻塞。
redis4.0之后提供了第三种机制,即RDB-AOF混合的方式。我们之前讲到,RDB在增量复制的时候需要记录文件修改 *** 作,当修改变动大时时很不可取的。这时,我们可以使用AOF文件记录增量间隙之间的修改,然后下次做全量快照的时候,可以重做AOF日志,然后清空AOF就好了。
3,总结适用场景:
RDB:恢复速度快,数据丢失较高;
AOF:丢失率低,存储占用多,恢复速度慢;
RDB-AOF:推荐选择
4,其他fork原理:fork的理解,是一种复制,复制映射关系而非物理内存,fork时,主进程内存越大,阻塞越长。
写时复制:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)