一、缓存的概念

首先引入缓存还是有几个问题要问的
1.为什么要用缓存
2.项目中缓存是如何使用的
3.常见的缓存问题
带着这几个问题进行下面的学习

为什么需要缓存?

我们用缓存主要有两个原因
1,缓存是位于内存中的,而内存天然对并发有出色的支持力(高并发)
2,在缓存中的数据读取速度远远高于数据库,极大的提高了程序的性能

项目中如何使用缓存?

缓存一般用在非实时变化的数据上,当一个请求过来通过DB查询用了很长时间,后面这个数据几个小时可能都不会改变,这个时候我们便可以定义一个Key,把数据放到value中存入缓存。下次再查询的时候直接走缓存,性能上会有巨大的提升。

在高并发的场景下,Mysql数据库是完全不支持的,如果项目高峰期请求过来1万+,Mysql数据库完全有可能直接挂掉,这个时候我们可以把数据放入缓存,通过key进行查询,这个时候并发轻松解决,而且查询速度是Mysql的几十倍。

常见的缓存问题

那么当我们使用了缓存以后,还会出现什么不利的影响吗?回答是肯定的,主要有如下几个问题
1.缓存导致和数据库数据不一致的问题
2.缓存雪崩,缓存穿透
3.缓存并发竞争

一、缓存导致和数据库数据不一致的问题

当我们把数据放到缓存之后有一个请求过来修改了数据库的数据,这个时候便产生了数据不一致的问题。
常用的解决办法就是读的时候先读缓存,如果缓存中没有再去读数据库,然后把读出来的数据放入缓存中,消费的时候修改数据库,然后删除缓存。
这里我们用到了懒加载思想(懒加载又叫延迟加载,他有两个好处,第一:当使用时才加载,而不是一开始就加载,为CPU节省时间做其他的事情,第二:加载之前会判断数据是否为空,如果空是空的才去加载,避免了重复加载数据,系统可能会清理内存使数组为空,这样确保数组不为空)
高并发场景如果缓存删除失败导致依然是老数据
这个时候我们可以先删除缓存,然后再修改数据库,这个时候如果缓存删除失败我们可以让事务回滚,重新进行删除,直到删除成功后再修改数据库。

二、缓存雪崩,缓存穿透

缓存雪崩
如果系统在某一时刻请求数量大幅度提升导致缓存机器宕机或者缓存过期查询为空导致查询数据库,这时候所有请求都会请求数据库,数据库必然也会直接挂掉,这个时候系统直接不可用,这就是缓存雪崩。
解决方案
1.把一些热点数据设置为永不过期,有过期时间的防止在同一时间点内清空缓存
2.设置本地缓存和增加 hystrix 限流/降级

缓存穿透
缓存穿透指请求的数据缓存中和数据库中都没有,用户还在不断访问,这个时候会导致数据库压力过大,容易挂死。
解决方案
1.如果第一次从缓存中没有读到数据,从数据库中也没有读到,我们可以存一个value为空的对象到缓存,有效期设置短一些,这样可以防止同一时刻用户不断访问给数据库带来的压力,后续还可以正常存取。
2.还可以设置拦截器,如果查询条件不正确直接返回错误,防止多次请求数据库。

三、缓存并发竞争

这个主要是针对Redis的写问题,当两个客户端同时操作同一个Key,当第一个客户端还没有设置新值回去的时候,第二个客户端获取到的是相同的Key,例如value为20,两个客户端都要给这个值+1,但是最终设置的都是21,这个便是并发竞争问题。
解决方案
1.增加Redission分布式锁或者利用Zookeeper实现分布式锁
2.CAS乐观锁
3.增加时间戳

二、缓存的实现

一、引入依赖

        <!-- ehcache缓存依赖 --><dependency><groupId>net.sf.ehcache</groupId><artifactId>ehcache</artifactId></dependency><!--redis缓存依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><!-- 1.5的版本默认采用的连接池技术是jedis  2.0以上版本默认连接池是lettuce--><exclusions><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions></dependency><!-- 添加jedis --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency>

二、增加本地缓存配置文件

1.增加xml配置本地缓存位置和缓存名称

    <!--name:缓存名称maxElementsInMemory:缓存最大数目maxElementsOnDisk:硬盘最大缓存个数eternal:对象是否永久有效,一但设置了,timeout将不起作用overflowToDisk:是否保存到磁盘timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0diskPersistent:是否缓存虚拟机重启期数据diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MBdiskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存clearOnFlush:内存数量最大时是否清除memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)-->

例1

    <cache name="LocalCache"maxElementsInMemory="10000"eternal="false"timeToIdleSeconds="0"timeToLiveSeconds="200000"diskPersistent="true"overflowToDisk="false"memoryStoreEvictionPolicy="LRU"/><cache name="RedisCache"maxElementsInMemory="10000"eternal="false"timeToIdleSeconds="0"timeToLiveSeconds="150000"diskPersistent="true"overflowToDisk="false"memoryStoreEvictionPolicy="LRU"/>

三、增加Configuration配置实现CacheManager

@Configuration
public class CacheConfiguration {/** ehcache 管理器*/@Bean(name = "localCacheManager")public CacheManager localCacheManager(){return new EhCacheCacheManager();}/*** 重写Redis序列化方式,使用Json方式:* 当我们的数据存储到Redis的时候,我们的键(key)和值(value)都是通过Spring提供的Serializer序列化到数据库的。RedisTemplate默认使用的是JdkSerializationRedisSerializer,StringRedisTemplate默认使用的是StringRedisSerializer。* Spring Data JPA为我们提供了下面的Serializer:* GenericToStringSerializer、Jackson2JsonRedisSerializer、JacksonJsonRedisSerializer、JdkSerializationRedisSerializer、OxmSerializer、StringRedisSerializer。* 在此我们将自己配置RedisTemplate并定义Serializer。*/@Bean@Primarypublic CacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {//方便观察数据,序列化成json格式Jackson2JsonRedisSerializer JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper objectMapper = new ObjectMapper();objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);JsonRedisSerializer .setObjectMapper(objectMapper);RedisSerializationContext.SerializationPair<Object> serializeValues = RedisSerializationContext.SerializationPair.fromSerializer(JsonRedisSerializer);//缓存的失效实现统一为2小时RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(2)).serializeValuesWith(serializeValues);return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config).build();}
}

此外我们还要在启动类上面加上@EnableCaching注解

四、使用缓存

注:本次我们都是使用注解方式增加缓存

    /** 增加本地缓存@Cacheable*/@Cacheable(cacheManager="localCacheManager", cacheNames ={"LocalCache"},key="#studentId")public Integer putLocalCache(String studentId,Integer age){return age;}/** 删除本地缓存@CacheEvict*/@CacheEvict(cacheManager="localCacheManager", cacheNames ={"LocalCache"},key="#studentId")public String deleteLocalCache(String studentId){return studentId;}
    /** 增加Redis缓存@Cacheable*/@Cacheable(cacheManager="redisCacheManager", cacheNames ={"RedisCache"},key="#studentId")public Integer putRedisCache(String studentId,Integer age){return age;}/** 删除Redis缓存@CacheEvict*/@CacheEvict(cacheManager="redisCacheManager", cacheNames ={"RedisCache"},key="#studentId")public String deleteRedisCache(String studentId){return studentId;}

更多用法搜索@Cacheable&&@CacheEvict

以上就是本地缓存和Redis缓存的简单使用啦,自己也是把学习到的地方记录下来,第一次使用注解,如果有不足的地方和错误的地方还希望小伙伴们可以评论指出,一起分享学习!

论微服务接入Redis缓存和本地缓存,提高性能并发第一步!相关推荐

  1. 2022面试200题目和答案分布式+微服务+MYSQL+Redis+JVM+Spring

    200题目和答案分布式+微服务+MYSQL+Redis+JVM+Spring等等 带图MD在资源https://download.csdn.net/download/m0_47987937/86509 ...

  2. 微服务架构下静态数据通用缓存机制

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 来源 |  my.oschina.net/u/3971241/bl ...

  3. redis 什么是冷数据_阿里Java三面凉凉:微服务,Redis,JVM一个都搞不懂

    前言: 金九银十刚刚过去了,不知道很多小伙伴都拿到自己心仪的offer没有,我这边也收到了一个粉丝投来的消息,说看到阿里的面试真题之后人都是懵的,发现自己一窍不通,下面给大家分享我这个粉丝的经历,以及 ...

  4. 服务端分布式缓存与本地缓存

    缓存技术是保障系统性能的基础技术.核心技术. 缓存发挥的作用 ① 最大程度上避免对数据库的并发查询,从而降低因为数据库资源不足导致的系统故障. ② 提升系统的响应速度,保证用户体验 总之缓存使系统稳定 ...

  5. SpringCloud(第 017 篇)电影微服务接入Feign,添加 fallbackFactory 属性来触发请求进行容灾降级...

    2019独角兽企业重金招聘Python工程师标准>>> SpringCloud(第 017 篇)电影微服务接入Feign,添加 fallbackFactory 属性来触发请求进行容灾 ...

  6. 从架构上来理解redis缓存和本地缓存的关系

    redis缓存和本地缓存混用是一种非常实用的实践方式. 优点:极大地降低了redis的读写频率,特别是处理特别耗时的业务逻辑(大于1分钟). 缺点:会产生一定的延时,这个延时具体的影响将会根据业务的差 ...

  7. 分布式缓存与本地缓存的区别

    分布式缓存与本地缓存的区别 转载自:https://ost.51cto.com/posts/1002 缓存的概念: 在服务端中,缓存主要是指将数据库的数据加载到内存中,之后对该数据的访问都在内存中完成 ...

  8. 分布式缓存和本地缓存的区别

    分布式缓存和本地缓存的区别 redis/memcached**分布式缓存**和map/guava**本地缓存**的区别 什么是缓存一致性? redis/memcached分布式缓存和map/guava ...

  9. 前端缓存 (http缓存 与 本地缓存)

    前端缓存主要是分为http缓存和本地缓存 http 缓存 强缓存:Expires(过期时间)/ Cache-Control(no-cache)(优先级高) 协商缓存:Last-Modified/Eta ...

最新文章

  1. Makefile与Shell的问题
  2. 【web安全】你的open_basedir安全吗?
  3. 向io设备发出中断请求_人们常说的计算机设备管理是什么,深入解读计算机设备管理...
  4. 启动Jupyter Notebook时出现Kernel error错误的解决方法
  5. Java堆空间– JRockit和IBM VM
  6. ajax传值 实体类_ajax传参到实体类对应字段
  7. Android 8.0 学习(12)---init.rc语法及解析过程总结
  8. 报名 | NVIDIA线下交流会:手把手教你搭建TensorFlow Caffe深度学习服务器
  9. mysql实现了四种通信协议_MySQL 通信协议
  10. VTD(Virtual Test Drive)
  11. Pygame游戏编程
  12. 【拖拽】拖动原理 拖动基本思路
  13. 转转转转转转转转转转转转转转转转转转转转转转转转转
  14. “大数据应用场景”之隔壁老王(连载四)
  15. VMware Workstation 12序列号: 5A02H-AU243-TZJ49-GTC7K-3C61N
  16. java数据透视表算法_java – 在数据透视表上对数组进行分区
  17. POJ前面的题目算法思路【转】
  18. 配置AAA认证和授权
  19. 【百练】圣诞老人的礼物-Santa Clau’s Gifts(c语言)
  20. 实时股票数据获取方式

热门文章

  1. 音频转换软件哪个比较好?这三个不错的软件值得使用
  2. 2020年4月30日 星期四 晴 爱情
  3. 原创_移动版天邑TY1611_晶晨S905L3-B_RTL8822CS机顶盒免拆卡刷包及线刷机包刷机教程
  4. 魔百盒CM102_晨星MSO9280芯片_安卓4.4.4_当贝桌面免拆卡刷及TTL固件包
  5. java左值与右值问题_什么是左值和右值
  6. 《大数据分析原理与实践》一一1.5 全书概览
  7. MATLAB 路径设置
  8. 存储器电路设计学习记录之 版图验证DRC LVS LPE 及后仿扫盲
  9. 剑指offer刷题 --前端(javascript)
  10. 打卡3本书10句话-24