WANG 5 سال پیش
والد
کامیت
da5e10f138
1فایلهای تغییر یافته به همراه50 افزوده شده و 2 حذف شده
  1. 50 2
      src/main/java/cn/com/qmth/examcloud/web/cache/ObjectRedisCacheProcessor.java

+ 50 - 2
src/main/java/cn/com/qmth/examcloud/web/cache/ObjectRedisCacheProcessor.java

@@ -1,8 +1,13 @@
 package cn.com.qmth.examcloud.web.cache;
 
+import java.util.concurrent.TimeUnit;
+
 import org.apache.commons.lang3.StringUtils;
 import org.assertj.core.util.Arrays;
 
+import cn.com.qmth.examcloud.commons.exception.ExamCloudRuntimeException;
+import cn.com.qmth.examcloud.commons.util.ThreadLocalUtil;
+import cn.com.qmth.examcloud.commons.util.Util;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
 import cn.com.qmth.examcloud.web.support.SpringContextHolder;
 
@@ -65,10 +70,53 @@ public class ObjectRedisCacheProcessor {
 		String key = keyPrefix + StringUtils.join(Arrays.asList(propKeys), '_');
 
 		RandomCacheBean t = getRedisClient().get(key, c);
+
 		if (null == t) {
-			getObjectRedisCacheTrigger().fire(appName, className, propKeys);
-			t = getRedisClient().get(key, c);
+
+			int count = 0;
+
+			String cacheLock = "CACHE_LOCK:" + key;
+			String cacheException = "CACHE_EXCEPTION:" + key;
+
+			while (true) {
+				count++;
+				Boolean locked = getRedisClient().setIfAbsent(cacheLock,
+						ThreadLocalUtil.getTraceId(), 30);
+
+				if (locked) {
+					try {
+						getObjectRedisCacheTrigger().fire(appName, className, propKeys);
+						getRedisClient().delete(cacheException);
+						break;
+					} catch (Exception e) {
+						getRedisClient().set(cacheException, true, 10);
+						throw e;
+					} finally {
+						getRedisClient().delete(cacheLock);
+					}
+				}
+
+				t = getRedisClient().get(key, c);
+
+				if (null != t) {
+					break;
+				}
+
+				if (null != getRedisClient().get(cacheException, Boolean.class)) {
+					throw new ExamCloudRuntimeException(
+							"exception happened when loading cache. key=" + key);
+				}
+
+				// 10秒内未加载完缓存,抛出异常
+				if (200 < count) {
+					throw new ExamCloudRuntimeException(
+							"fail to load cache in 10 seconds. key=" + key);
+				}
+				Util.sleep(TimeUnit.MILLISECONDS, 50);
+			}
+
 		}
+
 		@SuppressWarnings("unchecked")
 		T ret = (T) t;
 		return ret;