目录
大家好,我是jstart千语。redis作为缓存,既然是存数据的地方,肯定要考虑到数据的持久性。持久性通俗点来讲就是让数据存活地更久一点吧。那么趁热打铁,我们直接开始数据持久化的讲解。
思考
在开始之前,我们不妨先自己想一想,如何让数据存活的更久一点呢?其实归根结底就是一个问题,给数据续命。我们要考虑的就是,当数据出现意外已经没有了的时候,应该怎么复活他们呢?我们想要轻松地理解的话,就不要陷入教条般的定义里,可以从生活出发。想想我们常用的github仓库,其中一个功能不就是给我们的项目代码做备份吗,相当于一个影分身之术,一个挂了,另一个还在。还有,我们平时做笔记的时候,都是将一些功能的实现的流程写下来的吧,不会完完全全将一整个代码拷贝下来吧,如果是这样,复习的时候还不如直接看源代码呢。所以按照这个思路我们下次再实现这个功能的时候,不就是把流程再写一遍吗。这两种思路其实就是下面要将的RDB和AOF。
RDB
RDB就是一个数据备份文件,也称为Redis的数据快照。它就是把内存中的所有数据都记录下来到磁盘中,当redis故障时,直接从磁盘中读取快照文件,恢复数据。这就类似于我们将代码给github托管然后再下载下来的效果。
主动备份
在命令行中手动开启备份,实现方式有两种命令,都是切换到redis客户端后直接可执行的命令:一是save,二是bgsave。save命令是让redis的主进程来执行RDB,bgsave让子进程来执行RDB的。区别就是使用主进程时,会阻塞其他所有命令。使用子进程可以避免其他命令受到影响。
默认备份
redis内部本身就有一个出发RDB的机制,当满足某些条件时,自动使用bgsave命令执行RDB。可以打开redis的配置文件redis.conf文件中找到:满足下面注释的条件时,RDB就会自动执行。
save 900 1 # 当900秒内有1个key被修改时
save 300 10 # 当300秒内有10个key被修改时
save 60 10000 # 当60秒内有10000个key被修改时
RDB执行原理
用bgsave执行RDB,bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入RDB文件。
Linux中的物理内存:
首先要知道在Linux中,所有的进程都无法直接对物理内存(可理解为计算机的内存条)进行操作,但是redis就是想要将数据存到内存当中啊。怎么办呢?这时候页表就出现了。操作系统会给每个进程分配一个虚拟内存,操作系统去操作虚拟内存,操作系统会维护一个虚拟内存和物理内存的关系映射表,这个表就是页表。
Redis操作物理内存:
所以redis操作的流程是:主进程操作虚拟内存——>虚拟内存基于页表的映射关联到物理内存——>物理内存中存储数据——>实现对物理内存的读和写操作。
页表的作用:
回到bgsave,bgsave就是fork一个子进程(相当于复制),注意是进程不是线程。子进程会对主进程的页表复制。那页表都是从主进程复制过来的,子进程中也就可以通过页表的映射关系,通过虚拟内存操作操作物理内存啦。那么既然都可以读到物理内存中的数据了,是不是就可以将数据拿出来存储了,所以子进程就会将数据写入磁盘中生成新的RDB文件,替换旧的RDB文件,至此,完成备份。
注意点:凡是涉及到数据库读写问题都应该对“并发”敏感一点。具体来讲就是当子进程拷贝数据的时候,主进程如果往里面写数据那么可能会出现脏数据的情况。解决办法就是对共享数据添加一个“read-only”锁,不能往里面写数据。如果主进程redis要写数据时,会复制一份共享数据,然后主进程的读写都是对复制出来的那一份进行操作。
AOF
AOF备份的原理
redis数据持久化的第二章方案就是使用AOF,AOF是一种追加文件,里面记录的都是redis的写数据时的命令,当我们需要备份的时候,就把这些命令拿出来重写执行一遍就可以了。这种思路就是我们平常做笔记时,记录某个功能的实现流程。
AOF的相关配置
需要注意的是,AOF在redis中默认是关闭的,需要手动打开。通过redis的配置文件redis.conf开启AOF:
appendonly yes # 是否开启AOF功能,默认是no
appendfilename "appendonly.aof" # AOF文件的名称
AOF记录命令的频率也是可以通过配置文件来配置的:
# 每次执行写命令都记录到AOF中
appendfsync always
# 写命令先放入缓冲区,然后每隔一秒将缓冲区的数据写到AOF文件中,是默认方案
appendfsync everysec
# 写命令先放入缓冲区,由操作系统决定何时将缓冲区内容写回到磁盘
appendfsync no
各种不同频率记录策略的差异:项目中最常使用的是everysec
配置项 | 刷盘时机 | 优点 | 缺点 |
Always | 同步刷盘 | 可靠性高,不会丢失数据 | 性能影响大 |
everysec | 每秒刷盘 | 性能适中 | 最多丢失一秒数据 |
no | 操作系统控制 | 性能最好 | 可靠性差,可能会丢失大量数据 |
AOF的缺点
因为是记录命令,AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作 才有意义。
通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。可以通过配置文件redis.conf设置,什么情况下会出发重写:
# AOF文件比上次文件 增长超过多少百分比才触发,比如100%
auto-aof-rewrite-percentage 100
# AOF文件体积最小多大以上才触发重写,比如64mb
auto-aof-rewrite-min-size 64mb