当前位置: 首页 > news >正文

二级缓存在实际项目中的应用

二级缓存在项目中的应用

目录

  • 1. 二级缓存简介
  • 2. 应用场景
  • 3. 重难点分析
  • 4. 结合SpringBoot使用
  • 5. 最佳实践与案例
  • 6. 总结

1. 二级缓存简介

1.1 什么是二级缓存

二级缓存(Second-Level Cache) 是Hibernate框架中的一个重要特性,它提供了应用程序级别的缓存机制。与一级缓存(Session级别)不同,二级缓存是SessionFactory级别的缓存,可以在多个Session之间共享数据。

1.2 缓存层次结构

应用层缓存架构
├── 一级缓存 (L1 Cache)
│   ├── Session级别
│   ├── 生命周期短
│   └── 自动管理
├── 二级缓存 (L2 Cache)
│   ├── SessionFactory级别
│   ├── 生命周期长
│   └── 需要配置
└── 查询缓存 (Query Cache)├── 查询结果缓存├── 依赖二级缓存└── 需要显式启用

1.3 二级缓存的特点

  • 跨Session共享: 多个Session可以共享缓存数据
  • 生命周期长: 与SessionFactory生命周期一致
  • 可配置性: 支持多种缓存提供者
  • 透明性: 对应用程序透明,无需修改业务代码
  • 选择性缓存: 可以指定哪些实体需要缓存

1.4 支持的缓存提供者

缓存提供者特点适用场景
EHCache成熟稳定,功能丰富单机应用
Redis分布式,高性能集群环境
Hazelcast内存网格,分布式微服务架构
Caffeine高性能,低延迟高并发场景
Infinispan企业级,事务支持复杂业务场景

2. 应用场景

2.1 适用场景

2.1.1 读多写少的场景
// 用户信息查询 - 读多写少
@Entity
@Cacheable
public class User {@Idprivate Long id;private String username;private String email;// 用户信息变化不频繁,适合缓存
}
2.1.2 数据变化不频繁
// 字典数据 - 变化不频繁
@Entity
@Cacheable
public class Dictionary {@Idprivate Long id;private String type;private String code;private String value;// 字典数据相对稳定,适合缓存
}
2.1.3 复杂查询结果
// 统计报表数据 - 复杂查询
@Entity
@Cacheable
public class ReportData {@Idprivate Long id;private String reportType;private LocalDate reportDate;private BigDecimal amount;// 报表数据计算复杂,适合缓存
}

2.2 不适用场景

2.2.1 频繁更新的数据
// 实时数据 - 频繁更新
@Entity
public class RealTimeData {@Idprivate Long id;private BigDecimal price;private LocalDateTime updateTime;// 价格数据实时变化,不适合缓存
}
2.2.2 敏感数据
// 用户密码 - 敏感数据
@Entity
public class UserCredentials {@Idprivate Long id;private String password;private String salt;// 密码等敏感信息不应缓存
}

2.3 典型应用案例

2.3.1 电商系统
// 商品信息缓存
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Product {@Idprivate Long id;private String name;private BigDecimal price;private String description;private String category;// 商品信息相对稳定,适合缓存// 价格可能变化,需要及时更新
}
2.3.2 内容管理系统
// 文章内容缓存
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class Article {@Idprivate Long id;private String title;private String content;private String author;private LocalDateTime publishTime;// 已发布的文章内容不变,适合只读缓存
}
2.3.3 用户权限系统
// 角色权限缓存
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Role {@Idprivate Long id;private String roleName;@OneToMany(mappedBy = "role")private Set<Permission> permissions;// 角色权限变化不频繁,适合缓存
}

3. 重难点分析

3.1 技术难点

3.1.1 缓存一致性

难点: 保证缓存与数据库数据的一致性
解决方案:

// 缓存一致性策略配置
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User {@Idprivate Long id;private String username;private String email;// 使用READ_WRITE策略保证一致性// 读操作从缓存获取// 写操作同时更新缓存和数据库
}// 缓存更新策略
@Service
public class UserService {@Transactionalpublic User updateUser(User user) {// 1. 更新数据库User updatedUser = userRepository.save(user);// 2. 清除相关缓存evictUserCache(user.getId());// 3. 重新加载到缓存loadUserToCache(updatedUser.getId());return updatedUser;}private void evictUserCache(Long userId) {// 清除用户相关缓存cacheManager.getCache("userCache").evict(userId);}
}
3.1.2 缓存穿透

难点: 查询不存在的数据导致缓存失效
解决方案:

@Service
public class UserService {@Cacheable(value = "userCache", key = "#id")public User findById(Long id) {User user = userRepository.findById(id).orElse(null);if (user == null) {// 缓存空值,防止缓存穿透return new User(); // 返回空对象}return user;}// 布隆过滤器防止缓存穿透@Autowiredprivate BloomFilter<Long> userBloomFilter;public User findByIdWithBloomFilter(Long id) {// 先检查布隆过滤器if (!userBloomFilter.mightContain(id)) {return null; // 确定不存在}return findById(id);}
}
3.1.3 缓存雪崩

难点: 大量缓存同时失效导致数据库压力
解决方案:

@Service
public class UserService {@Cacheable(value = "userCache", key = "#id")public User findById(Long id) {// 添加随机过期时间,避免同时失效return userRepository.findById(id).orElse(null);}// 缓存预热@PostConstructpublic void warmUpCache() {List<User> users = userRepository.findAll();users.forEach(user -> {cacheManager.getCache("userCache").put(user.getId(), user);});}// 熔断机制@HystrixCommand(fallbackMethod = "getUserFallback")public User getUserWithCircuitBreaker(Long id) {return findById(id);}public User getUserFallback(Long id) {// 降级处理return new User();}
}

3.2 性能难点

3.2.1 内存管理

难点: 缓存占用大量内存
解决方案:

// EHCache配置
@Configuration
public class CacheConfig {@Beanpublic CacheManager cacheManager() {EhCacheManagerFactoryBean factory = new EhCacheManagerFactoryBean();factory.setConfigLocation(new ClassPathResource("ehcache.xml"));factory.setShared(true);EhCacheCacheManager cacheManager = new EhCacheCacheManager();cacheManager.setCacheManager(factory.getObject());return cacheManager;}
}// ehcache.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<ehcache><cache name="userCache"maxEntriesLocalHeap="1000"maxEntriesLocalDisk="10000"eternal="false"timeToIdleSeconds="300"timeToLiveSeconds="600"memoryStoreEvictionPolicy="LRU"diskPersistent="false"diskExpiryThreadIntervalSeconds="120"/>
</ehcache>
3.2.2 序列化性能

难点: 对象序列化影响性能
解决方案:

// 使用高效的序列化方式
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);// 使用Jackson序列化Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(serializer);template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(serializer);return template;}
}// 实体类优化
@Entity
@Cacheable
public class User implements Serializable {private static final long serialVersionUID = 1L;@Idprivate Long id;private String username;private String email;// 避免循环引用@JsonIgnore@OneToMany(mappedBy = "user")private Set<Order> orders;
}

3.3 业务难点

3.3.1 缓存策略选择

难点: 选择合适的缓存策略
解决方案:

// 不同场景的缓存策略
@Entity
@Cacheable
public class Product {@Idprivate Long id;private String name;private BigDecimal price;// 根据业务特点选择策略@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)private String description; // 可读写@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)private String category; // 只读@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)private Integer stock; // 非严格读写
}
3.3.2 缓存更新策略

难点: 确定何时更新缓存
解决方案:

@Service
public class ProductService {// 主动更新策略@Transactionalpublic Product updateProduct(Product product) {Product updated = productRepository.save(product);// 立即更新缓存cacheManager.getCache("productCache").put(product.getId(), updated);return updated;}// 延迟更新策略@Transactionalpublic Product updateProductLazy(Product product) {Product updated = productRepository.save(product);// 延迟更新缓存CompletableFuture.runAsync(() -> {cacheManager.getCache("productCache").put(product.getId(), updated);});return updated;}// 版本控制策略@Entity@Cacheablepublic class Product {@Idprivate Long id;private String name;@Versionprivate Long version; // 乐观锁版本// 版本变化时自动清除缓存}
}

4. 结合SpringBoot使用

4.1 环境准备

4.1.1 依赖配置
<!-- pom.xml -->
<dependencies><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Data JPA --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- Spring Boot Cache --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><!-- Hibernate Core --><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId></dependency><!-- EHCache --><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-ehcache</artifactId></dependency><!-- Redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
</dependencies>
4.1.2 配置文件
# application.yml
spring:datasource:url: jdbc:mysql://localhost:3306/testdbusername: rootpassword: passworddriver-class-name: com.mysql.cj.jdbc.Driverjpa:hibernate:ddl-auto: updateshow-sql: trueproperties:hibernate:cache:use_second_level_cache: trueuse_query_cache: trueregion:factory_class: org.hibernate.cache.ehcache.EhCacheRegionFactoryformat_sql: truecache:type: ehcacheehcache:config: classpath:ehcache.xmlredis:host: localhostport: 6379password: timeout: 2000mslettuce:pool:max-active: 8max-wait: -1msmax-idle: 8min-idle: 0

4.2 基础配置

4.2.1 缓存配置类
@Configuration
@EnableCaching
public class CacheConfig {// EHCache配置@Beanpublic CacheManager ehCacheManager() {EhCacheManagerFactoryBean factory = new EhCacheManagerFactoryBean();factory.setConfigLocation(new ClassPathResource("ehcache.xml"));factory.setShared(true);EhCacheCacheManager cacheManager = new EhCacheCacheManager();cacheManager.setCacheManager(factory.getObject());return cacheManager;}// Redis配置@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);// 序列化配置Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(serializer);template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(serializer);return template;}// 缓存键生成器@Beanpublic KeyGenerator keyGenerator() {return new KeyGenerator() {@Overridepublic Object generate(Object target, Method method, Object... params) {StringBuilder sb = new StringBuilder();sb.append(target.getClass().getName());sb.append(method.getName());for (Object obj : params) {sb.append(obj.toString());}return sb.toString();}};}
}
4.2.2 EHCache配置文件
<!-- ehcache.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"><!-- 默认缓存配置 --><defaultCachemaxEntriesLocalHeap="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"maxEntriesLocalDisk="10000000"diskExpiryThreadIntervalSeconds="120"memoryStoreEvictionPolicy="LRU"><persistence strategy="localTempSwap"/></defaultCache><!-- 用户缓存 --><cache name="userCache"maxEntriesLocalHeap="1000"eternal="false"timeToIdleSeconds="300"timeToLiveSeconds="600"memoryStoreEvictionPolicy="LRU"diskPersistent="false"/><!-- 商品缓存 --><cache name="productCache"maxEntriesLocalHeap="5000"eternal="false"timeToIdleSeconds="600"timeToLiveSeconds="1200"memoryStoreEvictionPolicy="LRU"diskPersistent="false"/><!-- 查询缓存 --><cache name="queryCache"maxEntriesLocalHeap="10000"eternal="false"timeToIdleSeconds="300"timeToLiveSeconds="600"memoryStoreEvictionPolicy="LRU"diskPersistent="false"/>
</ehcache>

4.3 实体类配置

4.3.1 基础实体类
@Entity
@Table(name = "users")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(unique = true, nullable = false)private String username;@Column(unique = true, nullable = false)private String email;@Column(name = "created_at")private LocalDateTime createdAt;@Column(name = "updated_at")private LocalDateTime updatedAt;// 关联实体不缓存,避免循环引用@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)@JsonIgnoreprivate Set<Order> orders = new HashSet<>();// 构造方法public User() {}public User(String username, String email) {this.username = username;this.email = email;this.createdAt = LocalDateTime.now();this.updatedAt = LocalDateTime.now();}// Getter和Setter方法// ...
}
4.3.2 商品实体类
@Entity
@Table(name = "products")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Product {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(nullable = false)private String name;@Column(columnDefinition = "TEXT")private String description;@Column(precision = 10, scale = 2)private BigDecimal price;@Column(name = "category_id")private Long categoryId;@Column(name = "stock_quantity")private Integer stockQuantity;@Column(name = "created_at")private LocalDateTime createdAt;@Column(name = "updated_at")private LocalDateTime updatedAt;// 构造方法public Product() {}public Product(String name, String description, BigDecimal price, Long categoryId) {this.name = name;this.description = description;this.price = price;this.categoryId = categoryId;this.stockQuantity = 0;this.createdAt = LocalDateTime.now();this.updatedAt = LocalDateTime.now();}// Getter和Setter方法// ...
}

4.4 服务层实现

4.4.1 用户服务
@Service
@Transactional
public class UserService {@Autowiredprivate UserRepository userRepository;@Autowiredprivate CacheManager cacheManager;// 根据ID查找用户(使用缓存)@Cacheable(value = "userCache", key = "#id")public User findById(Long id) {return userRepository.findById(id).orElseThrow(() -> new EntityNotFoundException("User not found with id: " + id));}// 根据用户名查找用户@Cacheable(value = "userCache", key = "#username")public User findByUsername(String username) {return userRepository.findByUsername(username).orElseThrow(() -> new EntityNotFoundException("User not found with username: " + username));}// 保存用户(清除相关缓存)@CacheEvict(value = "userCache", allEntries = true)public User save(User user) {user.setUpdatedAt(LocalDateTime.now());return userRepository.save(user);}// 更新用户(清除相关缓存)@CacheEvict(value = "userCache", key = "#user.id")public User update(User user) {user.setUpdatedAt(LocalDateTime.now());return userRepository.save(user);}// 删除用户(清除相关缓存)@CacheEvict(value = "userCache", key = "#id")public void deleteById(Long id) {userRepository.deleteById(id);}// 批量清除缓存@CacheEvict(value = "userCache", allEntries = true)public void clearUserCache() {// 清除所有用户缓存}// 手动缓存管理public void evictUserCache(Long userId) {Cache cache = cacheManager.getCache("userCache");if (cache != null) {cache.evict(userId);}}public void putUserToCache(User user) {Cache cache = cacheManager.getCache("userCache");if (cache != null) {cache.put(user.getId(), user);}}
}
4.4.2 商品服务
@Service
@Transactional
public class ProductService {@Autowiredprivate ProductRepository productRepository;@Autowiredprivate CacheManager cacheManager;// 根据ID查找商品@Cacheable(value = "productCache", key = "#id")public Product findById(Long id) {return productRepository.findById(id).orElseThrow(() -> new EntityNotFoundException("Product not found with id: " + id));}// 根据分类查找商品@Cacheable(value = "productCache", key = "'category:' + #categoryId")public List<Product> findByCategoryId(Long categoryId) {return productRepository.findByCategoryId(categoryId);}// 搜索商品@Cacheable(value = "productCache", key = "'search:' + #keyword")public List<Product> searchProducts(String keyword) {return productRepository.findByNameContainingIgnoreCase(keyword);}// 保存商品@CacheEvict(value = "productCache", allEntries = true)public Product save(Product product) {product.setUpdatedAt(LocalDateTime.now());return productRepository.save(product);}// 更新商品@CacheEvict(value = "productCache", key = "#product.id")public Product update(Product product) {product.setUpdatedAt(LocalDateTime.now());return productRepository.save(product);}// 更新库存@CacheEvict(value = "productCache", key = "#productId")public Product updateStock(Long productId, Integer quantity) {Product product = findById(productId);product.setStockQuantity(quantity);product.setUpdatedAt(LocalDateTime.now());return productRepository.save(product);}// 条件更新缓存@CacheEvict(value = "productCache", condition = "#product.price > 100")public Product updateExpensiveProduct(Product product) {return productRepository.save(product);}
}

4.5 控制器层

4.5.1 用户控制器
@RestController
@RequestMapping("/api/users")
public class UserController {@Autowiredprivate UserService userService;// 获取用户信息@GetMapping("/{id}")public ResponseEntity<User> getUser(@PathVariable Long id) {try {User user = userService.findById(id);return ResponseEntity.ok(user);} catch (EntityNotFoundException e) {return ResponseEntity.notFound().build();}}// 创建用户@PostMappingpublic ResponseEntity<User> createUser(@RequestBody User user) {User savedUser = userService.save(user);return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);}// 更新用户@PutMapping("/{id}")public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {try {user.setId(id);User updatedUser = userService.update(user);return ResponseEntity.ok(updatedUser);} catch (EntityNotFoundException e) {return ResponseEntity.notFound().build();}}// 删除用户@DeleteMapping("/{id}")public ResponseEntity<Void> deleteUser(@PathVariable Long id) {try {userService.deleteById(id);return ResponseEntity.noContent().build();} catch (EntityNotFoundException e) {return ResponseEntity.notFound().build();}}// 清除用户缓存@PostMapping("/cache/clear")public ResponseEntity<String> clearUserCache() {userService.clearUserCache();return ResponseEntity.ok("User cache cleared successfully");}
}
4.5.2 商品控制器
@RestController
@RequestMapping("/api/products")
public class ProductController {@Autowiredprivate ProductService productService;// 获取商品信息@GetMapping("/{id}")public ResponseEntity<Product> getProduct(@PathVariable Long id) {try {Product product = productService.findById(id);return ResponseEntity.ok(product);} catch (EntityNotFoundException e) {return ResponseEntity.notFound().build();}}// 根据分类获取商品@GetMapping("/category/{categoryId}")public ResponseEntity<List<Product>> getProductsByCategory(@PathVariable Long categoryId) {List<Product> products = productService.findByCategoryId(categoryId);return ResponseEntity.ok(products);}// 搜索商品@GetMapping("/search")public ResponseEntity<List<Product>> searchProducts(@RequestParam String keyword) {List<Product> products = productService.searchProducts(keyword);return ResponseEntity.ok(products);}// 创建商品@PostMappingpublic ResponseEntity<Product> createProduct(@RequestBody Product product) {Product savedProduct = productService.save(product);return ResponseEntity.status(HttpStatus.CREATED).body(savedProduct);}// 更新商品@PutMapping("/{id}")public ResponseEntity<Product> updateProduct(@PathVariable Long id, @RequestBody Product product) {try {product.setId(id);Product updatedProduct = productService.update(product);return ResponseEntity.ok(updatedProduct);} catch (EntityNotFoundException e) {return ResponseEntity.notFound().build();}}// 更新库存@PutMapping("/{id}/stock")public ResponseEntity<Product> updateStock(@PathVariable Long id, @RequestParam Integer quantity) {try {Product product = productService.updateStock(id, quantity);return ResponseEntity.ok(product);} catch (EntityNotFoundException e) {return ResponseEntity.notFound().build();}}
}

4.6 查询缓存

4.6.1 查询缓存配置
@Repository
public class UserRepository extends JpaRepository<User, Long> {// 启用查询缓存@QueryHints(@QueryHint(name = "org.hibernate.cacheable", value = "true"))@Query("SELECT u FROM User u WHERE u.username = :username")Optional<User> findByUsername(@Param("username") String username);// 复杂查询缓存@QueryHints(@QueryHint(name = "org.hibernate.cacheable", value = "true"))@Query("SELECT u FROM User u WHERE u.createdAt >= :startDate AND u.createdAt <= :endDate")List<User> findUsersByDateRange(@Param("startDate") LocalDateTime startDate, @Param("endDate") LocalDateTime endDate);// 统计查询缓存@QueryHints(@QueryHint(name = "org.hibernate.cacheable", value = "true"))@Query("SELECT COUNT(u) FROM User u WHERE u.createdAt >= :startDate")Long countUsersSince(@Param("startDate") LocalDateTime startDate);
}
4.6.2 查询缓存服务
@Service
public class UserQueryService {@Autowiredprivate UserRepository userRepository;// 缓存查询结果@Cacheable(value = "queryCache", key = "'users_by_date:' + #startDate + '_' + #endDate")public List<User> findUsersByDateRange(LocalDateTime startDate, LocalDateTime endDate) {return userRepository.findUsersByDateRange(startDate, endDate);}// 缓存统计结果@Cacheable(value = "queryCache", key = "'user_count_since:' + #startDate")public Long countUsersSince(LocalDateTime startDate) {return userRepository.countUsersSince(startDate);}// 清除查询缓存@CacheEvict(value = "queryCache", allEntries = true)public void clearQueryCache() {// 清除所有查询缓存}
}

5. 最佳实践与案例

5.1 缓存策略最佳实践

5.1.1 缓存粒度控制
// 细粒度缓存 - 单个实体
@Cacheable(value = "userCache", key = "#id")
public User findById(Long id) {return userRepository.findById(id).orElse(null);
}// 粗粒度缓存 - 列表数据
@Cacheable(value = "userListCache", key = "'all_users'")
public List<User> findAllUsers() {return userRepository.findAll();
}// 条件缓存 - 根据条件决定是否缓存
@Cacheable(value = "userCache", key = "#id", condition = "#id > 0")
public User findByIdConditional(Long id) {return userRepository.findById(id).orElse(null);
}
5.1.2 缓存更新策略
@Service
public class CacheUpdateService {@Autowiredprivate CacheManager cacheManager;// 立即更新策略@CachePut(value = "userCache", key = "#user.id")public User updateUserImmediate(User user) {return userRepository.save(user);}// 延迟更新策略@Async@CacheEvict(value = "userCache", key = "#user.id")public void updateUserLazy(User user) {userRepository.save(user);// 异步更新缓存CompletableFuture.runAsync(() -> {putUserToCache(user);});}// 批量更新策略@CacheEvict(value = "userCache", allEntries = true)public void batchUpdateUsers(List<User> users) {userRepository.saveAll(users);}
}

5.2 性能优化案例

5.2.1 缓存预热
@Component
public class CacheWarmupService {@Autowiredprivate UserService userService;@Autowiredprivate ProductService productService;@EventListener(ApplicationReadyEvent.class)public void warmupCache() {// 预热用户缓存warmupUserCache();// 预热商品缓存warmupProductCache();}private void warmupUserCache() {List<User> users = userService.findAll();users.forEach(user -> {userService.findById(user.getId()); // 触发缓存});}private void warmupProductCache() {List<Product> products = productService.findAll();products.forEach(product -> {productService.findById(product.getId()); // 触发缓存});}
}
5.2.2 缓存监控
@Component
public class CacheMonitorService {@Autowiredprivate CacheManager cacheManager;// 获取缓存统计信息public Map<String, Object> getCacheStats() {Map<String, Object> stats = new HashMap<>();cacheManager.getCacheNames().forEach(cacheName -> {Cache cache = cacheManager.getCache(cacheName);if (cache instanceof EhCache) {EhCache ehCache = (EhCache) cache;Map<String, Object> cacheStats = new HashMap<>();cacheStats.put("hitCount", ehCache.getStatistics().getCacheHits());cacheStats.put("missCount", ehCache.getStatistics().getCacheMisses());cacheStats.put("hitRate", ehCache.getStatistics().getCacheHitPercentage());stats.put(cacheName, cacheStats);}});return stats;}// 清理过期缓存@Scheduled(fixedRate = 300000) // 每5分钟执行一次public void cleanExpiredCache() {cacheManager.getCacheNames().forEach(cacheName -> {Cache cache = cacheManager.getCache(cacheName);if (cache instanceof EhCache) {((EhCache) cache).getNativeCache().evictExpiredElements();}});}
}

5.3 实际应用案例

5.3.1 电商系统缓存方案
// 商品详情页缓存策略
@Service
public class ProductDetailService {@Autowiredprivate ProductService productService;@Autowiredprivate ProductReviewService reviewService;// 商品详情页数据聚合@Cacheable(value = "productDetailCache", key = "#productId")public ProductDetailVO getProductDetail(Long productId) {Product product = productService.findById(productId);List<ProductReview> reviews = reviewService.findByProductId(productId);ProductStatistics stats = productService.getProductStatistics(productId);return ProductDetailVO.builder().product(product).reviews(reviews).statistics(stats).build();}// 商品列表页缓存@Cacheable(value = "productListCache", key = "#categoryId + '_' + #page + '_' + #size")public Page<Product> getProductList(Long categoryId, int page, int size) {return productService.findByCategoryId(categoryId, PageRequest.of(page, size));}
}
5.3.2 用户权限缓存方案
// 用户权限缓存
@Service
public class UserPermissionService {@Autowiredprivate UserRepository userRepository;@Autowiredprivate RoleRepository roleRepository;// 用户权限缓存@Cacheable(value = "userPermissionCache", key = "#userId")public UserPermissionVO getUserPermissions(Long userId) {User user = userRepository.findById(userId).orElse(null);if (user == null) {return null;}Set<Role> roles = user.getRoles();Set<Permission> permissions = new HashSet<>();roles.forEach(role -> {permissions.addAll(role.getPermissions());});return UserPermissionVO.builder().userId(userId).roles(roles).permissions(permissions).build();}// 权限检查public boolean hasPermission(Long userId, String permission) {UserPermissionVO userPermissions = getUserPermissions(userId);if (userPermissions == null) {return false;}return userPermissions.getPermissions().stream().anyMatch(p -> p.getName().equals(permission));}
}

6. 总结

6.1 二级缓存优势

  1. 性能提升: 减少数据库访问,提高响应速度
  2. 可扩展性: 支持多种缓存提供者,适应不同场景
  3. 透明性: 对业务代码透明,无需修改现有逻辑
  4. 灵活性: 支持细粒度缓存控制,可配置缓存策略

6.2 使用建议

  1. 合理选择缓存策略: 根据数据特点选择合适的并发策略
  2. 注意缓存一致性: 确保缓存与数据库数据的一致性
  3. 监控缓存性能: 定期监控缓存命中率和性能指标
  4. 合理设置过期时间: 根据业务需求设置合适的缓存过期时间
  5. 避免缓存雪崩: 使用随机过期时间,避免同时失效

6.3 注意事项

  1. 内存管理: 注意缓存占用内存,合理配置缓存大小
  2. 序列化性能: 选择高效的序列化方式
  3. 缓存穿透: 防止查询不存在数据导致缓存失效
  4. 缓存雪崩: 避免大量缓存同时失效
  5. 数据一致性: 确保缓存与数据库数据的一致性

二级缓存是提升应用性能的重要手段,合理使用可以显著提高系统响应速度和用户体验。在实际应用中,需要根据具体业务场景选择合适的缓存策略和配置参数。


文章转载自:

http://OR7QFefh.nrjLt.cn
http://mfRgwyYq.nrjLt.cn
http://EJJpn7lE.nrjLt.cn
http://a5K7UyNa.nrjLt.cn
http://uTslyKHo.nrjLt.cn
http://ThYFp9vP.nrjLt.cn
http://4HDvNicQ.nrjLt.cn
http://pvSJRZKu.nrjLt.cn
http://zSbsfzjv.nrjLt.cn
http://IcroqO9f.nrjLt.cn
http://QIR6a1y0.nrjLt.cn
http://bk65DjOk.nrjLt.cn
http://QO2yWDoR.nrjLt.cn
http://eTSRa5Ar.nrjLt.cn
http://oV23I9hY.nrjLt.cn
http://i0sSgkRU.nrjLt.cn
http://mHey8ewe.nrjLt.cn
http://RL6P25zE.nrjLt.cn
http://dNj8jkeD.nrjLt.cn
http://kEXON6Kr.nrjLt.cn
http://5hRbOmQq.nrjLt.cn
http://1OWBetjh.nrjLt.cn
http://ylqrOOL8.nrjLt.cn
http://lNjkdXZM.nrjLt.cn
http://n80ygHSm.nrjLt.cn
http://lkhmdntb.nrjLt.cn
http://04rvocie.nrjLt.cn
http://61uWjOJ9.nrjLt.cn
http://Ve6QhB2I.nrjLt.cn
http://d9h8FqHm.nrjLt.cn
http://www.dtcms.com/a/373843.html

相关文章:

  • 第14篇:循环神经网络(RNN)与LSTM:序列建模的利器
  • 【P02_AI大模型之调用LLM的方式】
  • 浅谈Go 语言开发 AI Agent
  • pgsql for循环一个 数据文本 修改数据 文本如下 ‘40210178‘, ‘40210175‘, ‘40210227‘, ‘40210204‘
  • 工业检测机器视觉为啥非用工业相机?普通相机差在哪?
  • 基于MATLAB的粒子群算法优化广义回归神经网络的实现
  • 25年9月通信基础知识补充1:NTN-TDL信道建模matlab代码(satellite-communications toolbox学习)
  • Aider AI Coding项目 流式处理架构深度分析
  • 打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程的智慧工业开源了
  • PAT 1103 Integer Factorization
  • WindowManagerService (WMS)
  • Tool | AI类网址收录
  • SU-03T语音模块的使用
  • kubernetes-lxcfs解决资源可见性问题
  • 235kw发动机飞轮设计说明书CAD+设计说明书
  • Day9 | 类、对象与封装全解析
  • 【財運到】股票期货盯盘助手V3-盯盘界面找不到了
  • “微服务“一词总是出现,它是什么?
  • 打包应用:使用 Electron Forge
  • 详解布隆过滤器
  • ArcGIS学习-16 实战-栅格数据可达性分析
  • MySQL全库检索关键词 - idea 工具 Full-Text Search分享
  • Android小工具:使用python生成适配不同分辨率的dimen文件
  • 基于Python的电影推荐系统【2026最新】
  • 【C语言入门级教学】内存函数
  • 第三届“陇剑杯”CTF比赛部分WP(Web部分和应急)
  • 人工智能-python-深度学习-神经网络VGG(详解)
  • Spring框架重点概述
  • vue2+el的树形穿梭框
  • JuiceFS分布式文件系统