|
@@ -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;
|