【Redis(8)】Spring Boot整合Redis和Guava,解决缓存穿透、缓存击穿、缓存雪崩等缓存问题

这篇具有很好参考价值的文章主要介绍了【Redis(8)】Spring Boot整合Redis和Guava,解决缓存穿透、缓存击穿、缓存雪崩等缓存问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在缓存技术的挑战及设计方案我们介绍了使用缓存技术可能会遇到的一些问题,那么如何解决这些问题呢?

在构建缓存系统时,Spring Boot和Redis的结合提供了强大的支持,而Guava的LoadingCache则为缓存管理带来了便捷的解决方案。下面我将介绍如何通过整合Spring Boot、Redis和Guava来实现一个解决缓存穿透、缓存击穿、缓存雪崩、缓存污染和缓存数据一致性问题的缓存方案。

一、整合Spring Boot与Redis

首先,我们需要在Spring Boot项目中整合原生Redis客户端。这可以通过添加Spring Boot Redis依赖来实现。

二、引入Guava

Guava的LoadingCache是一个高级缓存工具,它支持自动加载、缓存数据的自动刷新和监听器通知。

三、工具类

下面是一个三高缓存工具类的实现,它整合了Spring Boot、Redis和Guava的LoadingCache。这个工具类旨在解决缓存穿透、缓存击穿、缓存雪崩、缓存污染和缓存数据一致性问题。

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class CacheUtil<DataLoader extends CacheUtil.DataLoaderInterface> {

    private final StringRedisTemplate stringRedisTemplate;
    private final ValueOperations<String, String> valueOperations;
    private final LoadingCache<String, String> loadingCache;
    private final DataLoader dataLoader;

    @Autowired
    public CacheUtil(
        StringRedisTemplate stringRedisTemplate, DataLoader dataLoader) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.valueOperations = stringRedisTemplate.opsForValue();
        this.dataLoader = dataLoader;

        // 初始化Guava LoadingCache
        // 设置最大容量,避免缓存污染
        // 设置写入后过期时间,避免缓存雪崩
        // 使用锁机制,避免缓存击穿
        this.loadingCache = CacheBuilder.newBuilder()
                .maximumSize(10000)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .build(new CacheLoader<String, String>() {
                    @Override
                    public String load(String key) throws Exception {
                        // 当缓存未命中时,调用数据加载器的方法从数据库加载数据
                        return dataLoader.loadDataFromDatabase(key);
                    }
                });
    }

    public String get(String key) {
        try {
            // 通过Guava LoadingCache获取数据
            // 自动处理缓存穿透和击穿
            return loadingCache.get(key);
        } catch (ExecutionException e) {
            // 异常处理,返回null
            return null;
        }
    }

    public void set(String key, String value) {
        // 同时更新Redis和Guava LoadingCache
        // 保持数据一致性
        valueOperations.set(key, value);
        loadingCache.put(key, value);
    }

    public void update(String key, String value) {
        // 更新缓存数据,解决数据一致性问题
        set(key, value);
    }

    public void insert(String key, String value) {
        // 插入前检查缓存,避免缓存污染
        if (get(key) == null) {
            set(key, value);
        }
    }

    public void delete(String key) {
        // 删除Redis和Guava LoadingCache中的数据
        // 保持数据一致性
        valueOperations.delete(key);
        loadingCache.invalidate(key); // 使缓存项失效
    }

    // 用于在数据库更新后刷新缓存
    public void refreshCache(String key) {
        loadingCache.invalidate(key);
    }

    // 数据加载器接口,调用者需要实现该接口以提供数据加载逻辑
    public interface DataLoaderInterface {
        String loadDataFromDatabase(String key);
    }
}

四、使用示例

  • 实现数据加载器接口:创建一个类实现CacheUtil.DataLoaderInterface接口,提供具体的数据加载逻辑。
public class UserCacheDataLoader implements CacheUtil.DataLoaderInterface {

    private final UserService userService; // 假设这是您的UserService

    @Autowired
    public UserCacheDataLoader(UserService userService) {
        this.userService = userService;
    }

    @Override
    public String loadDataFromDatabase(String key) {
        // 根据键(例如用户ID)从数据库加载数据
        User user = userService.findById(key);
        if (user != null) {
            return user.toString(); // 将用户信息转换为字符串
        }
        return null; // 用户不存在
    }
}
  • 配置Spring Bean:在Spring配置中注册CacheUtil Bean。
@Configuration
public class CacheConfig {

    @Bean
    public CacheUtil<UserCacheDataLoader> userCacheUtil(
        UserCacheDataLoader userCacheDataLoader) {
        // 假设已经配置好
        StringRedisTemplate stringRedisTemplate = stringRedisTemplate(); 
        return new CacheUtil<>(stringRedisTemplate, userCacheDataLoader);
    }

    // 其他配置...
}
  • 在应用中使用:在需要缓存的地方注入CacheUtil并使用它。
@RestController
@RequestMapping("/users")
public class UserController {

    private final CacheUtil<UserCacheDataLoader> userCacheUtil;

    @Autowired
    public UserController(CacheUtil<UserCacheDataLoader> userCacheUtil) {
        this.userCacheUtil = userCacheUtil;
    }

    @GetMapping("/{userId}")
    public String getUserDetails(@PathVariable String userId) {
        // 使用CacheUtil的get方法来获取缓存数据
        return userCacheUtil.get(userId);
    }

   
    // 更新缓存数据
    userCacheUtil.update(key, value);

    // 插入缓存数据
    userCacheUtil.insert(key, value);

    // 删除缓存数据
    userCacheUtil.delete(key);

    // 数据库更新后刷新缓存
    userCacheUtil.refreshCache(key);
}

 文章来源地址https://www.toymoban.com/news/detail-855509.html

注意:

  • 请确保StringRedisTemplate和数据加载器(如UserCacheDataLoader)已经正确配置并注入到CacheUtil中。
  • 根据业务逻辑的复杂性,loadDataFromDatabase方法可能需要合理的超时和重试策略。
  • 在实际部署前,进行充分的测试,确保缓存加载逻辑在各种情况下都能正常工作。

 

到了这里,关于【Redis(8)】Spring Boot整合Redis和Guava,解决缓存穿透、缓存击穿、缓存雪崩等缓存问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • redis缓存穿透、缓存击穿、缓存雪崩及对应解决方法

    缓存穿透、击穿和雪崩是缓存使用中的常见问题,对它们的理解和相应的解决方法对于维护系统性能和稳定性至关重要。 定义 : 当客户端请求的数据在缓存中和数据库中都不存在时,该请求会直接打到数据库上,这种情况称为缓存穿透。如果持续请求这样的数据,会给数据

    2024年04月08日
    浏览(34)
  • redis缓存雪崩、穿透、击穿解决方案

    关于缓存异常,我们常见的有三个问题:缓存雪崩、缓存击穿、缓存穿透。这三个问题一旦发生,会导致大量请求直接落到数据库层面。如果请求的并发量很大,会影响数据库的运行,严重的会导致数据库宕机。 为了避免缓存异常带来的损失,我们需要了解每种异常的原因以

    2024年02月10日
    浏览(39)
  • Redis缓存穿透、击穿、雪崩问题及其解决方法

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

    2024年02月02日
    浏览(30)
  • Redis什么是缓存穿透、击穿、雪崩?如何解决

    通常后端会采用Mysql等磁盘数据库,可以持久化但是访问慢,高并发时性能差,需要设置Nosql内存型数据库缓存:Redis等 但缓存可能出现:缓存穿透、缓存击穿、缓存雪崩等问题 查找数据的顺序是:先查找缓存,再查找数据库 当查找一个数据时,缓存没有都会请求数据库,当

    2024年02月09日
    浏览(40)
  • Redis:缓存击穿、缓存穿透与缓存雪崩的区别、解决方案

            近期学习redis相关原理,记录一下开发过程中Redis的一些常见问题及应对方法。 一句话总结:先查 redis发现没数据 ,再去 数据库查发现还是没数据 。 这种情况下 缓存永远不会生效 ,数据库将承担巨大压力。         我们知道,redis的缓存作用,是在客户端发起查

    2024年02月06日
    浏览(37)
  • redis中缓存雪崩,缓存穿透,缓存击穿的原因以及解决方案

    在redis中,新,旧数据交替时候,旧数据进行了删除,新数据没有更新过来,造成在高并发环境下,大量请求查询redis没有数据,直接查询mysql,造成mysql的压力骤增,给mysql造成极大的压力,造成一连串的后续异常反应。 1.大多数系统设计者 考虑用加锁 (最多的解决方案)或

    2024年02月15日
    浏览(38)
  • Redis中的缓存雪崩、击穿、穿透的原因以及解决办法

    缓存雪崩、击穿、穿透一旦发生,会导致大量的请求积压到数据库层。如果请求的并发量很大,就会导致数据库宕机或是故障,这就是很严重的生产事故了。 俗话说,知己知彼,百战不殆。了解了问题的成因,我们就能够在应用Redis缓存时,进行合理的缓存设置,以及相应的

    2024年02月12日
    浏览(35)
  • redis实战-缓存三剑客穿透击穿雪崩解决方案

    缓存穿透 :缓存穿透是指客户端请求的 数据在缓存中和数据库中都不存在 ,这样缓存永远不会生效,这些请求都会打到数据库, 造成数据库压力 ,也让缓存没有发挥出应有的作用 缓存空对象 当我们客户端访问不存在的数据时,先请求redis,但是此时redis中没有数据,此时

    2024年02月11日
    浏览(33)
  • Redis中的缓存穿透、雪崩、击穿的原因以及解决方案

    是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。 我们可以简单的

    2024年02月12日
    浏览(31)
  • Redis缓存雪崩、穿透、击穿原因分析和解决方案,附Redis管道使用技巧

    先给大家附上其他几篇文章,感兴趣的自行开车导航 Redis过期策略和持久化机制全面揭秘,教你如何合理配置 【深入浅出Redis 一】从版本特性到数据类型到线程模型,带你了解Redis的核心特性和应用场景! 一次redis OOM问题分析解决,rdbtools安装分析redis内存 Redis管道(pipelin

    2024年02月16日
    浏览(32)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包