缓存击穿的解决方案

举报
一颗小谷粒 发表于 2024/11/26 18:08:58 2024/11/26
【摘要】 缓存击穿在微服务架构中,Redis等缓存系统被广泛用于提高系统的响应速度和减轻数据库的压力。通过将热点数据存储在缓存中,系统可以直接从缓存中获取数据,而无需每次都查询数据库,从而大大提高了系统的性能。然而,在使用缓存的过程中,也会遇到一些问题,其中之一就是缓存击穿问题。什么是缓存击穿缓存击穿是指当缓存中没有某个热点数据的缓存时(一种情况是缓存时间到期,另一种是大量请求集中在程序某一处判定为缓...

缓存击穿

在微服务架构中,Redis等缓存系统被广泛用于提高系统的响应速度和减轻数据库的压力。通过将热点数据存储在缓存中,系统可以直接从缓存中获取数据,而无需每次都查询数据库,从而大大提高了系统的性能。然而,在使用缓存的过程中,也会遇到一些问题,其中之一就是缓存击穿问题。

什么是缓存击穿

缓存击穿是指当缓存中没有某个热点数据的缓存时(一种情况是缓存时间到期,另一种是大量请求集中在程序某一处判定为缓存不能存在),而此时恰好有大量的并发请求请求这个数据,这些请求都会直接打到数据库上,造成数据库短时间内承受大量请求而崩掉。

缓存击穿的原因

  • 缓存失效:当缓存中的数据因为过期时间到达而被删除,而新的缓存数据还没有被加载进来时,如果此时有大量的请求到来,这些请求都会直接打到数据库上,造成缓存击穿。
  • 缓存未命中:由于某些原因(如数据更新、缓存被误删等),缓存中不存在某个数据的缓存,当大量请求同时访问这个数据时,它们都会穿透缓存直接访问数据库。
  • 对于第一次请求:当第一次请求时,会判断缓存中没有存在这个数据,请求就会直接落到数据库上,当瞬间有大量的请求时,很有可能都会判断缓存中没有数据,直接全都打到了数据库层面上(开头举例就是此情况)

缓存击穿的解决方案

  • 设置热点数据永远不过期:这是一种简单直接的解决方案,但是会导致缓存中的数据无法实时更新,可能引发数据不一致的问题
  • 分布式锁:当缓存失效时,不是立即去加载数据库数据,而是先使用分布式锁去获取加载数据的权限,当获取到权限后,再去加载数据到缓存。这样,在第一个请求去加载数据时,其他并发请求则需要等待,第一个请求将数据加载到缓存后,直接释放分布式锁,此时其他请求就能够从缓存中获取数据,而不需要再去查询数据库

解决方案的分析

  • 第一种方案数据不过期肯定是不行的,就算只存放热点数据,但是也会随着数据量越来越大的情况下,redis的承受压力也会越来越大
  • 第二种使用分布式锁让请求进行串行化,确实可以解决缓存击穿的问题,我们来写一段代码实现使用分布式锁的方案

使用分布式锁

public String getDataV2(String id){
    RedisTemplate<String,String> redisTemplate = redisCache.getInstance();
    String cachedValue = redisTemplate.opsForValue().get(id);
    if (StringUtil.isEmpty(cachedValue)) {
        //分布式锁
        RLock lock = serviceLockTool.getLock(LockType.Reentrant, id);
        lock.lock();
        try {
            Program program = programMapper.selectById(id);
            if (Objects.nonNull(program)) {
                redisTemplate.opsForValue().set(id,JSON.toJSONString(program));
                cachedValue = JSON.toJSONString(program);
            }
        } finally {
            lock.unlock();
        }
    }
    return cachedValue;
}
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。