简介

Redis 是使用非常广泛的 Key-Value 内存数据库。因为数据都存放在内存中,所以存取速度非常快。不过,很多情况下我们需要将 Redis 中的数据保存到硬盘中以便做备份。Redis 提供了两种数据持久化方式,分别是 RDB 和 AOP,本文分析这两种方式的使用以及过期键对持久化的影响。

RDB

RDB 指的是将 Redis 数据库在某个时间点的快照保存到磁盘,所生成的 RDB 文件是一个经过压缩的二进制文件,通过这个文件可以还原出 Redis 的数据状态。

创建快照的方式有以下几种:

  • 客户端向 Redis 发送 BGSAVE 命令,Redis 会调用 fork 创建一个子进程,然后子进程负责将快照写入硬盘,而父进程继续处理命令请求。
  • 客户端向 Redis 发送 SAVE 命令,此时 Redis 将开始创建快照,并且在完成之前不再响应其它命令。
  • 用户设置 save 配置选项,比如 save 60 10000,那么从 Redis 最近一次创建快照算起,当 “60 秒内有 10000 次写入” 这个条件被满足时, Redis 就会自动触发 BGSAVE 命令。如果用户设置了多个 save 配置选项,那么当任意一个 save 配置满足时,Redis 就会触发一次 BGSAVE 命令。save 配置的格式如下所示:

save 60 10000
stop-writes-on-bgsave-error no
rdbcompression yes // 使用压缩
dbfilename dump.rdb // RBD 文件的名字 dir ./
  • 当 Redis 通过 SHUTDOWN 命令接收到关闭服务器的请求时,或者接收到 TERM命令时,会执行一个 SAVE 命令,并且阻塞所有的客户端,不再执行任何请求。在 SAVE 命令执行结束后关闭服务器。
  • 当一个 Redis 服务器连接另一个 Redis 服务器,并向对方发送 SYNC 命令来开始一次复制操作的时候,如果主服务器没有在执行 BGSAVE 操作,或者主服务器并非刚执行完 BGSAVE,那么主服务器会执行 BGSAVE 命令。

RDB 的主要问题是,如果系统发生崩溃,那么最近一次执行完快照后修改的数据将被丢失。因此,RDB 适合用于即使丢失一部分数据也不会造成影响的应用程序。

AOF

AOF 指的是将所有执行的写命令写到 AOF 文件的末尾,以此来记录数据发生的变化。如果 Redis 想要恢复 AOF 中的数据,只要重新执行一次 AOF 文件中所包含的写命令就可以。

AOF 的配置如下所示:


appendonly yes // 打开 aof
appendfsync everysec // aof 同步的频率
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100 // 文件大小增长比超过这个值开始自动重写 aof
auto-aof-rewrite-min-size 64mb // 文件大小超过这个值才可以有可能自动重写 aof

上面的配置中,appendfsync everysec 设置的是同步的频率。应用程序在向硬盘写入数据的时候有 3 个步骤:

  1. 调用 file.write() 向文件写入,此时需要写入的内容被存储到了缓冲区,并不是真正写到硬盘上了。
  2. 操作系统在某个时候将缓冲区的内容写入硬盘,这时数据才真正被持久化了。

操作系统使用以上的文件写入方式是为了提高性能,毕竟硬盘 I/O 操作是比较耗时的。但是,这种方式的缺点在于如果机器崩溃了那么缓冲区的内容将丢失。程序可以使用 file.flush() 来请求操作系统尽快地将缓冲区的内容刷新到硬盘上,不过何时开始执行仍然由操作系统决定。程序也可以命令操作系统将文件同步 ( sync ) 到硬盘,同步操作会阻塞应用程序直到数据被写入硬盘。当同步操作完成后,即使系统出现故障,也不会对被同步的文件造成影响。

对于 Redis 来讲,可以指定 appendfsync 以何种方式让数据完全同步到硬盘,这个配置有 3 个选项:

  1. always: 每个 Redis 写命令都立即同步到硬盘,这是比较消耗性能的
  2. everysec: 每秒执行一次同步,兼顾性能与数据安全,是比较常用的选项
  3. no: 让操作系统决定何时进行同步

always 可以使得在 Redis 发生崩溃时丢失的数据最少,但是也是最消耗性能的,导致 Redis 的处理速度变慢。ererysec 是一种兼顾性能与数据安全的方式,在这种情况下,如果系统崩溃,用户最多会丢失一秒内的数据。no 选项完全将同步交给操作系统被决定,性能也不比 everysec 高多少,是不推荐的方式。

AOF 的缺点是随着 Redis 的不断运行,AOF 文件可能会非常大,甚至用完硬盘的空间。解决这个问题的办法是 AOF 重写。

重写

客户端可以发送 BGREWRITEAOF 命令让 Redis 重写 AOF 文件,Redis 会移除冗余的 AOF 命令进行重写,使得 AOF 文件的体积尽可能地小。

除了客户端主动发送 BGREWRITEAOF 命令,也可以使用配置让 Redis 在满足一定条件地情况下自动开始重写 AOF 文件。例如上一小节设置了 auto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mb。这两个配置的含义是,如果 AOF 文件大于 64MB 并且比上一次重写之后的大小增加了一倍的时候,Redis 将执行 BGREWERITEAOF 命令。

过期键删除

用户往往为 Redis 中的键设定过期时间,因此需要一定的策略来删除过期键,可以有三种策略:

  1. 定时删除,即通过定时器在过期时间到达的时候删除过期的键。这种方式的优点是节省内存,不会因为大量的过期键占用内存资源,而缺点则是消耗 CPU 资源,尤其是过期键数量较多的时候,删除操作消耗太长时间,降低了 Redis 的响应时间。
  2. 惰性删除,即在每次获取某个键的时候判断是否过期,如果未过期,则正常返回其值,否则删除这个键,返回空。这种方式的优点是节省 CPU 资源,但是消耗了内存。尤其是过期键数量较多的时候,大量内存被无效的键占用,相当于内存泄露。
  3. 定期删除,即每隔一段时间周期对数据库中的键进行扫描,但是只扫描其中一部分,力求在内存和 CPU 之间达到一个平衡。

从上面 3 种策略可以看出,单用第一个肯定是不行的,Redis 的响应时间至关重要。第二个则是比较好的方式,在获取键的时候判断是否过期并决定是否删除,它的缺点是很多键无法及时删除。如果一个过期键再也没有被访问,那么它将永远留在内存中,而第三种方式正好可以弥补。

Redis 中过期键的删除策略正是惰性删除与定期删除的结合。

过期键与持久化

了解了过期键的删除策略后,下面看下键的过期时间对持久化的影响。

在生成 RDB 文件的过程中,如果一个键已经过期,那么其不会被保存到 RDB 文件中。在载入 RDB 的时候,要分两种情况:

  1. 如果 Redis 以主服务器的模式运行,那么会对 RDB 中的键进行时间检查,过期的键不会被恢复到 Redis 中。
  2. 如果 Redis 以从服务器的模式运行,那么 RDB 中所有的键都会被载入,忽略时间检查。在从服务器与主服务器进行数据同步的时候,从服务器的数据会先被清空,所以载入过期键不会有问题。

对于 AOF 来说,如果一个键过期了,那么不会立刻对 AOF 文件造成影响。因为 Redis 使用的是惰性删除和定期删除,只有这个键被删除了,才会往 AOF 文件中追加一条 DEL 命令。在重写 AOF 的过程中,程序会检查数据库中的键,已经过期的键不会被保存到 AOF 文件中。

在运行过程中,对于主从复制的 Redis,主服务器和从服务器对于过期键的处理也不相同:

  1. 对于主服务器,一个过期的键被删除了后,会向从服务器发送 DEL 命令,通知从服务器删除对应的键
  2. 从服务器接收到读取一个键的命令时,即使这个键已经过期,也不会删除,而是照常处理这个命令。
  3. 从服务器接收到主服务器的 DEL 命令后,才会删除对应的过期键。

这么做的主要目的是保证数据一致性,所以当一个过期键存在于主服务器时,也必然存在于从服务器。

总结

本文对 Redis 的两种持久化方式进行了简要的梳理,分析了 Redis 删除过期键的策略以及对持久化的影响。理解了这部分内容不仅可以让我们对 Redis 的使用更加得心应手,对于学习 Redis 的其它内容如复制的过程也会很有帮助。

参考

  • 《Redis 实战》
  • 《Redis 设计与实现》

如果我的文章对您有帮助,不妨点个赞支持一下(^_^)

来源:https://segmentfault.com/a/1190000017526315

Redis 的持久化与过期键的更多相关文章

  1. redis中key的过期键删除策略

    Redis过期键删除策略 Redis key过期的方式有三种: 被动删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key 主动删除:由于惰性删除策略无法保证冷数据被及时删 ...

  2. redis的3种过期键删除策略

    Redis的过期键的过期时间都保存在过期字典中,过期键的删除策略有三种,分别是定时删除.惰性删除和定期删除. 定时删除 定时删除策略,是指在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时 ...

  3. redis学习笔记——RDB、AOF和复制时对过期键的处理

    AOF.RDB和复制功能对过期键的处理 生成RDB文件 在执行SAVE命令或者BGSAVE命令创建一个新的RDB文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到新创建的RDB文件中.举个例 ...

  4. Redis基本数据类型、数据持久化、过期策略及淘汰机制

    一点技术.技术乐享!!! 如果有人问你:Redis这么快,他的“多线程模式”你了解吗? 请回答他:您是想问Redis这么快,为什么还是单线程模式吗? redis是什么 简单来说redis是C语言开发的 ...

  5. Redis系列(五):Redis的过期键删除策略

    本篇博客是Redis系列的第5篇,主要讲解下Redis的过期键删除策略. 本系列的前4篇可以点击以下链接查看: Redis系列(一):Redis简介及环境安装 Redis系列(二):Redis的5种数 ...

  6. redis过期键的策略

    一.过期时间设置: 127.0.0.1:6379> expire key seconds //设置键的过期时间为多少秒 127.0.0.1:6379> setex key seconds ...

  7. 【Redis】过期键删除策略和内存淘汰策略

    Redis 过期键策略和内存淘汰策略 目录 Redis 过期键策略和内存淘汰策略 设置Redis键过期时间 Redis过期时间的判定 过期键删除策略 定时删除 惰性删除 定期删除 Redis过期删除策 ...

  8. 你应该知道的Redis过期键和过期策略

    今天,我和大家分享一篇关于 Redis 有关过期键的内容,主要有四个内容: 如何设置过期键 如何取消设置的过期时间 过期键的过期策略是怎样的 RDB.AOF 和复制对过期键的处理又是怎样的 设置键的生 ...

  9. Redis 过期键删除策略

    Redis 中数据库键的过期时间都保存在过期字典中,当一个键过期了,Redis 存在三种不同的删除策略:定时删除.惰性删除和定期删除 定时删除 定义 在设置键的过期时间的同时创建一个计时器,让定时器在 ...

随机推荐

  1. VS2010中打开VS2012项目的方法

    VS2012中对C#的支持度非常好,不管是编写方便程度(不需要插件就能高亮代码及代码自动提示功能),还对MFC的一些功能优化很多. 修改两个工程文件就把VS2012的项目移植到VS2010中去的方法如 ...

  2. 传输层:UDP 协议

    一.传输层协议 从之前介绍的网络层协议来看,通信的两端是两台主机,IP 数据报首部就标明了这两台主机的 IP 地址.但是从传输层来看,是发送方主机中的一个进程与接收方主机中的一个进程在交换数据,因此, ...

  3. Windows API 教程(七) hook 钩子监听

    茵蒂克丝 如何创建一个窗口 手动创建窗口的流程 实际代码 安装钩子 (Install hook) 钩子简介 SetWindowsHookEx 函数 设置监听[键盘]消息 设置监听[鼠标]消息 如何创建 ...

  4. 怎样使用 iOS 7 的 AVSpeechSynthesizer 制作有声书(3)

    plist 中的每一页 utteranceSting 我们都创建了一个RWTPage.displayText.因此,每页的文本会一次性地显示出来. 由于 You've constructedeach ...

  5. 翻翻git之---一个丰富的通知工具类 NotifyUtil

    转载请注明出处王亟亟的大牛之路 P1(废话板块.今天还加了个小广告) 昨天出去浪,到家把麦麦当当放出来玩一会就整到了12点多..早上睡过头了. .简直心酸. ... 近期手头上有一些职位能够操作,然后 ...

  6. 为什么阿里巴巴不建议在for循环中使用"+"进行字符串拼接

    字符串,是Java中最常用的一个数据类型了.关于字符串的知识,作者已经发表过几篇文章介绍过很多,如: Java 7 源码学习系列(一)--String 该如何创建字符串,使用" " ...

  7. 团队项目的Git分支管理规范

    原文地址: http://blog.jboost.cn/2019/06/17/git-branch.html 许多公司的开发团队都采用Git来做代码版本控制.如何有效地协同开发人员之间,以及开发.测试 ...

  8. 开始nodejs+express的学习+实践(1)

    开始nodejs+express的学习+实践(1) 开始nodejs+express的学习+实践(2) 开始nodejs+express的学习+实践(3) 开始nodejs+express的学习+实践 ...

  9. Chrome自带恐龙小游戏的源码研究(二)

    在上一篇<Chrome自带恐龙小游戏的源码研究(一)>中实现了地面的绘制和运动,这一篇主要研究云朵的绘制. 云朵的绘制通过Cloud构造函数完成.Cloud实现代码如下: Cloud.co ...

  10. PHP网站常见安全漏洞 及相应防范措施总结

    一.常见PHP网站安全漏洞 对于PHP的漏洞,目前常见的漏洞有五种.分别是Session文件漏洞.SQL注入漏洞.脚本命令执行漏洞.全局变量漏洞和文件漏洞.这里分别对这些漏洞进行简要的介绍. 1.se ...