緩存設計方案
- java緩存的通用實作方案
-
- 設計思路
- 定義annotation
- 通過切面掃描标注了@Redis的方法自動實作緩存管理
java緩存的通用實作方案
redis提供的緩存的API,但是在開發階段,如果每個人都自己調用原生API實作緩存時,由于每個人的水準問題,會導緻實作方案千差萬别,同僚又很難統一管理維護
設計思路
通過提供spring的annotation,實作緩存方案的統一
定義annotation
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Redis {
int expireSeconds() default 0;
boolean isNeedLocalCatch() default false;
}
通過切面掃描标注了@Redis的方法自動實作緩存管理
@Around(“execution(* com.lufax.ztcs….(…)) && @annotation(redis)”)
public Object redis(ProceedingJoinPoint pjp, Redis redis){
Object object = null;
String catchKey = getCatchKey(pjp);
object = getCatchObject(pjp, redis, catchKey);
// "null"為空資料的緩存,防止緩存穿透
if (object != null && “null”.equals(object)) {
return null;
} else if (object != null) {
return object;
}
// 雙重檢查鎖,防止緩存擊穿情況的發送
synchronized(catchKey) {
object = getCatchObject(pjp, redis, catchKey);
if (object != null && “null”.equals(object)) {
return null;
} else if (object != null) {
return object;
}
try {
object = pjp.proceed();
} catch (Throwable throwable) {
Logger.error(this, “方法調用失敗”, throwable);
}
}
int expireSeconds = redis.expireSeconds();
if (expireSeconds == 0) {
// 預設緩存時間是15到20分鐘之間,防止緩存雪崩
expireSeconds = (int)(15+Math.random()(20-15+1));
expireSeconds = expireSeconds 60;
}
putCatchObject(catchKey, redis.expireSeconds(), object, redis.isNeedLocalCatch());
return object;
}