Redis 的数据都在内存里,如果突然宕机,数据就会全部丢失,因此必须有一种机制来保证redis的数据不会因为故障而丢失,这种机制就是redis的持久化机制。
redis的持久化机制有两种,一种是快照,另一种是AOF日志。
快照是一次全量备份,AOF日志是连续的增量备份。
快照是内存数据的二进制序列化形式,存储上非常紧凑
AOF日志记录的是内存数据修改的指令记录文本。AOF日志在长期的运行过程中会变得无比庞大,数据库重启时需要加载AOF日志进行指令重放,所以需要定期进行AOF重写,给AOF日志进行瘦身。
快照的原理 :
为了不阻塞线上的业务,Redis就需要一遍持久化,一遍响应客户端的请求,持久化的同时内存数据结构还在改变,比如一个大型的hash字典正在持久化,结果一个请求过来把他给删除了,可是他还没有持久化完呢,所以只能redis使用操作系统的多进程Copy on write机制来实现快照持久化。
Redis在持久化时会调用参数fork产生一个子进程,快照持久化完全交给子进程来进行处理,父进程继续处理客户端请求。
子进程做数据持久化,不会修改现有内存的数据结构,他只是对数据结构进行遍历读取,然后序列化写到磁盘中。但是父进程不一样,他必须持续服务客户端请求,然后对内存数据结构进行不间断的修改。
这个时候就会使用操作系统的COW机制来进行数据段页面的分离。当父进程对其中一个页面的数据进行修改时,会将被共享的页面复制一份分离出来,然后对这个复制的页面进行修改。这时子进程对应的页面没有变化,还是进程产生时那一瞬间的数据。
AOF原理:
AOF日志存储的是redis服务器的顺序指令序列,AOF日志只记录对内存进行修改的指令记录。
随着时间的推移,AOF日志会越来越大,进行瘦身的几种办法。
AOF重写:开辟一个子进程对内存进行遍历,序列化到一个新的AOF日志文件中,
fsync:AOF日志是以文件的形式存在的,当程序对AOF日志进行写操作时,实际上是将内容写到了内存缓存中,然后内核会异步将数据刷回到磁盘的,这个时候如果机器宕机,AOF日志还没来得及刷新到磁盘上,会出现日志丢失。这个时候调用fsync函数强制刷到磁盘,就会保证AOF日志不丢失。生产环境通常每隔一秒就要fsync一次。
所以通常redis的主节点不会进行持久化操作,持久化操作主要在从节点进行,没有来自客户端请求的压力。
重启Redis时,很少使用rdb来恢复内存状态,因为会丢失大量数据。我们通常使用AOF日志重放,但是日志重放又会慢很多。Redis4.0为了解决这个问题,带来一个新的选项-混合持久化。将rdb文件的内容和增量的AOF日志文件存在一起,这里的AOF日志不是全量日志,是从持久化开始到持久化结束的发生的增量AOF日志。