You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Tomcat内存缓存MongoDB FindIterable?缓存未生效问题咨询

问题分析与解决方案

你的情况不正常,核心问题出在你缓存的FindIterable<Document>对象本身——它不是查询结果的快照,而是MongoDB的惰性查询迭代器。

当你把FindIterable存入HashMap后,每次从缓存取出并使用它时,它才会真正向MongoDB发起查询请求,所以你每次拿到的都是数据库的最新数据,完全没起到缓存的作用。

修复方案

  1. 缓存实际查询结果而非迭代器
    把FindIterable转换成内存中的集合(比如List<Document>),这样存入缓存的是真实的数据快照,不会再触发新的数据库查询:

    // 替换HashMap为线程安全的ConcurrentHashMap,适配Tomcat多线程环境
    ConcurrentHashMap<String, List<Document>> cache = new ConcurrentHashMap<>(); 
    List<Document> docList = null;
            
    if(cache.containsKey(key)) { 
      docList = cache.get(key);
    }
    else {
      mongo.setColl(com.gds.SysConfig._DB, "student_info");
      FindIterable<Document> docs = mongo.select({"stu_id": key});
      if(docs != null) {
        // 把迭代器转换成内存集合,固化查询结果
        docList = new ArrayList<>();
        docs.forEach(docList::add);
        cache.put(key, docList);
      }
    }           
            
    return docList;
    
  2. 解决线程安全问题
    原代码使用的HashMap在Tomcat多线程环境下会存在数据不一致甚至死循环的风险,必须换成线程安全的ConcurrentHashMap。

  3. 添加缓存过期/刷新机制
    即使是不常变更的数据,也需要应对更新场景:

    • 手动刷新:当学生数据更新时,删除对应key的缓存,下次查询会自动拉取最新数据
    • 自动过期:给缓存条目添加时间戳,每次取缓存时判断是否超过有效期(比如1小时),过期则重新查询并更新缓存

内容的提问来源于stack exchange,提问作者Cliff Lin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 13:43:09