Files
hzdyjs/docs/开发文档/文件下载缓存机制说明.md
T
2025-08-03 15:50:45 +08:00

7.1 KiB
Raw Blame History

🚀 文件下载缓存机制说明

📋 功能概述

为了提高文件下载性能,减少对MinIO存储的重复请求,系统实现了基于内存的文件缓存机制。该机制具有以下特性:

✨ 核心特性

  • LRU淘汰策略: 当缓存空间不足时,自动淘汰最久未访问的文件
  • 智能大小控制: 只缓存小于50MB的文件,避免内存溢出
  • 过期时间管理: 缓存条目具有30分钟的有效期
  • 并发安全: 使用读写锁保证多线程环境下的数据一致性
  • 统计监控: 提供缓存命中率、大小等统计信息
  • 配置化管理: 所有缓存参数可通过配置文件调整

🔧 配置参数

基础配置

在 application.yml 或 application-dev.yml 中添加以下配置:

system:
  file-cache:
    # 是否启用文件缓存
    enabled: true
    
    # 最大缓存文件数量
    max-cache-size: 100
    
    # 最大缓存大小(字节)- 500MB
    max-cache-size-bytes: 524288000
    
    # 缓存过期时间(毫秒)- 30分钟
    expire-time-ms: 1800000
    
    # 最大缓存单个文件大小(字节)- 50MB
    max-single-file-size: 52428800
    
    # LRU淘汰比例(百分比)
    evict-ratio: 20
    
    # 是否启用缓存统计
    enable-stats: true
    
    # 缓存清理间隔(毫秒)- 5分钟
    cleanup-interval-ms: 300000

参数说明

参数名 默认值 说明
enabled true 是否启用文件缓存功能
max-cache-size 100 缓存的最大文件数量
max-cache-size-bytes 524288000 缓存的最大总大小(500MB)
expire-time-ms 1800000 缓存条目的过期时间(30分钟)
max-single-file-size 52428800 单个文件的最大缓存大小(50MB)
evict-ratio 20 LRU淘汰时移除的条目比例(20%)
enable-stats true 是否启用缓存统计功能
cleanup-interval-ms 300000 自动清理过期条目的间隔(5分钟)

🚀 使用方法

1. 文件下载

缓存机制对用户透明,正常使用文件下载接口即可:

GET /resource/oss/download/{ossId}

系统会自动:

  1. 检查缓存中是否存在该文件
  2. 如果存在且未过期,直接从缓存返回
  3. 如果不存在或已过期,从MinIO下载并缓存

2. 缓存管理API

获取缓存统计信息

GET /resource/oss/cache/stats

返回示例:

{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "cacheSize": 25,
    "currentCacheSizeBytes": 104857600,
    "maxCacheSizeBytes": 524288000,
    "cacheHits": 150,
    "cacheMisses": 50,
    "hitRate": "75.00%"
  }
}

清空缓存

DELETE /resource/oss/cache/clear

移除指定文件缓存

DELETE /resource/oss/cache/{ossId}

📊 性能优化

缓存命中率优化

  • 增加缓存大小: 对于内存充足的环境,适当增加 max-cache-size-bytes
  • 调整文件数量: 对于小文件较多的场景,增加 max-cache-size
  • 优化过期时间: 根据文件访问频率调整 expire-time-ms

内存使用优化

  • 控制单个文件大小: 根据实际情况调整 max-single-file-size
  • 调整淘汰策略: 通过 evict-ratio 控制淘汰比例
  • 定期清理: 设置合适的 cleanup-interval-ms

监控指标

  • 缓存命中率: 目标 > 70%
  • 内存使用率: 监控缓存占用的内存大小
  • 响应时间: 缓存命中时的下载速度应显著提升

🔍 技术实现

核心组件

1. 缓存条目类 (CacheEntry)

private class CacheEntry {
    private final byte[] data;           // 文件数据
    private final long size;             // 文件大小
    private final long createTime;       // 创建时间
    private final long lastAccessTime;   // 最后访问时间
    private final String contentType;    // 内容类型
}

2. LRU淘汰策略

private void evictLRUEntries() {
    // 按最后访问时间排序
    List<Map.Entry<Long, CacheEntry>> entries = new ArrayList<>(fileCache.entrySet());
    entries.sort((e1, e2) -> Long.compare(e1.getValue().getLastAccessTime(), e2.getValue().getLastAccessTime()));
    
    // 淘汰最旧的20%条目
    int evictCount = Math.max(1, entries.size() / 5);
    for (int i = 0; i < evictCount && i < entries.size(); i++) {
        Map.Entry<Long, CacheEntry> entry = entries.get(i);
        fileCache.remove(entry.getKey());
        currentCacheSize.addAndGet(-entry.getValue().getSize());
    }
}

3. 并发安全

  • 使用 ConcurrentHashMap 存储缓存数据
  • 使用 ReentrantReadWriteLock 保证读写安全
  • 使用 AtomicLong 统计缓存大小和命中率

工作流程

  1. 文件下载请求

    用户请求 → 权限验证 → 检查缓存 → 返回文件
    
  2. 缓存命中流程

    检查缓存 → 验证过期 → 直接返回 → 更新统计
    
  3. 缓存未命中流程

    检查缓存 → 从MinIO下载 → 添加到缓存 → 返回文件
    
  4. 缓存管理流程

    检查大小限制 → LRU淘汰 → 清理过期 → 添加新条目
    

⚠️ 注意事项

1. 内存管理

  • 缓存会占用JVM堆内存,需要合理配置缓存大小
  • 建议监控应用的内存使用情况
  • 大文件不会被缓存,避免内存溢出

2. 数据一致性

  • 缓存的文件数据可能与MinIO中的文件不同步
  • 如果需要最新数据,可以手动清除缓存
  • 建议在文件更新后清除相关缓存

3. 性能考虑

  • 缓存命中时响应速度显著提升
  • 缓存未命中时会有轻微的性能开销(用于缓存数据)
  • 建议根据实际访问模式优化缓存参数

4. 安全考虑

  • 缓存数据存储在内存中,应用重启后会丢失
  • 敏感文件建议设置较短的过期时间
  • 可以通过API手动管理缓存

🔧 故障排查

常见问题

  1. 缓存命中率低

    • 检查缓存大小配置是否合理
    • 分析文件访问模式
    • 调整过期时间
  2. 内存使用过高

    • 减少缓存大小限制
    • 降低单个文件大小限制
    • 增加淘汰比例
  3. 缓存不生效

    • 检查 enabled 配置是否为 true
    • 确认文件大小是否超过限制
    • 查看日志中的缓存相关信息

监控建议

  1. 定期检查缓存统计

    curl -X GET "http://localhost:8080/resource/oss/cache/stats"
    
  2. 监控应用内存使用

    jstat -gc <pid> 1000
    
  3. 查看缓存相关日志

    tail -f logs/application.log | grep "cache"
    

📈 性能测试

测试场景

  1. 首次下载: 从MinIO下载并缓存
  2. 缓存命中: 从内存直接返回
  3. 并发下载: 多用户同时下载同一文件
  4. 大文件下载: 超过缓存大小限制的文件

预期性能提升

  • 缓存命中时: 响应时间减少 80-90%
  • 并发访问: 显著减少MinIO压力
  • 整体性能: 平均下载速度提升 60-80%

📝 维护说明: 本文档基于文件缓存机制的实现,如需修改缓存策略或参数,请同步更新相关代码和配置。