deason 8 miesięcy temu
rodzic
commit
2dcbed94e5

+ 6 - 0
src/main/java/com/qmth/exam/reserve/cache/CacheConstants.java

@@ -84,6 +84,12 @@ public interface CacheConstants {
      */
     String LOCK_STUDENT_APPLY = "student_apply:%s";
 
+    /**
+     * 某考点相关的剩余可约数量缓存 操作锁
+     * $lock:exam_site_capacity:{examSiteId}
+     */
+    String LOCK_EXAM_SITE_CAPACITY = "exam_site_capacity:%s";
+
     /**
      * 系统自动为考生预约操作锁
      * $lock:auto_apply

+ 46 - 24
src/main/java/com/qmth/exam/reserve/cache/impl/ApplyTaskCacheService.java

@@ -1,6 +1,7 @@
 package com.qmth.exam.reserve.cache.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.qmth.boot.core.concurrent.service.ConcurrentService;
 import com.qmth.exam.reserve.bean.apply.ApplyRecordCacheBean;
 import com.qmth.exam.reserve.bean.applytask.CurrentApplyTaskVO;
 import com.qmth.exam.reserve.bean.examsite.ExamSiteCapacityInfo;
@@ -21,6 +22,7 @@ import org.springframework.stereotype.Component;
 
 import java.util.*;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
 
 @Component
 public class ApplyTaskCacheService implements CacheConstants {
@@ -45,6 +47,9 @@ public class ApplyTaskCacheService implements CacheConstants {
     @Autowired
     private StudentApplyService studentApplyService;
 
+    @Autowired
+    private ConcurrentService concurrentService;
+
     /**
      * 获取当前启用的预约任务缓存
      */
@@ -193,33 +198,50 @@ public class ApplyTaskCacheService implements CacheConstants {
      * 初始化 某考点某时段的“剩余可约数量”缓存
      */
     public void initApplyAvailableCountCache(Long examSiteId, int oldCapacity, int newCapacity) {
-        // 获取所有时段ID集合
-        List<TimePeriodEntity> timePeriods = timePeriodService.list(new LambdaQueryWrapper<TimePeriodEntity>().select(TimePeriodEntity::getId));
-        if (CollectionUtils.isEmpty(timePeriods)) {
-            return;
-        }
+        String examSiteCapacityLockKey = String.format(CacheConstants.LOCK_EXAM_SITE_CAPACITY, examSiteId);
+        Lock examSiteCapacityLock = concurrentService.getLock(examSiteCapacityLockKey);
 
-        // 新、旧考点容量差额
-        int diffCapacity = newCapacity - oldCapacity;
+        try {
+            if (!examSiteCapacityLock.tryLock()) {
+                log.warn("获取锁失败,不允许同时操作!lockKey:{}", examSiteCapacityLockKey);
+                return;
+            }
+            log.debug("获取锁成功!lockKey:{}", examSiteCapacityLockKey);
 
-        for (TimePeriodEntity timePeriod : timePeriods) {
-            String cacheKey = String.format(CACHE_APPLY_AVAILABLE_COUNT, examSiteId, timePeriod.getId());
-            if (redisClient.exist(cacheKey)) {
-                if (diffCapacity == 0) {
-                    // 考点总容量未变化,不用更新缓存
-                    continue;
-                }
+            // 获取所有时段ID集合
+            List<TimePeriodEntity> timePeriods = timePeriodService.list(new LambdaQueryWrapper<TimePeriodEntity>().select(TimePeriodEntity::getId));
+            if (CollectionUtils.isEmpty(timePeriods)) {
+                return;
+            }
 
-                // 总容量变化时,则更新考点剩余容量缓存
-                RAtomicLong atomic = redisClient.getRedissonClient().getAtomicLong(cacheKey);
-                long availableCount = Math.max(atomic.get() + diffCapacity, 0);
-                atomic.set(availableCount);
-                log.warn("SET cacheKey:{} value:{}", cacheKey, availableCount);
-            } else {
-                // 初始考点剩余容量缓存
-                RAtomicLong atomic = redisClient.getRedissonClient().getAtomicLong(cacheKey);
-                atomic.set(newCapacity);
-                log.debug("SET cacheKey:{} value:{}", cacheKey, newCapacity);
+            // 新、旧考点容量差额
+            int diffCapacity = newCapacity - oldCapacity;
+            for (TimePeriodEntity timePeriod : timePeriods) {
+                String cacheKey = String.format(CACHE_APPLY_AVAILABLE_COUNT, examSiteId, timePeriod.getId());
+                if (redisClient.exist(cacheKey)) {
+                    if (diffCapacity == 0) {
+                        // 考点总容量未变化,不用更新缓存
+                        continue;
+                    }
+
+                    // 总容量变化时,则更新考点剩余容量缓存
+                    RAtomicLong atomic = redisClient.getRedissonClient().getAtomicLong(cacheKey);
+                    long availableCount = Math.max(atomic.get() + diffCapacity, 0);
+                    atomic.set(availableCount);
+                    log.warn("SET cacheKey:{} value:{}", cacheKey, availableCount);
+                } else {
+                    // 初始考点剩余容量缓存
+                    RAtomicLong atomic = redisClient.getRedissonClient().getAtomicLong(cacheKey);
+                    atomic.set(newCapacity);
+                    log.debug("SET cacheKey:{} value:{}", cacheKey, newCapacity);
+                }
+            }
+        } finally {
+            try {
+                examSiteCapacityLock.unlock();
+                log.debug("解锁成功!lockKey:{}", examSiteCapacityLockKey);
+            } catch (Exception e) {
+                log.warn("解锁失败!lockKey:{} err:{}", examSiteCapacityLockKey, e.getMessage());
             }
         }
     }