【系统开发】尚硅谷 - 谷粒商城项目笔记(五):分布式缓存

文章目录

  • 分布式缓存
    • 缓存使用场景
    • redis作缓存中间件
      • 引入redis依赖
      • 配置redis
      • 堆外内存溢出
    • 缓存失效问题
      • 缓存穿透
      • 缓存雪崩
      • 缓存击穿
    • Redisson分布式锁
      • 导入依赖
      • redisson配置类
      • 可重入锁
      • 读写锁
      • 缓存一致性解决
    • 缓存-SpringCache
      • 简介
      • @Cacheable
      • 自定义缓存配置
      • @CacheEvict
      • @CachePut
      • 原理与不足


分布式缓存

缓存使用场景

image-20220208135426837

image-20220208135510086

image-20220208135906136

redis作缓存中间件

引入redis依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置redis

# ip地址
spring.redis.host=124.222.43.217
# 端口
spring.redis.port=6379

堆外内存溢出

image-20220208142445893

<!--引入redis,排除lettuce,使用jedis-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><exclusions><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions>
</dependency>
<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId>
</dependency>

缓存失效问题

缓存穿透

image-20220208142558424

缓存雪崩

image-20220208142803867

缓存击穿

image-20220208142858386

Redisson分布式锁

导入依赖

<!-- 以后使用redisson作为所有分布式锁,分布式对象等功能框架 -->
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.12.0</version>
</dependency>

redisson配置类

@Configuration
public class MyRedissonConfig {@Bean(destroyMethod="shutdown")RedissonClient redissonClient() throws IOException {Config config = new Config();// 这里必须以redis://开头,否则会报错config.useSingleServer().setAddress("redis://124.222.43.217:6379");return Redisson.create(config);}
}

可重入锁

可重入锁解释:无论是公平方式还是非公平方式,进门坐下来之后,你可以问医生问题一次,两次,无数次( 重入),只要你还坐着,你都可以问,但是一旦起身离开座位,你的位置就会被抢,除非没人排队,不然你失去了提问的资格。

@ResponseBody
@GetMapping("/hello")
public String hello() {//1 获取一把锁,只要锁的名字一样,就是同一把锁RLock lock = redisson.getLock("my-lock");// 2 加锁lock.lock(); // 阻塞式等待,默认加的锁都是30s// 锁的自动续期,如果业务超长,运行期间自动给锁续上新的30s。不用担心业务时间长,锁自动过期被删除// 加锁的业务只要运行完成,就不会给当前锁续期,即使不手动解锁,锁默认在30s以后自动删除lock.lock(10, TimeUnit.SECONDS); //10s自动解锁,自动解锁时间一定要大于业务的执行时间// lock.lock(10, TimeUnit.SECONDS); // 锁时间到了之后,不会自动续期try {System.out.println("加锁成功,执行业务" + Thread.currentThread().getId());// 模拟长业务5sThread.sleep(5000);} catch (Exception e) {}finally {// 3 解锁System.out.println("释放锁" + Thread.currentThread().getId());lock.unlock();}return "hello";
}

读写锁

读锁(共享锁)会等待写锁(互斥锁,排他锁)释放,保证一定能读到最新数据

写锁也会等待读锁释放,保证写数据时不能读取数据

总结:读写互斥,不管是先读后写,还是先写后读,都会进行阻塞等待

    @GetMapping("/write")@ResponseBodypublic String writeValue() {RReadWriteLock lock = redisson.getReadWriteLock("rw-lock");String s = "";// 改数据,加写锁RLock rLock = lock.writeLock();try {rLock.lock();System.out.println("nihao");s = UUID.randomUUID().toString();Thread.sleep(30000);redisTemplate.opsForValue().set("writeValue", s);} catch (Exception e) {e.printStackTrace();}finally {rLock.unlock();}return s;}
@GetMapping("/read")@ResponseBodypublic String readValue() {RReadWriteLock lock = redisson.getReadWriteLock("rw-lock");String s = "";// 读数据,加读锁RLock rLock = lock.readLock();try {rLock.lock();s = redisTemplate.opsForValue().get("writeValue");} catch (Exception e) {e.printStackTrace();}finally {rLock.unlock();}return s;}

缓存一致性解决

双写模式:写操作后,同时修改缓存

失效模式:写操作后,删除缓存

image-20220208161958708

image-20220208162404365

image-20220208162549958

缓存-SpringCache

简介

image-20220208182042271

image-20220208181958192

image-20220208182936391

@Cacheable

引入依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>

properties配置

# 使用redis作为缓存
spring.cache.type=redis
# 设置有效时间,毫秒为单位,3600*1000
spring.cache.redis.time-to-live=3600000
# 是否使用缓存前缀
spring.cache.redis.use-key-prefix=true
# 指定缓存前缀,如果不指定,则默认使用注解中value指向的值(分组名),如果value没有指向任何值,则无缓存前缀
# spring.cache.redis.key-prefix=WSKH_CACHE_
# 是否缓存空值,防止缓存穿透
spring.cache.redis.cache-null-values=true
spring.session.store-type=redis

启动类上加注解,开启缓存

@EnableCaching

在要开启缓存的方法上加上@Cacheable注解,示例如下所示:

// 每一个需要缓存的数据我们都要指定放到哪个名字的缓存。【缓存的分区】
// 当前方法的结果需要缓存,如果缓存中有,方法不调用,如果缓存中没有,会调用方法,最后将方法的结果放入缓存
// value = {"category"} 表示:属于哪个缓存分区(分组),当没有指定缓存前缀的时候,就会使用这个分组名作为前缀
// key = "#root.method.name" 表示:将方法名作为存入redis中的键
// sync = true 表示:是否为同步代码块
@Cacheable(value = {"category"},key = "#root.method.name",sync = true)  
@Override
public List<CategoryEntity> getLevel1Categorys() {long l = System.currentTimeMillis();List<CategoryEntity> categoryEntities = baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));System.out.println("消耗时间," + (System.currentTimeMillis() - 1));return categoryEntities;
}

自定义缓存配置

默认缓存数据是保存JDK序列化后的数据,一般业务上需要使用JSON格式进行缓存的存储(JSON具有跨语言,跨平台的高兼容性)

@EnableConfigurationProperties(CacheProperties.class)
@Configuration
@EnableCaching
public class MyCacheConfig {@BeanRedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();config = config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));config = config.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));CacheProperties.Redis redisProperties = cacheProperties.getRedis();if (redisProperties.getTimeToLive() != null) {config = config.entryTtl(redisProperties.getTimeToLive());}if (redisProperties.getKeyPrefix() != null) {config = config.prefixKeysWith(redisProperties.getKeyPrefix());}if (!redisProperties.isCacheNullValues()) {config = config.disableCachingNullValues();}if (!redisProperties.isUseKeyPrefix()) {config = config.disableKeyPrefix();}return config;}
}

@CacheEvict

  • value = “category”:指定分组名,即缓存默认前缀
  • allEntries = true:指定删除value指向的分组下的所有缓存数据
  • key = " ‘myKey’ ":指定缓存的key值,如果是普通字符串,则需要在双引号中加单引号,将其包裹
@CacheEvict(value = "category",allEntries = true)  // 失效模式
@CachePut // 双写模式
@Transactional
@Override
public void updateCasecade(CategoryEntity category) {this.updateById(category);categoryBrandRelationService.updateCategory(category.getCatId(), category.getName());
}

同时清除多个缓存

image-20220208190615505

@CachePut

双写模式,修改完数据库后,将返回的结果更新到缓存中,如果方法返回修饰符为void,那么就不能使用@CachePut注解

原理与不足

image-20220208191257439

image-20220208191733676

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/2130.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis主从/哨兵机制原理介绍

目录 ​编辑 一、主从复制 1.1 什么是主从复制 1.2 主从复制的作用 1.3 主从复制原理 1.3.1 全量复制 1.3.2 增量复制 1.3.3 同步流程 二、哨兵机制 2.1 哨兵机制介绍 2.1.1 集群逻辑图 2.1.2 哨兵机制实现的功能 2.2 哨兵机制原理 2.2.1 监控 2.2.2 下线 2.2.2.1 下线流程 2.…

HarmonyOS学习路之开发篇—AI功能开发(文档检测校正)

基本概念 文档校正提供了文档翻拍过程的辅助增强功能&#xff0c;包含两个子功能&#xff1a; 文档检测&#xff1a;能够自动识别图片中的文档&#xff0c;返回文档在原图中的位置信息。这里的文档泛指外形方正的事物&#xff0c;比如书本、相片、画框等。文档校正&#xff1a…

Midjourney使用教程:三 图片风格提示

这里我根据现在的官方文档来继续我们的Midjourney的教程&#xff0c;看到这里如果你去实践的话&#xff0c;估计你已经有了好多张属于自己的图片。 这时候你不在满足简单的提示生成的Midjourney的默认风格图片&#xff0c;实际上你可以通过一些关键词做提示&#xff0c;来改变…

pcl基于八叉树进行空间划分和搜索操作

建立空间索引在点云数据处理中已被广泛应用&#xff0c;常见空间索引一般是自顶向下逐级划分空间的各种空间索引结构&#xff0c;比较有代表性的包括 BSP 树、KD 树、KDB 树、 R树、R树、CELL 树、四叉树和八叉树等索引结构&#xff0c;而在这些结构中 KD 树和八叉树在 3D点云数…

多元分类预测 | Matlab灰狼算法(GWO)优化混合核极限学习机(HKELM)分类预测,多特征输入模型,GWO-HKELM分类预测

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元分类预测 | Matlab灰狼算法(GWO)优化混合核极限学习机(HKELM)分类预测,多特征输入模型,GWO-HKELM分类预测 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab…

【redis】redis集群

这里是redis系列文章之《redis集群》&#xff0c;上一篇文章链接&#xff1a;【redis基础】哨兵_努力努力再努力mlx的博客-CSDN博客 目录 概念 作用 集群算法-分片-槽位slot 槽位与分配的概念及两者的优势 官网介绍分析 槽位 分片 两者的优势 slot槽位映射的三种解决方…

mac 安装 aab android包

一、配置bundletool环境 1、下载最新版的bundletool 版本号要最新的 bundletool-all-1.15.1.jarhttps://github.com/google/bundletool/releases/download/1.15.1/bundletool-all-1.15.1.jar Releases google/bundletool GitHub​​​​​​​​​​ 2、把bundletool放在…

2-css-2

一 复合选择器 定义&#xff1a;由两个或多个基础选择器&#xff0c;通过不同的方式组合而成。 作用&#xff1a;更准确、更高效的选择目标元素&#xff08;标签&#xff09;。 1 后代选择器 后代选择器&#xff1a;选中某元素的后代元素。 选择器写法&#xff1a;父选择器…

个人git笔记,持续学习并补充填写

git --version //查看git版本信息 sudo yum remove git -y //卸载gitsudo yum install git -y//安装git 该文章仅仅是为了方便个人日常观看&#xff0c;有些地方没有做详细介绍 git init 创建本地仓库&#xff08;最好先创建一个目录&#xff0c;在该目录下输入指令创建git仓…

TI AM64x工业核心板规格书(双核ARM Cortex-A53 + 单/四核Cortex-R5F + 单核Cortex-M4F,主频1GHz)

1 核心板简介 创龙科技SOM-TL64x是一款基于TI Sitara系列AM64x双核ARM Cortex-A53 单/四核Cortex-R5F 单核Cortex-M4F设计的多核工业级核心板&#xff0c;通过工业级B2B连接器引出5x TSN Ethernet、9x UART、2x CAN-FD、GPMC、PCIe/USB 3.1等接口。核心板经过专业的PCB Layo…

行为型模式--备忘录模式

目录 概述 结构 案例实现 “白箱”备忘录模式 总结&#xff1a; “黑箱”备忘录模式 优缺点 优点&#xff1a; 缺点&#xff1a; 使用场景 概述 又叫快照模式&#xff0c;在不破坏封装性的前提下&#xff0c;捕获一个对象的内部状态&#xff0c;并在该对象之外保存这…

举例说明什么是卷积计算

卷积计算是一种数学运算&#xff0c;主要用于信号处理、图像处理等领域。它涉及到两个函数&#xff08;通常称为信号和核&#xff09;的互相关运算。在图像处理中&#xff0c;卷积计算通常用于实现图像的平滑、锐化、边缘检测等操作。 以图像处理为例&#xff0c;我们可以用一个…