谷粒商城实战笔记-167-缓存-SpringCache-简介

一,使用缓存的痛点

在使用缓存时,有一个通用的编程模式:

  • 首先查询缓存,如果命中缓存,返回缓存中的结果
  • 如果没有命中,则查询数据库,返回结果的同时将查询结果写入缓存
  • 为了防止缓存击穿,需要加分布式锁以及查询结束后解锁

这个模式下有大量的模板代码,如果有大量需要使用缓存的方法,会导致大量的冗余,代码可读性差、可维护性差。

举例说明

在这种情况下,需要手动编写逻辑来处理缓存的读写和分布式锁。

用户服务类 (UserService)

@Service
public class UserService {
  
    public User findUserById(Long id) throws InterruptedException {
        // 尝试从 Redis 中获取用户
        User user = (User) redisTemplate.opsForValue().get("user:" + id);

        if (user == null) {
            // 如果 Redis 中没有,则尝试获取分布式锁
            String lockKey = "lock:user:" + id;
            Boolean lockAcquired = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, "locked", 10, TimeUnit.SECONDS);

            if (Boolean.TRUE.equals(lockAcquired)) {
                try {
                    // 在锁保护下再次检查缓存
                    user = (User) redisTemplate.opsForValue().get("user:" + id);
                    if (user == null) {
                        // 如果仍然没有,则查询数据库
                        user = userRepository.findById(id).orElse(null);
                        // 存储到 Redis 中
                        if (user != null) {
                            redisTemplate.opsForValue().set("user:" + id, user);
                        } else {
                            // 防止缓存穿透,存储空对象或特殊标记
                            redisTemplate.opsForValue().set("user:" + id, "not-found", 5, TimeUnit.MINUTES);
                        }
                    }
                } finally {
                    // 释放锁
                    stringRedisTemplate.delete(lockKey);
                }
            } else {
                // 如果未能获取锁,则等待一段时间后重试
                Thread.sleep(1000);
                return findUserById(id); // 递归调用
            }
        }
        return user;
    }
}

上面代码,有大量嵌套的if/else和try/catch,导致代码冗长,可读性差,可维护性差。

理想情况

理想情况下,利用注解来简化缓存逻辑,开发者只需要专注于读取数据库的实现。

用户服务类 (UserService)

@Service
public class UserService {

    @Cacheable
    public User findUserByIdWithLock(Long id) throws InterruptedException {
        // 查询数据库
        return userRepository.findById(id).orElse(null);
	}
}

实际上,Spring3.1开始,提供了这样的解决方案Spring Cache。

二,Spring Cache

1,简介

  • Spring 从 3.1 开始定义了 org.springframework.cache.Cache
    和 org.springframework.cache.CacheManager 接口来统一不同的缓存技术;并支持使用 JCache(JSR-107)注解简化我们开发
  • Cache 接口为缓存的组件规范定义,包含缓存的各种操作集合;
    Cache 接 口 下 Spring 提 供 了 各 种 xxxCache 的 实 现,如 RedisCache,EhCacheCache,ConcurrentMapCache 等
  • 使用SpringCache后,每次调用需要缓存功能的方法时,Spring 会检查检查指定参数的指定的目标方法是否已经被调用过,如果有就直接从缓存中获取方法调用后的结果,如果没有就调用方法并缓存结果后返回给用户,下次调用直接从缓存中获取。这写逻辑的实现完全由SpringCache完成,开发者只需要提供查询数据库的方法,并在方法上添加SpringCache的注解,这种开发方式大大简化了缓存的使用。
  • 使用 Spring 缓存时我们需要关注以下两点
    • 1,确定方法需要被缓存以及缓存策略
    • 2,从缓存中读取之前缓存存储的数据
根据引用中提供的信息,谷粒商城是一个B2C模式的电商平台,主要销售自营商品给客户。B2C模式指的是商对客的模式,即商家直接向消费者销售商品和服务。谷粒商城使用微服务架构,这是一种将应用程序拆分成独立且可独立开发、部署和扩展的小型服务的架构。引用还提到谷粒商城的技术涵盖微服务架构、分布式、全栈、集群、部署和自动化运维等方面。 因此,从前慢-谷粒商城篇章6主要讨论的可能是谷粒商城的技术方面,包括微服务架构、分布式、全栈、集群、部署和自动化运维等内容。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [从前慢-谷粒商城篇章1](https://blog.csdn.net/m0_67391121/article/details/125383572)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [2020年谷粒商城md笔记](https://download.csdn.net/download/ZHUXIUQINGIT/12543161)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小手追梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值