项目
博客
文档
归档
资源链接
关于我
项目
博客
文档
归档
资源链接
关于我
49| 微服务性能优化之分布式缓存
2024-09-24
·
·
原创
·
·
本文共 317个字,预计阅读需要 2分钟。
### 分布式缓存和本地缓存 缓存 - 程序经常要调用的对象存在内存中,方便其使用时可以快速调用,不必去数据库或者其他持久化设备中查询,主要就是提高性能 - DNS缓存、前端缓存、代理服务器缓存Nginx、应用程序缓存(本地缓存、分布式缓存)、数据库缓存 分布式缓存 - 与应用分离的缓存组件或服务,与本地应用隔离一个独立的应用,多个应用可直接的共享缓存 - 常见的分布式缓存Redis、Memcached等 本地缓存 - 和业务程序一起的缓存,例如myabtis的一级或者二级缓存,本地缓存自然是最快的,但是不能在多个节点共享 - 常见的本地缓存:ssm基础课程myabtis 一级缓存、mybatis二级缓存;框架本身的缓存; redis本地单机服务;ehchche;guava cache、Caffeine等 选择本地缓存和分布式缓存 - 和业务数据结合去选择 - 高并发项目里面一般都是有本地缓存和分布式缓存共同存在的 ### 缓存穿透-击穿和雪崩 - 缓存击穿 (某个热点key缓存失效了) - 缓存中没有但数据库中有的数据,假如是热点数据,那key在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力增大。 - 和缓存雪崩的区别在于这里针对某一key缓存,后者则是很多key。 - 预防:设置热点数据不过期,定时任务定时更新缓存,或者设置互斥锁 - 缓存穿透(查询不存在数据) - 查询一个不存在的数据,由于缓存是不命中的,并且出于容错考虑,如发起为id为“-1”不存在的数据 - 如果从存储层查不到数据则不写入缓存这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。存在大量查询不存在的数据,可能DB就挂掉了,这也是黑客利用不存在的key频繁攻击应用的一种方式。 - 预防:接口层增加校验,数据合理性校验,缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,设置短点的过期时间,防止同个key被一直攻击 - 缓存雪崩 (多个热点key都过期) - 大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩 - 预防:存数据的过期时间设置随机,防止同一时间大量数据过期现象发生,设置热点数据永远不过期,定时任务定时更新 ### 微服务项目-SpringCache缓存框架 * SpringCache简介 * 自Spring 3.1起,提供了类似于@Transactional注解事务的注解Cache支持,且提供了Cache抽象 * 提供基本的Cache抽象,方便切换各种底层Cache * 只需要更少的代码就可以完成业务数据的缓存 * 提供事务回滚时也自动回滚缓存,支持比较复杂的缓存逻辑 * 核心:一个是Cache接口,缓存操作的API;一个是CacheManager管理各类缓存,有多个缓存框架的实现 * 更多详细操作和定制-可以看,小滴课堂Redis6专题视频 * 微服务中引入 * common项目中添加依赖 ```xml
org.springframework.boot
spring-boot-starter-cache
``` * 配置文件指定缓存类型 ```redis spring: cache: type: redis ``` * 启动类开启缓存注解 ```java @EnableCaching ``` * 修改redis缓存序列化器 ```java @Configuration @EnableCaching public class CustomRedisCacheManager extends CachingConfigurerSupport { @Bean public RedisCacheConfiguration redisCacheConfiguration(){ Jackson2JsonRedisSerializer
jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig(); configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)).entryTtl(Duration.ofMinutes(1)); return configuration; } } ``` ### 优惠券微服务-整合分布式缓存redis * 几个注解快速回顾 ```java @CachePut // 应用到写数据的方法上,如新增/修改方法,调用方法时会自动把相应的数据放入缓存 @CacheEvict // 清空对应的缓存 @Cacheable // 读取的数据放到缓存中 @Caching //组合上面的3个注解进行使用 ``` * 优惠券列表分页缓存 * 缓存名,它指定了你的缓存存放在哪块命名空间 * key里面是el表达式,所以如果是拼接字符串需要用单引号 ```java @Cacheable(value = {"coupon"},key = "#root.methodName + #page+'_'+#size") ``` ### 关于分布式缓存的思考和接口QPS的描述 * 其他微服务大家可以根据需要进行添加 * 最终看业务是否接收短暂的数据不一致【缓存和数据库】 * 缓存过期时间不宜过长 * 性能要求高前提,极端情况下存在短暂的不一致 * 使用缓存的话,一般是最终一致性 * 微服务只读接口使用了缓存 * 内网压测,暂停其他相关的高负载进程,4核8g配置 * 单机qps可以到达2~3万 * 写接口的话看链路 * 下单 100~500 * 注册 1000 * 登录 1万 * 收藏 1万 * 加购 1万