Redis + Caffeine多级缓存电商场景深度解析

embedded/2025/4/1 14:03:59/

Redis + Caffeine多级缓存

  • Redis + Caffeine多级缓存电商场景深度解析
    • 一、实施目的
    • 二、具体实施
      • 2.1 架构设计
      • 2.2 组件配置
      • 2.3 核心代码实现
    • 三、实施效果
      • 3.1 性能指标对比
      • 3.2 业务指标改善
      • 3.3 系统稳定性
    • 四、关键策略
      • 4.1 缓存预热
      • 4.2 一致性保障
      • 4.3 监控配置
        • Prometheus监控指标
    • 电商多级缓存完整实现方案
      • 1. 基础配置
        • 1.1 Maven依赖
        • 1.2 配置文件
      • 2. 核心实现类
        • 2.1 缓存配置类
        • 2.2 商品服务实现
        • 2.3 库存服务实现
      • 3. 辅助组件
        • 3.1 缓存预热
        • 3.2 监控端点
      • 关键点说明
        • 1. 多级缓存流程
        • 2. 缓存策略
        • 3. 一致性保障
        • 4. 监控能力
        • 5. 性能优化

Redis + Caffeine多级缓存电商场景深度解析

一、实施目的

  1. 性能优化

    • 降低商品详情页访问延迟
    • 提升系统整体吞吐量
  2. 成本控制

    • 减少Redis集群规模
    • 降低数据库查询压力
  3. 稳定性保障

    • 应对秒杀等高并发场景
    • 实现故障自动降级

二、具体实施

2.1 架构设计

用户请求 → Nginx → 应用服务器(Caffeine) → Redis集群 → MySQL/分库分表

2.2 组件配置

Caffeine配置

spring.cache.caffeine.spec=maximumSize=50000,expireAfterWrite=60s,refreshAfterWrite=30s,recordStats

Redis集群配置

spring.redis.cluster.nodes=192.168.1.101:6379,192.168.1.102:6379
spring.redis.lettuce.pool.max-active=500
spring.redis.lettuce.pool.max-wait=2000

2.3 核心代码实现

商品查询服务

public ProductDetail getProductDetail(Long productId) {// 本地缓存查询ProductDetail detail = caffeineCache.get(productId, k -> {// Redis查询String redisKey = "pd:" + productId;ProductDetail value = redisTemplate.opsForValue().get(redisKey);if (value == null) {// 数据库查询value = productDao.findById(productId);// 异步写入Redisexecutor.execute(() -> {redisTemplate.opsForValue().set(redisKey, value,60 + ThreadLocalRandom.current().nextInt(30),TimeUnit.MINUTES);});}return value;});return detail;
}

库存扣减服务

public boolean deductStock(Long productId, int num) {// 本地库存标记if (!localStockMark.tryLock(productId)) {return false;}try {// Redis原子扣减Long remain = redisTemplate.execute(new DefaultRedisScript<>("local stock = tonumber(redis.call('GET', KEYS[1]))\n" +"if stock >= tonumber(ARGV[1]) then\n" +"    return redis.call('DECRBY', KEYS[1], ARGV[1])\n" +"else\n" +"    return -1\n" +"end",Long.class),Collections.singletonList("stock:" + productId),String.valueOf(num));if (remain >= 0) {// 异步记录库存变更mq.sendStockMessage(productId, num);return true;}return false;} finally {localStockMark.unlock(productId);}
}

三、实施效果

3.1 性能指标对比

指标单Redis架构多级缓存架构提升幅度
平均响应时间68ms9ms655%
峰值QPS12万85万608%
数据库查询量100%8%减少92%

3.2 业务指标改善

  1. 秒杀场景

    • 下单成功率从35%提升至89%
    • 超卖问题完全杜绝
  2. 常规场景

    • 商品详情页加载时间从1.2s→180ms
    • 服务器成本降低40%

3.3 系统稳定性

  1. Redis故障时:

    • 核心商品仍可提供服务
    • 系统存活时间从<1分钟延长至30分钟
  2. 大促期间:

    • 流量波动减少70%
    • CPU负载降低55%

四、关键策略

4.1 缓存预热

@Scheduled(cron = "0 0 3 * * ?")
public void dailyPreheat() {List<Long> hotItems = hotProductService.predictHotItems();hotItems.parallelStream().forEach(id -> {ProductDetail detail = productDao.getDetail(id);caffeineCache.put(id, detail);redisTemplate.opsForValue().set("pd:" + id,detail,6, TimeUnit.HOURS);});
}

4.2 一致性保障

@Transactional
public void updateProduct(Product product) {// 1.删除缓存caffeineCache.invalidate(product.getId());redisTemplate.delete("pd:" + product.getId());// 2.更新数据库productDao.update(product);// 3.延迟双删executor.schedule(() -> {redisTemplate.delete("pd:" + product.getId());}, 1, TimeUnit.SECONDS);
}

4.3 监控配置

Prometheus监控指标
 name: cache_hit_rateexpr: rate(caffeine_cache_hits_total[5m]) / (rate(caffeine_cache_hits_total[5m]) +  rate(caffeine_cache_misses_total[5m]))name: redis_latencyexpr: histogram_quantile(0.99, rate(redis_command_duration_seconds_bucket[1m]))

电商多级缓存完整实现方案

1. 基础配置

1.1 Maven依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>3.1.8</version></dependency>
</dependencies>
1.2 配置文件
spring:redis:host: 127.0.0.1port: 6379password: yourpasswordlettuce:pool:max-active: 16max-wait: 1000msmax-idle: 8caffeine:specs:productCache: maximumSize=10000,expireAfterWrite=60s,recordStatsstockCache: maximumSize=5000,expireAfterWrite=10s

2. 核心实现类

2.1 缓存配置类
@Configuration
@EnableCaching
public class CacheConfig {@Beanpublic CacheManager cacheManager() {CaffeineCacheManager cacheManager = new CaffeineCacheManager();cacheManager.registerCustomCache("products", Caffeine.from(caffeineProperties().getSpec("productCache")).build());cacheManager.registerCustomCache("stocks",Caffeine.from(caffeineProperties().getSpec("stockCache")).build());return cacheManager;}@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(factory);template.setKeySerializer(new StringRedisSerializer());template.setValueSerializer(new GenericJackson2JsonRedisSerializer());return template;}
}
2.2 商品服务实现
@Service
public class ProductServiceImpl implements ProductService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Cacheable(cacheNames = "products", key = "#productId")@Overridepublic ProductDetail getProductDetail(Long productId) {String redisKey = "product:" + productId;ProductDetail detail = (ProductDetail) redisTemplate.opsForValue().get(redisKey);if (detail == null) {detail = loadFromDB(productId);redisTemplate.opsForValue().set(redisKey, detail,60 + ThreadLocalRandom.current().nextInt(30),TimeUnit.MINUTES);}return detail;}private ProductDetail loadFromDB(Long productId) {// 数据库查询实现return productRepository.findById(productId);}
}
2.3 库存服务实现
@Service
public class StockServiceImpl implements StockService {@Autowiredprivate RedisTemplate<String, Object> redisTemplate;@Cacheable(cacheNames = "stocks", key = "#productId")@Overridepublic Integer getStock(Long productId) {String redisKey = "stock:" + productId;Integer stock = (Integer) redisTemplate.opsForValue().get(redisKey);if (stock == null) {stock = loadStockFromDB(productId);redisTemplate.opsForValue().set(redisKey,stock,10, TimeUnit.SECONDS);}return stock;}@CacheEvict(cacheNames = "stocks", key = "#productId")@Overridepublic boolean deductStock(Long productId, int quantity) {// 库存扣减逻辑return stockRepository.deductStock(productId, quantity);}
}

3. 辅助组件

3.1 缓存预热
@Component
public class CacheWarmUp implements CommandLineRunner {@Autowiredprivate ProductService productService;@Overridepublic void run(String... args) {List<Long> hotProducts = Arrays.asList(1001L, 1002L, 1003L);hotProducts.parallelStream().forEach(productService::getProductDetail);}
}
3.2 监控端点
@RestController
@RequestMapping("/cache")
public class CacheMonitorController {@Autowiredprivate CacheManager cacheManager;@GetMapping("/stats")public Map<String, Object> getCacheStats() {Map<String, Object> stats = new HashMap<>();CaffeineCache productsCache = (CaffeineCache) cacheManager.getCache("products");if (productsCache != null) {stats.put("products", productsCache.getNativeCache().stats());}return stats;}
}

关键点说明

1. 多级缓存流程
  1. 先查Caffeine本地缓存
  2. 未命中则查Redis
  3. 仍未命中则查数据库
  4. 回填各级缓存
2. 缓存策略
数据类型本地缓存TTLRedis TTL
商品数据60秒30-90分钟(随机)
库存数据10秒10秒
3. 一致性保障
  1. 使用@CacheEvict保证更新时缓存失效
  2. 库存采用短过期时间自动刷新
4. 监控能力
  1. 通过/cache/stats端点暴露缓存命中率
  2. 集成Spring Boot Actuator
5. 性能优化
  1. 并行预热热点数据
  2. Redis连接池配置
  3. 本地缓存大小控制

http://www.ppmy.cn/embedded/177808.html

相关文章

MySQL 基础查询语句参考手册

一、基本查询操作 从表中选取特定列 sql -- 从 employees 表中选取 last_name 列 SELECT last_name FROM employees;-- 从 employees 表中选取 last_name、salary、email 列 SELECT last_name, salary, email FROM employees;获取表的全部列信息 sql -- 从 jobs 表中获取所有列…

OpenBMC:BmcWeb 生效路由2 Trie字典树

OpenBMC:BmcWeb 生效路由1 基于method分类路由_openbmc web-CSDN博客 可以看到,在internalAdd中: std::vector<BaseRule*> rules; rules.emplace_back(ruleObject); trie.add(rule, static_cast<unsigned>(rules.size() - 1U)); ruleObject首先被放入了每个meth…

人工智能之数学基础:矩阵的相似变换

本文重点 矩阵的相似变换是线性代数中一个至关重要的概念,它揭示了矩阵之间的一种特殊关系,并通过可逆矩阵将一个矩阵转化为另一个相似矩阵,同时保持矩阵的某些本质特征不变。在机器学习领域,矩阵的相似变换发挥着不可或缺的作用,广泛应用于数据降维、聚类分析、分类推荐…

算法基础——模拟

目录 1 多项式输出 2.蛇形方阵 3.字符串的展开 模拟&#xff0c;顾名思义&#xff0c;就是题⽬让你做什么你就做什么&#xff0c;考察的是将思路转化成代码的代码能⼒。这类题⼀般较为简单&#xff0c;属于竞赛⾥⾯的签到题&#xff08;但是&#xff0c;万事⽆绝对&#xff…

ai-api-union项目,适配各AI厂商api

项目地址&#xff1a;alpbeta/ai-api-union 需求&#xff1a;实现兼容各大模型厂商api的流式对话和同步对话接口&#xff0c;本项目现兼容智谱、豆包、通义、通义版deepseek 设计 一个ChatController类对外暴露这两个接口&#xff0c;入参都为ChatRequest请求类&#xff0c;…

HarmonyOS-ArkUI Grip组件

我们在学习List的时候&#xff0c;已经捎带引入了Grid。讲解如下图所示&#xff1a; 也就是&#xff0c;如果一个表&#xff0c;长宽基本都是一致的&#xff0c;那么此时可以完全不用Grid也可以实现&#xff0c;并且&#xff0c;优先考虑的就是List。 如果List实现不了的情况下…

Spring Boot添加全局异常处理器捕捉异常 跳转登录页面

Spring Boot添加全局异常处理器捕捉异常 跳转登录页面 二、后端异常处理 添加全局异常处理器 在 Spring Boot 中创建 GlobalExceptionHandler&#xff0c;捕获所有异常并返回统一 JSON 格式&#xff1a; 1. 这里和下面的2 选一个就可以 这里可以改成跳转登录 RestController…

修改git在提交代码时的名称

在git中&#xff0c;如果想修改提交代码作者的名字&#xff0c;可以进行以下操作&#xff1a; 1.在桌面或者文件夹内右击鼠标&#xff0c;点开Git Bash here。 2.进入后&#xff0c;通过git config user.name 回车查看当前名称。 3.通过git config --global user.name "…