本文主要介绍了 Redis 持久化的两种机制:RDB 和 AOF,以及键过时的策略:惰性删除和按期删除,还有 RDB、AOF 和复制功能对过时键的处理。redis
RDB 是 Redis 持久化的第一种方式。有两个 Redis 命令能够用于生成 RDB 文件,一个是 SAVE,另外一个是 BGSAVE。
SAVE 会阻塞 Redis 服务器进程,执行时 Redis 服务器会阻塞全部客户端发送的命令。数据库
redis> SAVE OK
BGSAVE 会派生出一个子进程执行,执行时仍可继续处理客户端的命令,但会拒绝客户端 SAVE 和 BGSAVE 的命令,延迟 BGREWRITEAOF 命令。安全
redis> BGSAVE Background saving started
SAVE 命令会阻塞服务器,因此只能手动执行。BGSAVE 能够在不阻塞的状况下执行,因此能够配置 save 选项让服务器每隔一段时间自动执行一次。服务器
好比咱们能够向服务器提供如下配置:app
save 900 1 save 300 10 save 60 10000
那么只要知足如下三个条件中的任意一个便可被执行:async
为了实现这一功能,服务器会维持一个记录距离上次保存以后修改的次数的 dirty 计数器和一个记录上次保存时间的 lastsave 属性。ide
周期操做函数 serverCron 默认每一个 100 毫秒就会执行一次,它的其中一项工做就是检查 save 选项设置的条件是否知足,若是知足的话就会执行 BGSAVE 命令。函数
RDB 文件有多个部分,包括握手字段 ‘REDIS’ 字符串,版本号,数据库,’EOF’ 和校验字段。性能
核心部分是数据库字段,数据库字段包括了握手字段 ‘SELECTDB’,数据库编号和键值对,数据库编号指示了这是第几个数据库,而键值对则保存了各项数据。大数据
键值对中除了类型和数据,还可能会有过时时间。对于不一样类型的键值对,RDB 文件会用不一样的方式来保存它们。
RDB 文件自己是一个通过压缩的二进制文件,每次 SAVE 或者 BGSAVE 都会建立一个新的 RDB 文件,不支持追加操做。
AOF 是 Redis 持久化的第二种方式,在 AOF 和 RDB 同时开启时,服务器会优先考虑从 AOF 恢复数据,由于 AOF 每次记录间隔的时间更短。
和 RDB 直接记录键值对不一样,AOF 记录的是命令。服务器在执行完一个写命令之后,会把这条命令追加到服务器 aof_buf 缓冲区的末尾,并在一个适当的时候写入文件。重建时服务器会建立一个伪客户端,依次执行文件中的命令便可完成数据的载入。
AOF 的持久化发生在每次事件循环结束以前,会阻塞服务器。在持久化时会调用操做系统的 write 函数,但一般该函数会把数据保存在一个内存缓冲区里面而不是马上刷入磁盘。这就带来一个安全问题。为了不这个问题操做系统又提供了 fsync 和 fdatasync 两个强制刷盘的同步函数。咱们把 write 称为写入,把 fsync 和 fdatasync 称为同步。
服务器会在每次事件循环结束以前根据 appendfsync 选项写入和同步 aof_buf 中的数据:
随着服务器运行时间的流逝,AOF 文件中的内容会愈来愈多,文件的体积也会愈来愈大,不只会对宿主计算机形成影响,也拖慢了数据恢复所须要的时间。
AOF 重写是指从新生成一个 AOF 文件替换原来的 AOF 文件。但这里的重写不会对原有的文件进行读取、分析或者写入,而是把数据库中的键值对折算成命令,从新写入新的文件。
重写是一个耗时的操做,所以 Redis 把它放到后台去操做,对应的指令是 BGREWRITEAOF。在重写过程当中服务器还可能接收新的指令,所以 Redis 会维护一个 AOF 重写缓冲区,记录重写期间的写命令,在重写完成后追加到 AOF 文件末尾。
RDB 的优势:
RDB 的缺点:
AOF 的优势:
AOF 的缺点:
RDB 和 AOF 各有所长,RDB 体积小,恢复速度快,并且能够生成快照;AOF 频率更高,能够保存更新的数据。通常来讲,推荐同时使用。
Redis 采起的是惰性删除和按期删除配合使用的方式。
惰性删除是指 Redis 会在访问某个键的时候检查该键是否过时,若是过时,就会将输入键从数据库中删除。但惰性删除不能及时清理内存,所以 Redis 还有按期删除的机制。
按期删除是另外一种过时键删除方式。Redis 会维护一个过时字典(以下图所示),全部声明了过时时间的键都会被添加进这个字典中。周期操做函数 serverCron 执行时,会在规定时间内随机检查一部分键的过时时间,并删除其中的过时键。
RDB 文件在生成时会检查每一个键的过时时间,过时键不会被添加进 RDB 文件里。
载入 RDB 文件时,若是该服务器是主服务器,则不会载入文件中过时的键;若是该服务器是从服务器,则不论过时与否都会被载入。不过,由于主从服务器在同步的时候,从服务器的数据库会被清空,因此通常来说,过时键对载入 RDB 文件的从服务器不会形成影响。
AOF 文件写入时,若是数据库中的某个键已过时,但它还没被删除,那么 AOF 文件不会由于这个键产生任何影响。当它被惰性删除或者按期删除以后,程序会向 AOF 文件追加一条 DEL 命令显示记录该键已被删除。
AOF 重写时,和生成 RDB 文件同样,会过滤掉已通过期的键。
主服务器在删除一个过时键后,会显式地向全部从服务器发送一个 DEL 命令,告知从服务器删除这个过时键。
Redis 3.2 前,为了保持主从一致性,从服务器在执行客户端发送的读命令时,即便碰到过时键也不会将过时键删除,而是继续像处理未过时键同样处理过时键。从服务器只有在接到主服务器发来的 DEL 命令以后,才会删除过时键。Redis 3.2 后,从节点在读取数据时,增长了对数据是否过时的判断:若是该数据已过时,则不返回给客户端。