如何在Tomcat内存缓存MongoDB FindIterable?缓存未生效问题咨询
问题分析与解决方案
你的情况不正常,核心问题出在你缓存的FindIterable<Document>对象本身——它不是查询结果的快照,而是MongoDB的惰性查询迭代器。
当你把FindIterable存入HashMap后,每次从缓存取出并使用它时,它才会真正向MongoDB发起查询请求,所以你每次拿到的都是数据库的最新数据,完全没起到缓存的作用。
修复方案
缓存实际查询结果而非迭代器
把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;解决线程安全问题
原代码使用的HashMap在Tomcat多线程环境下会存在数据不一致甚至死循环的风险,必须换成线程安全的ConcurrentHashMap。添加缓存过期/刷新机制
即使是不常变更的数据,也需要应对更新场景:- 手动刷新:当学生数据更新时,删除对应key的缓存,下次查询会自动拉取最新数据
- 自动过期:给缓存条目添加时间戳,每次取缓存时判断是否超过有效期(比如1小时),过期则重新查询并更新缓存
内容的提问来源于stack exchange,提问作者Cliff Lin
相关产品推荐
相关产品推荐

