ソースを参照

update
1、抽卷模板 优先从本地缓存中获取
2、组卷结构 优先从本地缓存中获取

deason 1 年間 前
コミット
62d56042bf

+ 27 - 8
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/PaperStructService.java

@@ -18,6 +18,8 @@ import cn.com.qmth.examcloud.core.questions.dao.entity.dto.PaperDetailUnitStruct
 import cn.com.qmth.examcloud.core.questions.service.bean.dto.QuesNameDto;
 import cn.com.qmth.examcloud.support.CacheConstants;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
@@ -34,6 +36,7 @@ import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 /**
@@ -44,6 +47,8 @@ public class PaperStructService {
 
     private static final Logger log = LoggerFactory.getLogger(PaperStructService.class);
 
+    private Cache<String, PaperStruct> localPaperStructCache = CacheBuilder.newBuilder().expireAfterWrite(3, TimeUnit.MINUTES).build();
+
     private static int cacheTimeOut = 2 * 60 * 60;
 
     @Autowired
@@ -490,16 +495,30 @@ public class PaperStructService {
         return new QuesNameDto(name, name);
     }
 
-    public PaperStruct getByCache(String id) {
-        String key = CacheConstants.CACHE_Q_PAPER_STRUCT + id;
-        PaperStruct ps = redisClient.get(key, PaperStruct.class, cacheTimeOut);
+    public PaperStruct getPaperStructCacheById(String paperStructId) {
+        // 组卷结构 优先从本地缓存中获取
+        String key = CacheConstants.CACHE_Q_PAPER_STRUCT + paperStructId;
+        PaperStruct ps = localPaperStructCache.getIfPresent(key);
+        if (ps != null) {
+            log.warn("从【本地缓存】中获取组卷结构! key:{}", key);
+            return ps;
+        }
+
+        // 从redis缓存中获取
+        ps = redisClient.get(key, PaperStruct.class, cacheTimeOut);
+        if (ps != null) {
+            log.warn("从【Redis缓存】中获取抽卷模板! key:{}", key);
+            return ps;
+        }
+
+        // 从数据库中获取
+        ps = Model.of(paperStructRepo.findById(paperStructId));
         if (ps == null) {
-            ps = Model.of(paperStructRepo.findById(id));
-            if (ps == null) {
-                throw new StatusException("未找到试卷结构:" + id);
-            }
-            redisClient.set(key, ps, cacheTimeOut);
+            throw new StatusException("未找到试卷结构:" + paperStructId);
         }
+
+        log.warn("从【数据库】中获取抽卷模板! key:{}", key);
+        redisClient.set(key, ps, cacheTimeOut);
         return ps;
     }
 

+ 51 - 29
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/impl/RandomPaperServiceImpl.java

@@ -36,6 +36,8 @@ import cn.com.qmth.examcloud.support.CacheConstants;
 import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.support.cache.bean.CourseCacheBean;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.bson.types.ObjectId;
@@ -55,6 +57,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 @Service
@@ -62,6 +65,8 @@ public class RandomPaperServiceImpl implements RandomPaperService {
 
     private static final Logger log = LoggerFactory.getLogger(RandomPaperServiceImpl.class);
 
+    private Cache<String, RandomPaperCache> localRandomPaperCache = CacheBuilder.newBuilder().expireAfterWrite(3, TimeUnit.MINUTES).build();
+
     private static int cacheTimeOut = 2 * 60 * 60;
 
     @Autowired
@@ -898,10 +903,10 @@ public class RandomPaperServiceImpl implements RandomPaperService {
         long start = System.currentTimeMillis();
         RandomPaperCache rp = this.getRandomPaperTemplateCacheById(randomPaperId);
         long start2 = System.currentTimeMillis();
-        log.warn("获取抽卷模板耗时:{}ms ID:{} 题数量:{}", start2 - start, randomPaperId, rp.getQuestionMap().size());
+        log.warn("获取抽卷模板耗时:{}ms ID:{} 题数量:{}", start2 - start, randomPaperId, rp.getQuestionMap().size());
 
-        PaperStruct ps = paperStructService.getByCache(rp.getPaperStructId());
-        log.warn("获取组卷结构耗时:{}ms 结构类型:{} ID:{}", System.currentTimeMillis() - start2, ps.getPaperStrucType(), rp.getPaperStructId());
+        PaperStruct ps = paperStructService.getPaperStructCacheById(rp.getPaperStructId());
+        log.warn("获取组卷结构耗时:{}ms 结构类型:{} ID:{}", System.currentTimeMillis() - start2, ps.getPaperStrucType(), rp.getPaperStructId());
 
         CreateDefaultPaperParam param = new CreateDefaultPaperParam();
         param.setFullyObjective(true);
@@ -958,7 +963,7 @@ public class RandomPaperServiceImpl implements RandomPaperService {
         }
         paper.setFullyObjective(param.getFullyObjective());
 
-        log.warn("抽卷完成总耗时:{}ms ID:{}", System.currentTimeMillis() - start, randomPaperId);
+        log.warn("抽卷完成总耗时:{}ms ID:{}", System.currentTimeMillis() - start, randomPaperId);
         return paper;
     }
 
@@ -1125,33 +1130,50 @@ public class RandomPaperServiceImpl implements RandomPaperService {
         return ret;
     }
 
-    private RandomPaperCache getRandomPaperTemplateCacheById(String id) {
-        String key = CacheConstants.CACHE_Q_RANDOM_PAPER + id;
-        RandomPaperCache rp = redisClient.get(key, RandomPaperCache.class, cacheTimeOut);
-        if (rp == null) {
-            rp = new RandomPaperCache();
-            RandomPaper e = Model.of(randomPaperRepo.findById(id));
-            if (e == null) {
-                throw new StatusException("未找到随机模板:" + id);
-            }
-            rp.setName(e.getName());
-            rp.setPaperStructId(e.getPaperStructId());
-            List<RandomPaperQuestion> rpqs = randomPaperQuestionRepo.findByRandomPaperId(id);
-            if (CollectionUtils.isEmpty(rpqs)) {
-                throw new StatusException("随机模板试题库为空:" + id);
-            }
-            Map<String, List<RandomPaperQuestion>> map = new HashMap<>();
-            for (RandomPaperQuestion rpq : rpqs) {
-                List<RandomPaperQuestion> list = map.get(rpq.getKey());
-                if (list == null) {
-                    list = new ArrayList<>();
-                    map.put(rpq.getKey(), list);
-                }
-                list.add(rpq);
+    private RandomPaperCache getRandomPaperTemplateCacheById(String randomPaperId) {
+        // 抽卷模板 优先从本地缓存中获取
+        String key = CacheConstants.CACHE_Q_RANDOM_PAPER + randomPaperId;
+        RandomPaperCache rp = localRandomPaperCache.getIfPresent(key);
+        if (rp != null) {
+            log.warn("从【本地缓存】中获取抽卷模板! key:{}", key);
+            return rp;
+        }
+
+        // 从redis缓存中获取
+        rp = redisClient.get(key, RandomPaperCache.class, cacheTimeOut);
+        if (rp != null) {
+            log.warn("从【Redis缓存】中获取抽卷模板! key:{}", key);
+            return rp;
+        }
+
+        // 从数据库中获取
+        RandomPaper entity = Model.of(randomPaperRepo.findById(randomPaperId));
+        if (entity == null) {
+            throw new StatusException("未找到随机模板:" + randomPaperId);
+        }
+
+        List<RandomPaperQuestion> rpQuestions = randomPaperQuestionRepo.findByRandomPaperId(randomPaperId);
+        if (CollectionUtils.isEmpty(rpQuestions)) {
+            throw new StatusException("随机模板试题库为空:" + randomPaperId);
+        }
+
+        log.warn("从【数据库】中获取抽卷模板! key:{}", key);
+        rp = new RandomPaperCache();
+        rp.setName(entity.getName());
+        rp.setPaperStructId(entity.getPaperStructId());
+
+        Map<String, List<RandomPaperQuestion>> map = new HashMap<>();
+        for (RandomPaperQuestion rpq : rpQuestions) {
+            List<RandomPaperQuestion> list = map.get(rpq.getKey());
+            if (list == null) {
+                list = new ArrayList<>();
+                map.put(rpq.getKey(), list);
             }
-            rp.setQuestionMap(map);
-            redisClient.set(key, rp, cacheTimeOut);
+            list.add(rpq);
         }
+        rp.setQuestionMap(map);
+
+        redisClient.set(key, rp, cacheTimeOut);
         return rp;
     }