Redis的持久化方式和缓存淘汰策略

Redis的持久化方式和缓存淘汰策略

每天多学一点点~
写博客的目的不仅在于分享,也是为了方便日后复习巩固
话不多说,这就开始吧…

文章目录

  • Redis的持久化方式和缓存淘汰策略
    • 1.序
    • 2.RDB快照(snapshot)
    • 2.AOF(append-only file)
    • 3.选择哪一个
    • 4.Redis4.0混合持久化及AOF重写
    • 5.缓存淘汰策略
    • 6.结语

1.序

Redis系列文章

  • Redis主从架构搭建以及主从复制原理
  • Redis哨兵高可用架构搭建+springboot整合
  • Redis高可用集群(搭建+水平扩容缩容+原理+java代码整合)

昨天一个同事问了我一个问题,他在windows下下载了redis,并且以redis.windows.conf配置文件启动,set了一个key,再get,可以拿到值。然后关闭redis服务,再开启,再get key,发现显示nil,值没了,为何?这就要牵扯到redis的持久化方式了。

2.RDB快照(snapshot)

在默认情况下, Redis 将内存数据库快照保存在名字为 dump.rdb 的二进制文件中。
你可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。
比如说, 以下设置会让 Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时,
save 60 10000 注意60的单位秒 redis本身的注释写的也很清楚了
关闭RDB只需要将所有的save保存策略注释掉即可 即注释掉下图3个save
手动生成RDB快照
进入redis客户端执行命令savebgsave可以生成dump.rdb文件, 每次命令执行都会将所有redis内存快照到一个新的rdb文件里,并覆盖原有rdb快照文件。
save是同步命令,bgsave是异步命令,bgsave会从redis主进程fork(fork()是linux函数)出一个子进程 专门用来生成rdb快照文件。

命令 save bgsave
IO类型 同步 异步
是否阻塞redis其它命令 否(在生成子进程执行调用fork函 数时会有短暂阻塞)
复杂度 O(n) O(n)
优点 不会消耗额外内存 不阻塞客户端命令
缺点 阻塞客户端命令 需要fork子进程,消耗内存

配置自动生成rdb文件后台使用的是bgsave方式。
Redis的持久化方式和缓存淘汰策略_第1张图片

Redis的持久化方式和缓存淘汰策略_第2张图片

图:redis.conf配置文件
dump.rdb文件
图:dump.rdb 文件打开后的样子

2.AOF(append-only file)

快照功能并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化,将修改的每一条指令记录进文件
你可以通过修改配置文件来打开 AOF 功能:
appendonly yes

从现在开始, 每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾。
这样的话, 当 Redis 重新启时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。
你可以配置 Redis 多久才将数据 fsync 到磁盘一次。
有三个选项:

  1. 每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全。
  2. 每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
  3. 从不 fsync :将数据交给操作系统来处理。更快,也更不安全的选择。

推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。
Redis的持久化方式和缓存淘汰策略_第3张图片
图:redis.conf配置文件

Redis的持久化方式和缓存淘汰策略_第4张图片
redis内部resp存储协议
图:appendonly.aof 文件打开后的样子

如下两个配置可以控制AOF自动重写频率

  1. auto-aof-rewrite-min-size 64mb // aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就很快,重写的意义不大。
  2. auto-aof-rewrite-percentage 100 //aof文件自上一次重写后文件大小增长了100%则再次触发重写。

AOF还可以手动重写,进入redis客户端执行命令bgrewriteaof重写AOF (AOF重写redis会fork出一个子进程去做,不会对redis正常命令处理有太多影响)
aof重写命令

3.选择哪一个

如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。
有很多用户都只使用 AOF 持久化, 但并不推荐这种方式: 因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快。

命令 RDB AOF
启动优先级
体积
恢复速度
数据安全性 容易丢数据 根据策略决定

redis启动时如果既有rdb文件又有aof文件则优先选择aof文件恢复数据,因为aof一般来说数据更全一 点。

4.Redis4.0混合持久化及AOF重写

重启 Redis 时,我们很少使用 rdb 来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF日志重放,但是重放 AOF 日志性能相对 rdb 来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。
Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。AOF在重写(aof文件里可能有太多没用指令,所以aof会定期根据内存的最新数据生成aof文件)时将重写这一刻之前的内存rdb快照文件的内容和增量的 AOF修改内存数据的命令日志文件存在一起,都写入新的aof文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,原子的覆盖原有的AOF文件,完成新旧两个AOF文件的替换;
AOF根据配置规则在后台自动重写,也可以人为执行命令bgrewriteaof重写AOF。 于是在 Redis 重启的时候,可以先加载 rdb 的内容,然后再重放增量 AOF 日志就可以完全替代之前的 AOF 全量文件重放,重启效率因此大幅得到提升。

aof重写,不理解的童鞋可以看看这里
比如,公司用的redis配置的是aof,文件有10g,且已经好久没重启过了。分布式环境下,用redis进行分布式锁的操作。再竞争锁的过程中,比如incr lock 最后的结果是5,但是这个是经历了上万次的操作,最后变成5的,redis没必要将之前所有的get update等等改变数据集的命令记录下来。这个时候,redis会用单独的一个子进程,只会记录redis锁最后的值5。用重写之后的aof文件去恢复数据,大大的提高性能!

开启混合持久化:
aof-use-rdb-preamble yes
博主windows本地是3.0的,虚拟机是5.0的,就截图虚拟机上的图吧
Redis的持久化方式和缓存淘汰策略_第5张图片
混合持久化aof文件结构
Redis的持久化方式和缓存淘汰策略_第6张图片
Redis的持久化方式和缓存淘汰策略_第7张图片
新的aof文件:白色部分是rdb格式内容,下面是aof格式内容

5.缓存淘汰策略

当 Redis 内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换 (swap)。交换会让 Redis 的性能急剧下降,对于访问量比较频繁的 Redis 来说,这样龟速的存取效率基本上等于不可用。
在生产环境中我们是不允许 Redis 出现交换行为的,为了限制最大使用内存,Redis 提供了配置参数 maxmemory 来限制内存超出期望大小。
当实际内存超出 maxmemory 时,Redis 提供了几种可选策略 (maxmemory-policy) 来让用户自己决定该如何腾出新的空间以继续提供读写服务。

方式 解释
noeviction 不会继续服务写请求 (DEL 请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能持续进行。这是默认的淘汰策略。
volatile-lru 尝试淘汰设置了过期时间的 key,最少使用的 key 优先被淘汰。没有设置过期时间的 key 不会被淘汰,这样可以保证需要持久化的数据不会突然丢失。
volatile-ttl 不会继续服务写请求 (DEL 请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能持续进行。这是默认的淘汰策略。
volatile-random 跟上面一样,不过淘汰的 key 是过期 key 集合中随机的 key。
allkeys-lru 区别于 volatile-lru,这个策略要淘汰的 key 对象是全体的 key 集合,而不只是过期的 key 集合。这意味着没有设置过期时间的 key 也会被淘汰。
allkeys-random 跟上面一样,不过淘汰的策略是随机的 key。

volatile-xxx 策略只会针对带过期时间的 key 进行淘汰,allkeys-xxx 策略会对所有的 key 进行淘汰。如果你只是拿 Redis 做缓存,那应该使用 allkeys-xxx,客户端写缓存时不必携带过期时间。如果你还想同时使用 Redis 的持久化功能,那就使用 volatile-xxx 策略,这样可以保留没有设置过期时间的 key,它们是永久的 key 不会被 LRU 算法淘汰。

Redis的持久化方式和缓存淘汰策略_第8张图片

6.结语

世上无难事,只怕有心人,每天积累一点点,fighting!!!

你可能感兴趣的:(redis专题)