redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现?

面试题

redis 的过期策略都有哪些?内存淘汰机制都有哪些?手写一下 LRU 代码实现?

面试官心理分析

如果你连这个问题都不知道,上来就懵了,回答不出来,那线上你写代码的时候,想当然的认为写进 redis 的数据就一定会存在,后面导致系统各种 bug,谁来负责?

常见的有两个问题:

  • 往 redis 写入的数据怎么没了?

可能有同学会遇到,在生产环境的 redis 经常会丢掉一些数据,写进去了,过一会儿可能就没了。我的天,同学,你问这个问题就说明 redis 你就没用对啊。redis 是缓存,你给当存储了是吧?

啥叫缓存?用内存当缓存。内存是无限的吗,内存是很宝贵而且是有限的,磁盘是廉价而且是大量的。可能一台机器就几十个 G 的内存,但是可以有几个 T 的硬盘空间。redis 主要是基于内存来进行高性能、高并发的读写操作的。

那既然内存是有限的,比如 redis 就只能用 10G,你要是往里面写了 20G 的数据,会咋办?当然会干掉 10G 的数据,然后就保留 10G 的数据了。那干掉哪些数据?保留哪些数据?当然是干掉不常用的数据,保留常用的数据了。

  • 数据明明过期了,怎么还占用着内存?

这是由 redis 的过期策略来决定。

面试题剖析

redis 过期策略

redis 过期策略是:定期删除+惰性删除

所谓定期删除,指的是 redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。

假设 redis 里放了 10w 个 key,都设置了过期时间,你每隔几百毫秒,就检查 10w 个 key,那 redis 基本上就死了,cpu 负载会很高的,消耗在你的检查过期 key 上了。注意,这里可不是每隔 100ms 就遍历所有的设置过期时间的 key,那样就是一场性能上的灾难。实际上 redis 是每隔 100ms 随机抽取一些 key 来检查和删除的。

但是问题是,定期删除可能会导致很多过期 key 到了时间并没有被删除掉,那咋整呢?所以就是惰性删除了。这就是说,在你获取某个 key 的时候,redis 会检查一下 ,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。

获取 key 的时候,如果此时 key 已经过期,就删除,不会返回任何东西。

但是实际上这还是有问题的,如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期 key 堆积在内存里,导致 redis 内存块耗尽了,咋整?

答案是:走内存淘汰机制

在这里插入图片描述

内存淘汰机制

redis 内存淘汰机制有以下几个:

  • noeviction: 当内存不足以容纳新写入数据时,新写入操作会报错,这个一般没人用吧,实在是太恶心了。
  • allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)。
  • allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 key,这个一般没人用吧,为啥要随机,肯定是把最近最少使用的 key 给干掉啊。
  • volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 key(这个一般不太合适)。
  • volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 key。
  • volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 key 优先移除。

手写一个 LRU 算法

阅读: LeetCode146——LRU缓存机制:

https://blog.csdn.net/qq_32534441/article/details/89406571

你可以现场手写最原始的 LRU 算法,那个代码量太大了,似乎不太现实。

不求自己纯手工从底层开始打造出自己的 LRU,但是起码要知道如何利用已有的 JDK 数据结构实现一个 Java 版的 LRU。

class LRUCache<K, V> extends LinkedHashMap<K, V> {
    private final int CACHE_SIZE;

    /**
     * 传递进来最多能缓存多少数据
     *
     * @param cacheSize 缓存大小
     */
    public LRUCache(int cacheSize) {
        // true 表示让 linkedHashMap 按照访问顺序来进行排序,最近访问的放在头部,最老访问的放在尾部。
        super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);
        CACHE_SIZE = cacheSize;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        // 当 map中的数据量大于指定的缓存个数的时候,就自动删除最老的数据。
        return size() > CACHE_SIZE;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Redis的备份策略主要有RDB持久化和AOF持久化两种。其中RDB持久化是将Redis在某个时间点上的数据快照保存到磁盘上,而AOF持久化则是将Redis执行的每个写命令追加到文件中。这两种持久化方式可以单独使用,也可以同时使用,以提高数据的安全性和可靠性。另外,Redis还支持主从复制和集群模式,可以通过复制和分片来实现数据的备份和高可用性。 ### 回答2: Redis的备份策略有以下几种: 1. RDB持久化:Redis可以通过将数据转存到硬盘上创建一个快照,以便在发生故障时进行数据恢复。RDB持久化可手动触发,也可以通过设置自动触发的方式来实现定期备份。 2. AOF持久化:AOF持久化是将Redis的操作日志以追加的方式保存到硬盘上。每当有写命令时,都会将命令追加到文件末尾。在恢复时,Redis将重新执行这些命令来还原数据。相比于RDB持久化,AOF持久化提供了更好的持久化能力和数据完整性。 3. 主从复制:Redis可以通过主从复制的方式进行数据的备份。其中一个Redis实例作为主节点,负责处理写操作,并将数据同步到所有的从节点上。从节点作为备份节点,负责处理读操作,从主节点同步数据。当主节点发生故障时,可以通过切换从节点为主节点来实现高可用。 4. Redis Cluster:Redis Cluster是一种分布式的数据分片方案,将数据分布在多个节点上。每个节点都具有其中一部分数据的副本,当某个节点不可用时,其他节点可以继续提供服务。Redis Cluster具有自动数据迁移的功能,可以在节点故障或新节点加入时进行数据的重新分配和备份。 以上是Redis的备份策略的主要方式,可以根据实际需求选择适当的备份策略来保证数据的安全和高可用性。 ### 回答3: Redis的备份策略有以下几种: 1. RDB(Redis Database Backup)备份策略:RDB是一种将内存中的数据保存到磁盘的快照备份方法。通过定期生成RDB文件,将内存中的数据以二进制文件的形式保存到硬盘上。RDB备份策略相对简单,可以设定备份的触发条件,例如定时备份或者是超过一定数据变化量才进行备份。但是RDB备份时会阻塞Redis的主线程,可能会对性能产生影响,并且在发生故障时可能会丢失最后一次备份的数据。 2. AOF(Append-only File)备份策略:AOF采用记录命令的方式来备份数据。每条修改数据的命令都会追加到AOF文件中,以追加的方式进行日志记录,保证了数据的持久化。可以选择不同的AOF持久化策略,如无刷、每秒一次、每写入多少次等。AOF备份策略相对于RDB备份策略来说,可以提供更高的数据持久化保证,但是相应地会增加磁盘的写入操作,可能对性能产生一定影响。 3. 数据复制备份策略Redis支持主从复制架构,可以将主节点的数据实时复制到多个从节点上,实现数据的热备。主从复制不仅可以提供备份数据的高可用性,还可以通过读写分离来提升系统的读取性能。当主节点出现故障时,可以切换到其中一个从节点作为主节点,确保系统的高可用性。复制备份策略相对于其他备份策略来说,对于故障恢复和系统容错性更有优势。 综上所述,Redis的备份策略主要包括RDB备份、AOF备份和数据复制备份。使用者可以根据自身的业务需求和性能要求选择合适的备份策略

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值