缓存面试解析:穿透、击穿、雪崩,一致性、分布式锁、Redis过期,海量数据查找

这篇具有很好参考价值的文章主要介绍了缓存面试解析:穿透、击穿、雪崩,一致性、分布式锁、Redis过期,海量数据查找。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

为什么使用缓存

  1. 在程序内部使用缓存,比如使用map等数据结构作为内部缓存,可以快速获取对象。通过将经常使用的数据存储在缓存中,可以减少对数据库的频繁访问,从而提高系统的响应速度和性能。缓存可以将数据保存在内存中,读取速度更快,能够大大缩短数据访问的时间,提升用户体验。

  2. 在业界中,通常在数据库之前添加一层Redis缓存,这样可以避免数据库的性能被大量的请求耗费。当有大量的并发请求时,数据库可能会成为瓶颈,而使用缓存可以有效地缓解数据库的压力。Redis作为一种高效的缓存解决方案,可以将热门数据存储在内存中,以快速响应用户的请求。这种缓存层的引入不仅可以提高系统的性能和吞吐量,还可以提高系统的可靠性和稳定性,因为即使数据库出现故障,缓存仍然可以提供部分服务。

  3. 缓存还可以减少网络传输的负载,特别是在分布式系统中。通过将计算结果或频繁访问的数据缓存起来,可以避免重复计算和重复访问数据库,节省了网络带宽和服务器的资源消耗。这对于海量数据的查找和计算密集型任务尤为重要,可以大大提升系统的效率和可扩展性。

    总之,使用缓存可以优化系统的性能、提高响应速度、降低数据库负载、节省网络传输和服务器资源,从而提升用户体验和系统的可靠性。

缓存穿透、击穿、雪崩

缓存穿透:

缓存穿透指的是当一个请求查询的数据不在缓存中,也不在数据库中,导致每次请求都直接访问数据库,增加了数据库的负载。这可能是由于恶意攻击或者异常情况导致的。为了解决缓存穿透问题,可以采取以下措施:

  • 在缓存中存储一个空值或者默认值,且设置成一定过期时间,以避免重复的无效查询,但是这种方案有缺陷就是redis会多出无用的key,浪费内存资源;
  • 使用布隆过滤器等技术来过滤掉无效的请求,将可能不存在的数据快速过滤掉,布隆过滤器可以有效防止不存在的key进入业务调用数据库,但是需要提前将数据库数据预热到布隆过滤器中,并且他也有一种缺陷就是由于他的数据结构和算法导致无法删除热键,只能新增;
    缓存面试解析:穿透、击穿、雪崩,一致性、分布式锁、Redis过期,海量数据查找

缓存击穿

缓存击穿指的是当某个热点数据过期或者被删除时,大量的请求同时涌入,导致数据库负载过高。这通常发生在高并发环境下。为了避免缓存击穿问题,可以采取以下措施:

  • 第一种就是将热点数据永久缓存进redis,并另起一个线程定时的去更新这个热点数据,那么就热点数据永远不会失效,但是缺陷是在定时任务启动前可能存在数据错误的情况;
  • 第二种情况那么就是加锁,使用互斥锁或者分布式锁来保护对数据库的访问,确保只有一个请求能够重新加载数据到缓存中。但是这种虽然解决了数据库问题,但同时也带来了性能下降;

缓存雪崩

缓存雪崩指的是当缓存中大量的数据同时过期时,导致大量的请求直接访问数据库,造成数据库负载过高。这通常是由于缓存服务器故障、网络故障或者缓存数据过期时间设置不合理等原因导致的。为了避免缓存雪崩问题,可以采取以下措施:

  • 就是在给缓存数据设置过期时间的时候请加一个随机值使用不同的过期时间来分散缓存的失效时间,避免大量数据同时过期。
  • 使用热点数据预加载技术,在缓存数据即将过期之前,提前加载数据到缓存中,确保数据的可用性。

如何保证缓存与数据库之间的数据一致性

保证缓存与数据库之间的强一致性是一个相对复杂的问题。尽管没有绝对的解决方案,但可以采取一些策略来尽可能地提高数据一致性。以下是几种常见的策略:

第一种就是先删除缓存还是先写数据库,这两种都一样,我就说下先删除缓存带来的问题,先删除缓存确实可以在写完数据库后后续的操作都会更新缓存值,但是扛不住并发高,如果删除完缓存后还没来得及写入又被另一个线程读取了旧值更新缓存,那么这缓存白删除了,

第二种就是先写数据库呢?如果数据库写完后,一是在删除缓存之前的读操作读取的仍然是旧值,二是,如果写操作完成后,缓存删除操作由于网络原因丢失了怎么办,以后读取操作都是旧值了;

第三种也就是业界最常用的延时双删;但同时他也无法一定保证数据的一致性

  • 在操作数据库之前先删除缓存:首先,你需要先删除缓存中对应的数据,确保下一次读取请求不会命中旧的缓存数据。
  • 更新数据库:然后,你可以更新数据库中的数据,确保数据库中的数据是最新的。
  • 再次删除缓存:最后,在延时之后,再次删除缓存中的数据。这样可以确保在延时结束后,读操作仍然可以从缓存中获取最新的数据。

如果写操作很频繁,那么缺陷就很明显:很容易产生脏数据并且也无法满足缓存与数据库之间的一致性;

第四种:引入MQ,当我们有两个消费者的时候,一个消费者只管消息的数据库操作,一个消费者只管消息的缓存操作,这样可以确保操作是原子操作。确保了不会删除缓存失败的问题。

但是以上四种都无法保证缓存与数据库之间的强一致性,只能保证数据库与缓存之间的最终一致性;

如何设计分布式锁?如何对锁性能进行优化?

首先分布式锁主要应用场景就是应对多节点部署下如何控制资源的并发保护,那么单纯的jvm锁已经无法满足需求,所以引入了分布式锁,那么常见的有数据库、zookeeper、redis;通常分布式锁的要求的就是性能高、与业务无关;设计分布式锁时,常见的选择是使用Redis作为分布式锁的存储介质。下面将介绍如何设计分布式锁,并对锁性能进行优化。

首先,我们需要掌握Redis的基本命令:

  • SETNX:设置键值对,如果键不存在则返回1,如果键已存在则返回0。

  • EXPIRE:设置键的过期时间。

  • GETSET:先获取旧值,然后将新值设置进去;如果键不存在,则返回null。

  • DEL:删除一个键。

    接下来,我们将讨论几种常见的分布式锁设计方式:

  1. 使用SETNX和DEL操作:在当前业务执行完毕后,使用DEL操作删除锁。但是如果获取锁的进程执行失败,它将永远不会主动解锁,导致锁被死锁。
  2. 使用SETNX和EXPIRE操作:这是最常见的分布式锁设计方式。但是存在一个问题,如果在设置过期时间之前节点挂掉,其他服务将永远无法获取到锁,因为SETNX和EXPIRE不是原子操作。
  3. 使用SETNX和GETSET操作:在设置锁时,将过期时间作为值存储在Redis中。当其他线程争取锁失败时,可以通过GETSET操作检查当前锁是否已经失效。如果锁已失效,则可以使用自己的过期时间来替换旧的值,并与之前的过期时间进行比较,以确定是否成功获取锁。下面给出伪代码示例:
public boolean tryLock(RedisConnection conn) {
    long nowTime = System.currentTimeMillis();
    long expireTime = nowTime + 1000;
    if (conn.SETNX("mykey", expireTime) == 1) {
        conn.EXPIRE("mykey", 1000);
        return true;
    } else {
        long oldValue = conn.get("mykey");
        if (oldValue != null && oldValue < nowTime) {
            long currentValue = conn.GETSET("mykey", expireTime);
            if (oldValue == currentValue) {
                conn.EXPIRE("mykey", 1000);
                return true;
            }
            return false;
        }
        return false;
    }
}

上述代码实现了一种比较高效的分布式锁。然而,上述优化的根本问题在于SETNX和EXPIRE两个指令无法保证原子性。为此,Redis 2.6版本引入了执行Lua脚本的功能,通过Lua脚本可以保证原子性。Redission工具就是基于此原理提供的分布式锁工具。

如何设置过期时间,实现原理是什么?

redis有两种命令可以进行对key设置过期时间:expire和setex。这两种命令都可以用来给key设置过期时间。

实现过期时间的原理可以分为两个部分。

首先是主动删除。Redis会有一个定时任务,定期检查数据库中的key是否已经过期。如果发现某个key已经过期,那么Redis会直接将其删除。

其次是被动删除。当应用程序尝试获取一个已经设置了过期时间的key时,Redis会检查该key是否已经过期。如果已经过期,Redis会在返回结果之前将该key删除。

这样,通过主动删除和被动删除的组合,Redis实现了对key的过期时间的管理。这种混合实现的方式可以保证Redis中的数据始终是最新的,并且不会出现过期的数据。

需要注意的是,Redis并不会为每个key都启动一个单独的定时任务去检查过期时间。相反,Redis会根据实际情况动态调整定时任务的执行频率,以提高性能和效率。这种设计可以有效地减少对系统资源的占用,提高Redis的性能和稳定性。

海量数据下,如何快速查找一条记录?

当前这道题目考验的是对redis整体的理解,所以也要全方位考虑,可以考虑以下优化策略:

  • 使用布隆过滤器:布隆过滤器是一种概率型数据结构,可以用于判断某个元素是否存在于集合中。在海量数据下,可以先使用布隆过滤器将不存在的key过滤掉,这样可以减少部分请求,提高查询效率。

  • 合理选择存储结构:在缓存记录时,可以考虑使用适合的存储结构。如果存储的是大对象,使用key+value(json)形式,那么key可能会很大,不建议使用。而如果使用hash结构存储,可以充分利用Redis的哈希表特性,提高存储效率。此外,可以根据实际情况选择其他存储结构,如列表、有序集合等。

  • 查询优化:如果Redis是集群部署的,数据根据槽位进行分配。如果我们自己对key进行了定位,可以直接访问对应的Redis节点,而不需要通过集群路由。这样可以减少Redis集群的机器计算,提高查询性能。

总结

本文提供了一些保证数据一致性和设计分布式锁的策略。这些策略可以在实际应用中帮助开发人员解决相关的问题,确保系统的数据一致性和并发访问的正确性。同时,通过合理地使用缓存和分布式锁,可以提高系统的性能和可靠性。希望对你在面对Redis相关面试题时有所帮助!文章来源地址https://www.toymoban.com/news/detail-634619.html

到了这里,关于缓存面试解析:穿透、击穿、雪崩,一致性、分布式锁、Redis过期,海量数据查找的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Redis_缓存3_缓存异常(数据不一致、雪崩、击穿、穿透)

    四个方面 缓存中数据和数据库不一致 缓存雪崩 缓存击穿 缓存穿透 14.6.1数据不一致: 一致性包括两种情况 缓存中有数据,需要和数据库值相同 缓存中没有数据,数据库中的数据是最新值 如果不符合以上两种情况,则出现数据不一致的问题。 读写缓存 同步直写 异步写回

    2024年02月13日
    浏览(25)
  • redis缓存击穿/穿透/雪崩面试回答

    面试官 :什么是缓存穿透 ? 怎么解决 ? 候选人 : 嗯~~,我想一下 缓存穿透是指查询一个一定 不存在 的数据,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到 DB 去查询,可能导致 DB 挂掉。这种情况大概率是遭到了攻击。 解决方案的话,

    2024年02月08日
    浏览(33)
  • Redis - 做缓存时高并发问题:缓存穿透、击穿、雪崩,数据库缓存双写不一致

    当用户访问的数据既不在缓存也不在数据库中时,就会导致每个用户查询都会“穿透” 缓存“直抵”数据库。这种情况就称为缓存穿透。当高度发的访问请求到达时,缓存穿透不 仅增加了响应时间,而且还会引发对 DBMS 的高并发查询,这种高并发查询很可能会导致 DBMS 的崩

    2024年02月04日
    浏览(34)
  • Redis(概述、应用场景、线程模式、数据持久化、数据一致、事务、集群、哨兵、key过期策略、缓存穿透、击穿、雪崩)

    目录 Redis概述 应用场景 Redis的线程模式 数据持久化 1.Rdb(Redis DataBase) 2.Aof(Append Only File) mysql与redis保持数据一致 redis事务 主从复制(Redis集群) 哨兵模式 key过期策略 缓存穿透、击穿、雪崩 1.缓存穿透:缓存中没有,在mysql中也没有 2.缓存击穿:数据在数据库中存在,某个

    2024年01月16日
    浏览(44)
  • redis面试题目-如何保证数据库与缓存的数据一致性

    原视频:https://www.bilibili.com/video/BV1Km4y1r75f?p=62vd_source=fa75329ae3880aa55609265a0e9f5d34 由于缓存和数据库是分开的,无法做到原子性的同时进行数据修改,可能出现缓存更新失败,或者数据库更新失败的情况,这时候会出现数据不一致,影响前端业务 先更新数据库,再更新缓存。缓

    2024年02月05日
    浏览(45)
  • 缓存穿透、缓存击穿和缓存雪崩

    👏作者简介:大家好,我是爱发博客的嗯哼,爱好Java的小菜鸟 🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦 📝社区论坛:希望大家能加入社区共同进步 🧑‍💼个人博客:智慧笔记 📕系列专栏:Redis 一聊到redis,必不可少的就是缓存三兄弟的问题,即

    2024年02月11日
    浏览(31)
  • 缓存篇—缓存雪崩、缓存击穿、缓存穿透

    缓存异常会面临的三个问题:缓存雪崩、击穿和穿透。 其中,缓存雪崩和缓存击穿主要原因是数据不在缓存中,而导致大量请求访问了数据库,数据库压力骤增,容易引发一系列连锁反应,导致系统奔溃。不过,一旦数据被重新加载回缓存,应用又可以从缓存快速读取数据,

    2024年02月22日
    浏览(30)
  • 缓存技术(缓存穿透,缓存雪崩,缓存击穿)

    大家好 , 我是苏麟 , 今天聊一聊缓存 .  这里需要一些Redis基础 (可以看相关文章等) 本文章资料来自于 : 黑马程序员   如果想要了解更详细的资料去黑马官网查看 缓存 ,就是数据交换的  缓冲区 ( 称作Cache [ kæʃ ] ) ,俗称的缓存就是 缓冲区内的数据 ,是存贮数据的临时地方,读

    2024年02月10日
    浏览(29)
  • redis 缓存雪崩 && 缓存击穿 && 缓存穿透

    什么是缓存雪崩 当我们提到缓存系统中的问题,缓存雪崩是一个经常被讨论的话题。缓存雪崩是指在某一时刻发生大量的缓存失效,导致瞬间大量的请求直接打到了数据库,可能会导致数据库瞬间压力过大甚至宕机。尤其在高并发的系统中,这种情况会导致连锁反应,整个系

    2024年02月07日
    浏览(36)
  • Redis 缓存穿透、缓存雪崩、缓存击穿

    缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。 常见的解决方案有两种:         缓存空对象                  优点:实现简单,维护方便                 缺点: 额外的内存消耗 可能造

    2024年02月02日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包