结构包:
使用案例:
实现效果:
1、基本并发的本地缓存,基于分布式轻量级锁的redis缓存
2、热缓存(高频访问持续缓存)+快速过期(本地缓存2秒,redis缓存10秒)
3、方法级别缓存清理 (@HybridCache 与@HybridChange 绑定管理缓存 )
4、基于HybridType接口的可扩展式作用域,目前已实现:全局、token
5、基于HybridLevel接口的可扩展式缓存处理,目前已实现:本地缓存、redis缓存
核心代码包:
package com.*.server.live.core.hybridCache; import com.*.server.live.core.hybridCache.impl.DepthLocal; import com.*.server.live.core.hybridCache.impl.DepthRedis; import java.lang.annotation.*; /** * 功能描述:多重缓存 * 作者:唐泽齐 * @case @HybridCache(scope = ScopeGlobal.class) */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface HybridCache { /*缓存深度*/ Class<? extends HybridLevel> depth() default DepthRedis.class; /*缓存广度*/ Class<? extends HybridType> scope(); }
@HybridCache
package com.*.server.live.core.hybridCache; import com.*.server.live.core.hybridCache.impl.DepthRedis; import java.lang.annotation.*; /** * 功能描述:多重缓存更新 * 作者:唐泽齐 * @case @HybridChange(clazz = LiveStudioController.class,method = \"getStudio\",args = {Long.class}) * @case @HybridChange(clazz = LiveStudioController.class,method = \"getStudio\",args = {}) */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface HybridChange { /*关联类*/ Class<? extends Object> clazz(); /*关联方法*/ String method(); /*关联方法入参类型*/ Class<?>[] args(); }
@HybridChange
package com.*.server.live.core.hybridCache; import org.aspectj.lang.ProceedingJoinPoint; import javax.validation.constraints.NotNull; /** * 功能描述:多重缓存级别 * 作者:唐泽齐 */ public interface HybridLevel { /** * 缓存 * @param key 缓存key * @param id 混村ID * @param o 缓存值 * @param self 是否执行节点 * @param joinPoint 节点 * @return * @throws Throwable */ Object cache(@NotNull String key,@NotNull String id, Object o,@NotNull boolean self,@NotNull ProceedingJoinPoint joinPoint) throws Throwable; /** * 清缓存 * @param key 缓存key * @param self 是否执行节点 * @param joinPoint 节点 * @return * @throws Throwable */ Object del(@NotNull String key,@NotNull boolean self,@NotNull ProceedingJoinPoint joinPoint) throws Throwable; }
HybridLevel
package com.*.server.live.core.hybridCache; /** * 功能描述:多重缓存级别 * 作者:唐泽齐 */ public interface HybridType { String token(); }
HybridType
package com.*.server.live.core.hybridCache; import com.alibaba.fastjson.JSON; import com.alibaba.nacos.common.util.Md5Utils; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; import javax.annotation.Resource; import java.lang.reflect.Method; /** * 功能描述:多重缓存接口 * 作者:唐泽齐 */ @Aspect @Configuration public class HybridCacheInterceptor { @Resource ApplicationContext applicationContext; final static String cache = \"hybridCache:\"; @Around(value = \"@annotation(com.*.server.live.core.hybridCache.HybridCache)\") public Object cache(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature ms = (MethodSignature) joinPoint.getSignature(); Method method = ms.getMethod(); HybridCache cacheAnnotation = method.getAnnotation(HybridCache.class); String key = getCacheKey(method); String id = getCacheId(method,joinPoint.getArgs()); HybridLevel hybridLevel = applicationContext.getBean(cacheAnnotation.depth()); return hybridLevel.cache(key, id, null, true, joinPoint); } @Around(value = \"@annotation(com.*.server.live.core.hybridCache.HybridChange)\") public Object del(ProceedingJoinPoint joinPoint) throws Throwable { MethodSignature ms = (MethodSignature) joinPoint.getSignature(); Method method = ms.getMethod(); HybridChange cacheAnnotation = method.getAnnotation(HybridChange.class); try { Method method1 = cacheAnnotation.clazz().getMethod(cacheAnnotation.method(),cacheAnnotation.args()); HybridCache cache = method1.getAnnotation(HybridCache.class); String key = getCacheKey(method1); HybridLevel hybridLevel = applicationContext.getBean(cache.depth()); return hybridLevel.del(key,true, joinPoint); } catch (Exception e) { return joinPoint.proceed(); } } /*获取缓存key*/ private String getCacheKey(Method method) { return cache + method.getDeclaringClass().getSimpleName() + \":\" + method.getName(); } ; /*获取缓存id*/ private String getCacheId(Method method,Object[] args) { HybridCache cacheAnnotation = method.getAnnotation(HybridCache.class); HybridType hybridType = applicationContext.getBean(cacheAnnotation.scope()); return Md5Utils.getMD5((hybridType.token() + JSON.toJSONString(args)).getBytes()); } ; }
HybridCacheInterceptor
扩展代码包:
package com.*.server.live.core.hybridCache.impl; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.*.server.live.core.hybridCache.HybridLevel; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import java.util.concurrent.TimeUnit; /** * 功能描述:本地缓存 * 作者:唐泽齐 */ @Component public class DepthLocal implements HybridLevel { /*自带读写锁*/ public volatile static Cache<String, Object> localCache = CacheBuilder.newBuilder().initialCapacity(144).expireAfterAccess(2, TimeUnit.SECONDS).build(); @Override public Object cache(String key, String id, Object o, boolean search, ProceedingJoinPoint joinPoint) throws Throwable { String keyId = key + \":\" + id; MethodSignature ms = (MethodSignature) joinPoint.getSignature(); if (search && o == null && (o = localCache.getIfPresent(keyId)) == null) { synchronized (ms.getMethod()) { if ((o = localCache.getIfPresent(keyId)) == null) { o = joinPoint.proceed(); localCache.put(keyId, o); } } } if (o == null) { o = localCache.getIfPresent(keyId); } else { localCache.put(keyId, o); } return o; } @Override public Object del(String key, boolean self, ProceedingJoinPoint joinPoint) throws Throwable { Object o = null; if (self) { o = joinPoint.proceed(); } localCache.cleanUp(); return o; } }
DepthLocal
package com.*.server.live.core.hybridCache.impl; import cn.hutool.core.util.RandomUtil; import com.*.common.redis.service.RedisService; import com.*.server.live.core.hybridCache.HybridLevel; import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.stereotype.Component; import javax.annotation.Resource; /** * 功能描述:redis缓存 * 作者:唐泽齐 */ @Component public class DepthRedis implements HybridLevel { @Resource private RedisService redisService; @Resource private HybridLevel depthLocal; @Override public synchronized Object cache(String key, String id, Object o,boolean search, ProceedingJoinPoint joinPoint) throws Throwable { o = depthLocal.cache(key, id, o,false,joinPoint); String lock = getLock(key, id); if(search && o== null && (o=redisService.hget(key , id)) == null ) { for (;;) { if(redisService.incr(lock,1l) <= 1l && (o=redisService.hget(key , id)) == null ) { try { o = joinPoint.proceed(); redisService.hset(key , id, o, 10l); } catch (Throwable e) { throw e; }finally { redisService.del(lock); } } else { o = redisService.hget(key , id); } if(o == null) { Thread.sleep(1); } else { break; } } } if (o == null) { o = redisService.hget(key , id); } else { depthLocal.cache(key, id, o,false,joinPoint); redisService.hset(key , id, o, 10l); } return o; } @Override public Object del(String key,boolean self, ProceedingJoinPoint joinPoint) throws Throwable { Object o = null; if (self) { o = joinPoint.proceed(); } redisService.del(key); depthLocal.del(key,false,joinPoint); return o; } private String getLock(String key, String id) { return this.getClass().getSimpleName()+\":\"+key+\":\"+id; } }
DepthRedis
package com.*.server.live.core.hybridCache.impl; import com.*.server.live.core.hybridCache.HybridType; import org.springframework.stereotype.Component; /** * 功能描述:全局级别 * 作者:唐泽齐 */ @Component public class ScopeGlobal implements HybridType { @Override public String token() { return \"\"; } }
ScopeGlobal
package com.*.server.live.core.hybridCache.impl; import com.*.common.core.utils.*Util; import com.*.server.live.core.hybridCache.HybridType; import org.springframework.stereotype.Component; /** * 功能描述:token级别 * 作者:唐泽齐 */ @Component public class ScopeToken implements HybridType { @Override public String token() { return *Util.getCurrentTokenValue(); } }
ScopeToken
来源:https://www.cnblogs.com/tangzeqi/p/16466919.html
本站部分图文来源于网络,如有侵权请联系删除。