本地缓存

1.单机本地缓存

本地缓存的一种简单实现

           首先定义一个缓存实体,包含三个属性 放入缓存的时间戳,值以及过期时间;其次需要个线程去监控缓存实体是否过期。

/** 
* 
*本地缓存保存的实体 
*/  
public class CacheEntity implements Serializable {  
  
  /** */  
  private static final long serialVersionUID = 7172649826282703560L;  
  
  /** 
  * 值 
  */  
  private Object value;  
  
  /** 
  * 保存的时间戳 
  */  
  private long gmtModify;  
  
  /** 
  * 过期时间 
  */  
  private int expire;  
  
  public Object getValue() {  
    return value;  
  }  
  
  public void setValue(Object value) {  
    this.value = value;  
  }  
  
  public long getGmtModify() {  
    return gmtModify;  
  }  
  
  public void setGmtModify(long gmtModify) {  
    this.gmtModify = gmtModify;  
  }  
  
  public int getExpire() {  
    return expire;  
  }  
  
  public void setExpire(int expire) {  
    this.expire = expire;  
  }  
  
  public CacheEntity(Object value, long gmtModify, int expire) {  
    super();  
    this.value = value;  
    this.gmtModify = gmtModify;  
    this.expire = expire;  
  }  
  
}  
/**
* 简易本地缓存的实现类
*/
public class LocalCache {
    //默认的缓存容量
    private static int DEFAULT_CAPACITY = 512;
    //最大容量
    private static int MAX_CAPACITY = 100000;
    //刷新缓存的频率
    private static int MONITOR_DURATION = 2;
    // 启动监控线程
    static {
        new Thread(new TimeoutTimerThread()).start();
    }
    //使用默认容量创建一个Map
    private static ConcurrentHashMap<String, CacheEntity> cache = new ConcurrentHashMap<String, CacheEntity>(DEFAULT_CAPACITY);

    /**
    * 将key-value 保存到本地缓存并制定该缓存的过期时间
    * @param key
    * @param value
    * @param expireTime 过期时间,如果是-1 则表示永不过期
    * @return
    */
    public boolean putValue(String key, Object value, int expireTime) {
        return putCloneValue(key, value, expireTime);
    }

    /**
    * 将值通过序列化clone 处理后保存到缓存中,可以解决值引用的问题
    * @param key
    * @param value
    * @param expireTime
    * @return
    */
    private boolean putCloneValue(String key, Object value, int expireTime) {
        try {
            if (cache.size() >= MAX_CAPACITY) {
                return false;
            }
            // 序列化赋值
            CacheEntity entityClone = clone(new CacheEntity(value, System.nanoTime(), expireTime));
            cache.put(key, entityClone);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
    *
    * 序列化 克隆处理
    * @param object
    * @return
    */
    private <T extends Serializable> T clone(T object) {
        T cloneObject = null;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            oos.close();
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            cloneObject = (T) ois.readObject();
            ois.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cloneObject;
    }

    /**
    *从本地缓存中获取key对应的值,如果该值不存则则返回null
    * @param key
    * @return
    */
    public Object getValue(String key) {
        return cache.get(key).getValue();
    }

    /**
    * 清空所有
    */
    public void clear() {
        cache.clear();
    }

    /**
    * 过期处理线程
    *
    */
    static class TimeoutTimerThread implements Runnable {
        public void run() {
            while (true) {
                try {
                    System.out.println("Cache monitor");
                    TimeUnit.SECONDS.sleep(MONITOR_DURATION);
                    checkTime();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        /**
        * 过期缓存的具体处理方法
        * @throws Exception
        */
        private void checkTime() throws Exception {
            //"开始处理过期 ";

            for (String key : cache.keySet()) {
                CacheEntity tce = cache.get(key);
                long timoutTime = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime()- tce.getGmtModify());
                //" 过期时间 : "+timoutTime);
                if (tce.getExpire() > timoutTime) {
                    continue;
                }
                System.out.println(" 清除过期缓存 : " + key);
                //清除过期缓存和删除对应的缓存队列
                cache.remove(key);
            }
        }
    }

}

转载:https://www.iteye.com/blog/wujiu-2179087

本地缓存的思想

本地缓存会把数据放在内存中。所以不宜太大,否则容易造成内存不足

因为是放在内存中,所以对于分布式部署,需要考虑到缓存数据的同步。

1.可以建个缓存应用用来单独存放缓存。其他应用先访问缓存应用,没有得到缓存再访问数据库

2.不进行缓存同步。这台机器没有缓存,就重新去获取。有的话直接使用本机缓存

3.如果缓存同步要求型比较高,建议直接使用redis

原文地址:https://www.cnblogs.com/linhongwenBlog/p/13356707.html