Springboot - 16.二级分布式缓存集成


👀引导


👀中文文档


👀框架介绍

名称作用使用场景优点缺点速率
Spring Cache with Caffeine & RedisSpring Cache 抽象结合 Caffeine 和 Redis 创建二级缓存策略Spring Boot 项目,需要简单的二级缓存解决方案与 Spring 完美集成,配置简单需要额外的集成工作实现二级缓存高 (由于本地缓存)
J2Cache二级缓存策略的实现,结合了本地缓存和 Redis需要与多种缓存提供者结合的解决方案灵活,支持多种 L1 和 L2 缓存提供者可能需要额外配置和调优以获得最佳性能中到高 (取决于配置)
Hazelcast分布式数据网格解决方案,提供本地和分布式缓存大型分布式系统,需要数据网格和缓存功能功能丰富,支持分布式数据结构、查询和执行相对重量级,可能过于复杂对于简单的用例中到高 (取决于配置)
LayeringCache二级缓存策略的实现,结合了本地缓存如 Caffeine 和远程缓存如 Redis需要灵活的二级缓存策略,结合本地和远程缓存结合了本地和远程缓存的优势,配置灵活需要额外的集成和配置工作中到高 (取决于配置和网络延迟)

👀二级分布式缓存是什么

二级缓存的核心思想是将一个本地缓存和一个共享的分布式缓存结合在一起。第一级是本地缓存,提供快速访问,但其数据只在单个实例上。第二级是分布式缓存,所有应用实例共享它,但访问速度相对较慢。二级分布式缓存其实已经能够满足我们工作中的绝大部分项目,所以我没有集成更多级别的。

类别名称描述特点
本地缓存Caffeine一个高性能、可扩展的Java 8基础的本地缓存库。通常被用作第一级缓存。1. 基于大小、引用、到期等策略的驱逐策略。
2. 可以与LoadingCacheAsyncLoadingCache结合使用,实现在缓存未命中时自动加载数据。
共享的分布式缓存Redis一个分布式的键值存储,通常作为第二级缓存。-
Redisson一个在Redis上实现的Java内存数据网格。1. 为Java的各种集合、锁、信号量等提供了分布式版本。
2. 除了常规的Redis操作外。
序列化和反序列化Jackson一个用于处理JSON的Java库。在缓存结构中,用于序列化和反序列化对象,以便存储到或从Redis中检索。

👀二级分布式缓存的典型工作流程

步骤描述
步骤 1当请求某个数据时,首先检查第一级缓存(Caffeine)。
步骤 2如果在第一级缓存中找到数据,直接返回。
步骤 3如果在第一级缓存中未找到数据,检查第二级缓存(Redis)。
步骤 4如果在第二级缓存中找到数据,将其也存入第一级缓存,然后返回数据。
步骤 5如果两级缓存都未命中,从数据源(如数据库)获取数据,然后将数据存入两级缓存。
步骤 6在写入或更新数据时,首先更新数据源,然后使两级缓存中的相关数据失效或更新。

👀 二级分布式缓存常见问题

问题类型问题描述解决方案
缓存穿透查询不存在的数据,导致频繁查询数据库- 布隆过滤器:使用布隆过滤器判断可能存在的key。
- 空值缓存:设置空值缓存并较短过期时间。
缓存雪崩大量缓存同时过期,导致请求转发到数据库- 随机过期时间:为每个缓存项设置随机过期时间。
- 缓存预热:在缓存过期前预先加载数据。
- 分布式锁:使用分布式锁控制缓存加载。
缓存击穿热点key失效,导致大量请求转发到数据库- 永不过期策略:对于热点数据设置永不过期或手动维护。
- 互斥锁:使用锁控制并发加载数据。

👀二级分布式缓存的序列化问题

✌Caffeine和Redis

特性Caffeine缓存Redis缓存
存储位置在JVM内存中,直接存储对象。在网络中,通过序列化后的格式存储。
序列化和反序列化不需要序列化和反序列化,对象以原始形式存储。需要将对象序列化为可在网络上传输的格式,然后反序列化。
跨多个JVM或服务器实例的使用不适用,Caffeine通常用于单个JVM内存中的缓存。适用,Redis通常用于跨多个JVM或服务器实例之间的数据共享。
数据一致性和迁移数据迁移时需要确保序列化和反序列化方式一致。应确保序列化和反序列化方式一致,以便在不同系统之间正确共享数据。
二级缓存管理器在二级缓存管理器中可以处理数据的序列化和反序列化。在Redis客户端或中间件中通常处理序列化和反序列化。

✌Jackson

可处理的Java类型:

Java类型处理方式
基本数据类型
包装类型
字符串和字符
集合类型
Java Beans
枚举类型
数组
常见的Java库对象
Java 8日期和时间API使用jackson-datatype-jsr310模块
其他Java 8+类型使用其他Jackson模块

需要特殊处理或额外配置:

情况解决方法
循环引用使用@JsonManagedReference@JsonBackReference@JsonIdentityInfo注解
抽象类和接口使用@JsonTypeInfo和相关注解
懒加载的实体使用jackson-datatype-hibernate模块或其他适当的模块
Java代理对象需要特殊处理或配置以避免序列化问题
Java 8的Optional在较早版本中可能需要额外的配置
Java 8的日期和时间API使用jackson-datatype-jsr310模块
自定义类型编写自定义的序列化器和反序列化器
静态字段和transient字段默认情况下不会序列化,但可以自定义序列化器来处理
Java I/O类型不适合序列化为JSON,需要特殊处理
线程、锁和其他低级并发对象不应该被序列化,需要特殊处理或配置以排除
Java GUI组件不应该被序列化为JSON,需要特殊处理或配置以排除

👀二级分布式缓存的实现原理

✌1. Spring Cache核心接口

名称作用使用原理
CacheManager提供访问缓存的能力作为一个中心的接口,负责管理多个缓存容器
Cache代表缓存容器,提供基本的缓存操作提供如 get, put, evict 等基本的缓存操作
@Cacheable声明某个方法的结果是可以缓存的在方法执行前检查是否已缓存结果,如果有则直接返回缓存的值,否则执行方法并缓存结果
@CachePut总是导致方法被执行并将结果存入缓存方法总是被执行,并将结果缓存或覆盖之前的缓存
@CacheEvict在方法执行后移除缓存方法执行后,移除指定的缓存
@Caching允许多种缓存规则的组合定义一个或多个 @Cacheable, @CacheEvict, @CachePut 的组合,以应对复杂的缓存逻辑
@CacheConfig类级别的缓存共享配置在类级别提供公共的缓存配置
CacheResolver解析用于方法调用的缓存定制如何解析使用的缓存
KeyGenerator生成缓存键定制如何为缓存项生成键

✌2. Spring Cache工作流程

+----------------------------------------------------------------------------------+
|                                    我的服务                                       |
+----------------------------------------------------------------------------------+
|   开始                                                                           
|    |                                                                             
|    v                                                                             
|   +-----------------+   触发:服务方法被调用                                      
|   |     @Caching    | --------------->                                           
|   +-----------------+                                                            
|    |                                                                             
|    v                                                                             
|   +---------------------+                                                        
|   | 调用带有 @Cacheable  |                                                        
|   | 注解的方法           |                                                        
|   +---------------------+                                                        
|    |                                                                            
|    v                                                                             
|   +---------------------+                                                        
|   | Spring AOP代理拦截  |                                                         
|   | 方法调用             |                                                        
|   +---------------------+                                                        
|    |                                                                             
|    v                                                                             
|   +-----------------+   触发:定义如TTL、最大项数                                  
|   |    CacheConfig  | --------------->                                            
|   +-----------------+                                                             
|    |                                                                             
|    v                                                                             
|   +-----------------+   触发:管理缓存实例如EhCacheRedis                         
|   |   CacheManager  | --------------->                                            
|   +-----------------+                                                             
|    |                                                                              
|    v                                                                             
|   +-----------------+   触发:决定使用哪个缓存实例                                 
|   |  CacheResolver  | --------------->                                            
|   +-----------------+                                                             
|    |                                                                             
|    v                                                                             
|   +-----------------+   触发:生成缓存键如基于方法参数                             
|   |   KeyGenerator  | --------------->                                            
|   +-----------------+                                                             
|    |                                                                             
|    v                                                                             
|   +---------------------+                                                        
|   | 通过CacheManager|                                                        
|   | 询对应的Cache       |                                                        
|   +---------------------+                                                        
|    |                                                                             
|    v                                                                             
|   +-------------------------+                                                    
|   | Cache中是否存在对应数据?|                                                     
|   +-------------------------+                                                    
|    |       |                                                                      
|   是       否                                                                     
|    v       v                                                                      
|   +---------------------+   +---------------------+                               
|   | 返回缓存中的数据     |   | 调用原始方法获取数据 |                               
|   +---------------------+   +---------------------+                               
|                             |                                                     
|                             v                                                     
|                    +---------------------+                                        
|                    | 存储数据到Cache|                                         
|                    +---------------------+                                        
|                             |                                                     
|                             v                                                     
|                    +---------------------+                                        
|                    | 返回数据给调用者    |                                         
|                    +---------------------+                                        
|                             |                                                     
|                             v                                                     
|                             结束                                                  
+----------------------------------------------------------------------------------+


✌3. Spring Cache不支持批量缓存

Spring Framework的Cache抽象确实没有直接提供批量缓存的内置支持。Spring的缓存注解(如@Cacheable、@CachePut、@CacheEvict等)主要用于单个方法调用的缓存管理,而不是针对一组方法的批量缓存。

Spring缓存注解描述触发缓存接口方法
@Cacheable用于标记方法,表示方法的结果应该被缓存,当相同的参数被传递给方法时,缓存会被命中并返回结果。触发 get 操作和 put 操作
@CachePut用于标记方法,表示方法的结果应该被缓存,但不论何时调用,都会强制更新缓存。触发 put 操作
@CacheEvict用于标记方法,表示方法的结果应该从缓存中移除,通常在方法执行后调用,以清除缓存中的数据。触发 evict 操作
  • 原有的@Cacheable@CachePut@CacheEvict
  • 自定义@BatchCacheable, @BatchCachePut, 和 @BatchCacheEvict

✌4. Spring Cache同时配置Redis和Redisson

Redis和Redisson配置注意事项
Redis配置- 需要确保与Redis服务器连接的信息正确匹配,包括主机地址、端口、密码等。 - 应根据应用程序的需求配置Redis的数据持久化选项,以确保数据一致性和持久化需求得到满足。
Redisson配置- Redisson配置通常包括连接到Redis服务器的信息,确保与Redis配置一致。 - Redisson还包括对分布式数据结构和锁等功能的配置,应根据应用程序需求进行调整。
关系和注意事项- Redis和Redisson通常可以和谐共存,它们在不同层面上与Redis进行交互,不会直接冲突。 - 在配置过程中,确保Redis和Redisson的配置信息准确、一致,以避免潜在问题。 - 确保应用程序正确使用Redis和Redisson提供的功能和API,以充分利用它们的优势。

👀 二级分布式缓存的实现方案

✌需求分析

缓存层级缓存实现策略说明
一级缓存Caffeine一级缓存通常是应用程序内部的内存缓存,用于快速读取和写入数据,提高访问速度。
二级缓存Redis二级缓存通常是分布式缓存,用于在多个服务或节点之间共享数据,确保数据的一致性和可靠性。
多服务Redisson 分布式锁对于多服务环境,使用 Redisson 客户端提供的分布式锁实现。这可以确保在分布式环境中的线程安全。
单服务双重检查锁策略对于单服务环境,使用双重检查锁策略实现线程安全,以避免多个线程同时加载同一个键的数据。

✌配置分析

模式Redis 配置Redisson 配置原因
单节点模式yml 中配置单节点 Redis 信息yml 中配置 Redisson 和单节点 Redis 信息,配合代码配置其他功能单节点模式相对简单,只需配置单个 Redis 服务器。但 Redisson 可以提供额外的分布式功能,需要在代码中配置。
哨兵模式yml 中配置哨兵 Redis 信息yml 中配置 Redisson 和哨兵 Redis 信息,配合代码配置其他功能哨兵模式提供了高可用性,需要在配置文件中指定哨兵节点。 Redisson 可以在代码中配置分布式功能。
集群模式yml 中配置 Redis 集群信息yml 中配置 Redisson 和 Redis 集群信息,配合代码配置其他功能集群模式提供了数据分片和高可用性,需要指定多个节点。 Redisson 可以在代码中配置其他功能。

✌序列化分析

技术是否需要序列化序列化建议应用场景Java代码配置
Caffeine不适用内存中的数据缓存不适用
Redis序列化为二进制或其他常见格式缓存、数据存储、消息队列、分布式锁等使用Spring Boot的RedisTemplate,序列化工具为GenericJackson2JsonRedisSerializer
Redisson序列化为Java对象,确保可序列化分布式集合、分布式锁、分布式对象、分布式计算等使用Redisson的Config。要在Redisson的GenericJackson2JsonCodec extends BaseCodec中使用GenericJackson2JsonRedisSerializer 的配置,可以考虑从后者获取ObjectMapper并将其传递给前者。
  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

yueerba126

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

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

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

打赏作者

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

抵扣说明:

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

余额充值