本文主要介绍了 Redis 持久化的两种机制:RDB 和 AOF,以及键过期的策略:惰性删除和定期删除,还有 RDB、AOF 和复制功能对过期键的处理。
RDB 是 Redis 持久化的第一种方式。有两个 Redis 命令可以用于生成 RDB 文件,一个是 SAVE,另一个是 BGSAVE。
SAVE 会阻塞 Redis 服务器进程,执行时 Redis 服务器会阻塞所有客户端发送的命令。
redis> SAVE
OK
BGSAVE 会派生出一个子进程执行,执行时仍可继续处理客户端的命令,但会拒绝客户端 SAVE 和 BGSAVE 的命令,延迟 BGREWRITEAOF 命令。
redis> BGSAVE
Background saving started
SAVE 命令会阻塞服务器,所以只能手动执行。BGSAVE 可以在不阻塞的情况下执行,所以可以配置 save 选项让服务器每隔一段时间自动执行一次。
比如我们可以向服务器提供以下配置:
save 900 1
save 300 10
save 60 10000
那么只要满足以下三个条件中的任意一个即可被执行:
为了实现这一功能,服务器会维持一个记录距离上次保存之后修改的次数的 dirty 计数器和一个记录上次保存时间的 lastsave 属性。
周期操作函数 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 后,从节点在读取数据时,增加了对数据是否过期的判断:如果该数据已过期,则不返回给客户端。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。