如何在服务器上搭建网站,活动手机网站开发,wordpress样式多的编辑器,wordpress版微信小程序群3【黑马点评优化】之使用CaffeineRedis实现应用级二层缓存 1 缓存雪崩定义及解决方案2 为什么要使用多级缓存3 RedisCaffeine实现应用层二级缓存原理4 利用CaffeineRedis解决Redis突然宕机导致的缓存雪崩问题4.1 pom.xml文件引入相关依赖4.2 本地缓存配置类4.3 修改ShopServiceI… 【黑马点评优化】之使用CaffeineRedis实现应用级二层缓存 1 缓存雪崩定义及解决方案2 为什么要使用多级缓存3 RedisCaffeine实现应用层二级缓存原理4 利用CaffeineRedis解决Redis突然宕机导致的缓存雪崩问题4.1 pom.xml文件引入相关依赖4.2 本地缓存配置类4.3 修改ShopServiceImpl中的queryById方法 5 测试 在这里修改一下黑马点评2商户查询的方法。使用RedisCaffeine实现应用层二级缓存来解决缓存雪崩 的问题。 添加Caffeine的过程参考博客如下 SpringBoot 集成 Caffeine、Redis实现双重缓存方式(-)caffeine redis-CSDN博客
1 缓存雪崩定义及解决方案
缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机导致大量请求到达数据库带来巨大压力。 解决方案 ● 给不同的Key的TTL添加随机值 同一时段所以给不同key设置不同的TTL ● 利用Redis集群提高服务的可用性 ● 给缓存业务添加降级限流策略 微服务 ● 给业务添加多级缓存
2 为什么要使用多级缓存
如果只使用redis来做缓存我们会有大量的请求到redis但是每次请求的数据都是一样的假如这一部分数据就放在应用服务器本地那么就省去了请求redis的网络开销请求速度就会快很多 如果只使用Caffeine来做本地缓存我们的应用服务器的内存是有限并且单独为了缓存去扩展应用服务器是非常不划算。所以只使用本地缓存也是有很大局限性的 因此在项目中我们可以将热点数据放本地缓存作为一级缓存将非热点数据放redis缓存作为二级缓存减少Redis的查询压力。
使用流程大致如下
首先从一级缓存caffeine-本地应用内中查找数据如果没有的话则从二级缓存redis-内存中查找数据如果还是没有的话再从数据库数据库-磁盘中查找数据
3 RedisCaffeine实现应用层二级缓存原理
Redis 作为分布式缓存
Redis 具有高性能、丰富的数据结构和可扩展性适合作为分布式缓存存储大量的数据。它可以在多服务器环境下共享缓存数据提高系统的整体性能。可以根据数据的特点选择合适的数据结构来存储数据如使用哈希表存储对象、使用有序集合进行排行榜等操作。配置 Redis 的持久化机制以防止数据丢失。同时考虑使用 Redis 的集群或主从复制来提高可用性和可扩展性。
Caffeine 作为本地缓存
Caffeine 是一个高效的本地缓存库可以在应用程序内部实现缓存减少对外部缓存服务的依赖提高缓存的访问速度。Caffeine 支持自动过期功能可以根据设定的时间自动清除过期的缓存数据减少内存占用。可以根据数据的访问频率和大小来调整 Caffeine 的缓存配置如缓存的大小、过期时间等。 实现二级缓存架构
数据存储流程
当应用程序需要访问数据时首先从 Caffeine 本地缓存中查找数据。如果数据在 Caffeine 中存在则直接返回数据无需进一步访问 Redis 或数据库如果数据不在 Caffeine 中则从 Redis 分布式缓存中查找数据。如果数据在 Redis 中存在则将数据加载到 Caffeine 中并返回数据给应用程序。如果数据不在 Redis 中则从数据库中读取数据并将数据同时存储到 Redis 和 Caffeine 中然后返回数据给应用程序。
数据更新流程
当数据在数据库中被更新时需要同时更新 Redis 和 Caffeine 中的缓存数据以保证数据的一致性可以采用先更新数据库然后删除 Redis 中的对应数据让后续的访问从数据库中重新读取数据并更新到 Redis 和 Caffeine 中的方式来实现数据的更新。这种方式被称为 Cache Aside 模式。
缓存过期策略
对于 Caffeine 本地缓存可以设置自动过期时间根据数据的变化频率和访问频率来调整过期时间以避免内存占用过高。对于 Redis 分布式缓存可以根据业务需求设置合理的过期时间或者采用主动更新的方式来保证缓存数据的有效性。
4 利用CaffeineRedis解决Redis突然宕机导致的缓存雪崩问题
需求修改根据id查询商铺的业务基于二级缓存方式来解决缓存雪崩问题。 思路分析当用户开始查询时先查询本地缓存Caffeine判断是否命中如果没有命中则查询Redis命中则直接返回。 4.1 pom.xml文件引入相关依赖 !--引入本地缓存Caffine--dependencygroupIdcom.github.ben-manes.caffeine/groupIdartifactIdcaffeine/artifactIdversion2.9.2/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-cache/artifactId/dependency4.2 本地缓存配置类
Config目录下新建本地缓存配置类LocalCacheConfiguration
package com.hmdp.config;import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.concurrent.TimeUnit;import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.concurrent.TimeUnit;/*** 本地缓存Caffeine配置类*/
Configuration
public class LocalCacheConfiguration {Bean(localCacheManager)public CacheString, Object localCacheManager() {return Caffeine.newBuilder()//写入或者更新5s后缓存过期并失效, 实际项目中肯定不会那么短时间就过期根据具体情况设置即可.expireAfterWrite(120, TimeUnit.SECONDS)// 初始的缓存空间大小.initialCapacity(50)// 缓存的最大条数通过 Window TinyLfu算法控制整个缓存大小.maximumSize(500)//打开数据收集功能.recordStats().build();}}4.3 修改ShopServiceImpl中的queryById方法
public class ShopServiceImpl extends ServiceImplShopMapper, Shop implements IShopService {Resourceprivate CacheString,Object caffeineCache;// Cacheable(value shop,key #id)/public Result queryById(Long id){//1.从Caffeine中查询数据Object o caffeineCache.getIfPresent(CACHE_SHOP_KEY id);if(Objects.nonNull(o)){log.info(从Caffeine中查询到数据...);return Result.ok( o);}//缓存穿透Shop shop cacheClient.queryWithPassThrough(CACHE_SHOP_KEY,id,Shop.class,this::getById,CACHE_SHOP_TTL,TimeUnit.MINUTES);if(shop ! null){log.info(从Redis中查到数据);caffeineCache.put(CACHE_SHOP_KEYid,shop);}if(shop null){return Result.fail(店铺不存在);}//7.返回数据return Result.ok(shop);}
}caffeineCache.put(user.getId(), user)保存本地缓存caffeineCache.invalidate(id)移除指定的本地缓存caffeineCache.getIfPresent(id) 从本地缓存中获取值如果缓存中不存指定的值则方法将返回 nullcaffeineCache.get(id, Function) 从本地缓存中获取值该方法还支持将一个参数为 key 的 Function 作为参数传入。如果缓存中不存在该 key则该函数将用于提供默认值该值在计算后插入缓存中如果缓存的元素无法生成或者在生成的过程中抛出异常而导致生成元素失败则返回null。
5 测试
运行启动类使用前后端联调来测试查询商铺信息功能。运行结果如下首次查询Caffeine中没有数据所以输出从Redis中查询第二次查询相同店铺时从Caffeine中查询。