• 结合 ConcurrentHashMap.putIfAbsent 与 Futrue 实现本地缓存防击穿


    http://blog.csdn.net/michaelwubo/article/details/50865185

    Java 高并发缓存与Guava Cache


    这篇文章名字叫《Java 高并发缓存与Guava Cache》,但最核心的是如何高效的防止本地缓存击穿

    业务模型:

    res = cache.get(key);
    if(res == null) {
       value = sql;
       cach.put(key, value);
       return value;
    } 
    return res;
    

    这个代码多线程里不行:

    在多线程时,出现了在缓存里没有缓存时,会执行一样执行多次的业务数据并返回处理的数据,我们分析一下出现这种情况的:

    (1)当线程T1访问cacheMap里面有没有,这时根据业务到后台处理业务数据并返回处理数据,并放入缓存

    (2)当线程T2访问cacheMap里面同样也没有,也把根据业务到后台处理业务数据并返回处理数据,并放入缓存


    首先想到的是同步Synchronized
    res = cache.get(key);
    if(res == null) {
       synchronized(this) {
          oldValue = cache.get(key);
          if(oldValue == null) {
             value = sql;
             cach.put(key, value);
             return value;
          } else 
              return oldValue;
       }
    
    } 
    return res;
    然后就会想到这个代码对性能损伤较大,而且不适用于集群环境。
    缓存失效的瞬间,并发线程全部阻塞


    然后重点来了:使用Future和ConcurrentMap异步更新缓存



    res = cache.get(key);
    if(res == null) {
       FutureTask<V> futureTask=new FutureTask<V>(callable); 
       futureValue=cacheMap.putIfAbsent(keyValue, futureTask);  
       if(futureValue==null){  
          futureValue=futureTask;  
          futureTask.run();  
       }  
       return futureValue.get();
    }
    return res;
    假设现在缓存失效,并发线程5个,都创建了FutureTask,
    putIfAbsent:如果(调用该方法时)key-value 已经存在,则返回那个 value 值。如果调用时 map 里没有找到 key 的 mapping,返回一个 null 值


    故最终5个中只有一个线程能够得到真正的 执行-阻塞-返回 过程,其它4个线程可能有两种情况:

    (1)阻塞-返回

    (2)直接返回

    比用syn同步块清一色阻塞要好得多了



  • 相关阅读:
    突出展示案例
    下拉菜单案例
    推送人群的选择【技术篇】
    Couchbase 中的分布式储存
    开始了大概三四天的Rails学习之路
    分层架构与公司组织
    极光推送助推视频App,打造最活跃手机新媒体平台
    极光推送CTO黄鑫:技术人员要建立自己的知识图谱
    Android SDK教程
    Android消息推送 SDK 集成指南
  • 原文地址:https://www.cnblogs.com/silyvin/p/9106699.html
Copyright © 2020-2023  润新知