当前位置: 首页 > ds >正文

聊聊JetCache的CachePenetrationProtect

本文主要研究一下JetCache的CachePenetrationProtect

CachePenetrationProtect

com/alicp/jetcache/anno/CachePenetrationProtect.java

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface CachePenetrationProtect {boolean value() default true;int timeout() default CacheConsts.UNDEFINED_INT;TimeUnit timeUnit() default TimeUnit.SECONDS;
}

它定义value、timeout、timeUnit属性

computeIfAbsentImpl

com/alicp/jetcache/AbstractCache.java

    static <K, V> V computeIfAbsentImpl(K key, Function<K, V> loader, boolean cacheNullWhenLoaderReturnNull,long expireAfterWrite, TimeUnit timeUnit, Cache<K, V> cache) {AbstractCache<K, V> abstractCache = CacheUtil.getAbstractCache(cache);CacheLoader<K, V> newLoader = CacheUtil.createProxyLoader(cache, loader, abstractCache::notify);CacheGetResult<V> r;if (cache instanceof RefreshCache) {RefreshCache<K, V> refreshCache = ((RefreshCache<K, V>) cache);r = refreshCache.GET(key);refreshCache.addOrUpdateRefreshTask(key, newLoader);} else {r = cache.GET(key);}if (r.isSuccess()) {return r.getValue();} else {Consumer<V> cacheUpdater = (loadedValue) -> {if(needUpdate(loadedValue, cacheNullWhenLoaderReturnNull, newLoader)) {if (timeUnit != null) {cache.PUT(key, loadedValue, expireAfterWrite, timeUnit).waitForResult();} else {cache.PUT(key, loadedValue).waitForResult();}}};V loadedValue;if (cache.config().isCachePenetrationProtect()) {loadedValue = synchronizedLoad(cache.config(), abstractCache, key, newLoader, cacheUpdater);} else {loadedValue = newLoader.apply(key);cacheUpdater.accept(loadedValue);}return loadedValue;}}

AbstractCache的computeIfAbsentImpl方法,在cache.config().isCachePenetrationProtect()执行的是synchronizedLoad

synchronizedLoad

    static <K, V> V synchronizedLoad(CacheConfig config, AbstractCache<K,V> abstractCache,K key, Function<K, V> newLoader, Consumer<V> cacheUpdater) {ConcurrentHashMap<Object, LoaderLock> loaderMap = abstractCache.initOrGetLoaderMap();Object lockKey = buildLoaderLockKey(abstractCache, key);while (true) {boolean create[] = new boolean[1];LoaderLock ll = loaderMap.computeIfAbsent(lockKey, (unusedKey) -> {create[0] = true;LoaderLock loaderLock = new LoaderLock();loaderLock.signal = new CountDownLatch(1);loaderLock.loaderThread = Thread.currentThread();return loaderLock;});if (create[0] || ll.loaderThread == Thread.currentThread()) {try {V loadedValue = newLoader.apply(key);ll.success = true;ll.value = loadedValue;cacheUpdater.accept(loadedValue);return loadedValue;} finally {if (create[0]) {ll.signal.countDown();loaderMap.remove(lockKey);}}} else {try {Duration timeout = config.getPenetrationProtectTimeout();if (timeout == null) {ll.signal.await();} else {boolean ok = ll.signal.await(timeout.toMillis(), TimeUnit.MILLISECONDS);if(!ok) {logger.info("loader wait timeout:" + timeout);return newLoader.apply(key);}}} catch (InterruptedException e) {logger.warn("loader wait interrupted");return newLoader.apply(key);}if (ll.success) {return (V) ll.value;} else {continue;}}}}

synchronizedLoad会判断如果loaderThread不是当前线程,则通过ll.signal.await进行等待,等待timeout或者InterruptedException时则执行加载newLoader.apply(key)

小结

JetCache提供了@CachePenetrationProtect注解,支持多线程并发去回源的时候,控制在指定超时时间内整个JVM中只有1个去回源,过了超时时间若未有结果则自行加载,若已有结果则返回loader线程加载的结果。

doc

  • MethodCache
http://www.xdnf.cn/news/6108.html

相关文章:

  • Baklib知识中台驱动企业智慧服务升级
  • WebGIS 开发中的数据安全与隐私保护:急需掌握的要点
  • MongoDB 的主要优势和劣势是什么?适用于哪些场景?
  • 安卓刷机模式详解:Fastboot、Fastbootd、9008与MTK深刷
  • 19.three官方示例+编辑器+AI快速学习webgl_buffergeometry_points
  • 缺乏需求变更的影响评估,如何降低项目风险
  • AI 赋能数智孪生:更快、更智能、更易用
  • OCCT知识笔记之BRepBuilderAPI_NurbsConvert详解
  • 后531时代:光伏产业市场化转型实战策略
  • 使用Spring和Springboot遇到的问题及解决办法
  • 什么叫裸机开发
  • 差分探头量程选择的六大认知误区与应对方案
  • 模板的使用
  • ASP.NET Core Identity 框架中实现密码重置
  • 【Qt】之音视频编程2:QtAV的使用篇
  • MapReduce打包运行
  • 在Window上面添加交叉编译链 MinGW+NDK
  • blazor与硬件通信实现案例
  • PyTorch 分布式训练
  • AI时代,如何实现人机共舞?
  • 新建一个reactnative 0.72.0的项目
  • VLA 论文精读(二十二)Multi-agent Embodied AI: Advances and Future Directions
  • 【架构】RUP统一软件过程:企业级软件开发的全面指南
  • 在scala中sparkSQL连接masql并添加新数据
  • python使用OpenCV 库将视频拆解为帧并保存为图片
  • 【Mac 从 0 到 1 保姆级配置教程 15】- Python 环境一键安装与配置,就是这么的丝滑
  • 虚拟机Ubuntu系统怎么扩展容量,扩展容量后进不去系统怎么办?
  • python共享内存实际案例,传输opencv frame
  • Python面向对象编程(OOP)深度解析:从封装到继承的多维度实践
  • 【论信息系统项目的资源管理】