适用于高并发的本地缓存方案
使用本地缓存需要注意两个问题:
1 内存管理,及时解除无用对象的引用。防止大量无用对象进入old区,引发full gc。
2 数据同步,如果应用是一个集群,需要保持各台机器的数据一致性。
问题1的解决可以采用LRU算法,预先定好缓存大小。达到最大值后,清除最近最少使用的对象。
问题2比较复杂,需要有一个集中的地方控制缓存一致,比如可以采用消息中间件,写时进行异步复制。这种方式成本较大。
其实对于业务系统,用户通过浏览器访问的数据,不需要很强的一致性。只要在3秒内,各台机器能够保持最终一致,用户是感觉不大不同机器数据的不同步。
因此通过控制缓存时间为3秒或其它很短的时间,就可以保证一定程度的数据一致,避免数据同步的开销和复杂度。
缓存时间短又会引发另外一个问题,就是缓存的命中率。在高并发访问下,缓存时间短可能会导致,大量的访问刚好都没有命中,缓存穿透给系统带来瞬间的高峰压力。
综合考虑以上几个矛盾点,可以对缓存数据进行封装,使用有效失效次数的缓存对象,保证在高并发情况下,大量的访问都能命中缓存,同时又能保证缓存及时失效和更新。代码如下
class LRUHashMap extends LinkedHashMap<String, Object> { private int MAX_ENTRIES; public LRUHashMap(int size) { MAX_ENTRIES = size; } protected boolean removeEldestEntry(Map.Entry<String, Object> eldest) { return size() > MAX_ENTRIES; } }
缓存对象
public class CacheObject implements Serializable { long createTime; long lifeTime; Object value; AtomicInteger invalidTimes; public CacheObject(long lifeTime, Object value) { this.lifeTime = lifeTime; this.value = value; invalidTimes = new AtomicInteger(0); this.createTime = System.currentTimeMillis(); } public long getCreateTime() { return createTime; } public void setCreateTime(long createTime) { this.createTime = createTime; } public long getLifeTime() { return lifeTime; } public void setLifeTime(long lifeTime) { this.lifeTime = lifeTime; } public Object getValue() { // 如果已经失效很久,说明很久没有被访问,那么直接返回null,不对失效次数进行判断。 if ((System.currentTimeMillis() - createTime) > 10 * lifeTime) { return null; } // 保证在高并发下,缓存失效也可以保证较高的命中率 if (System.currentTimeMillis() - createTime > lifeTime) { if (invalidTimes.incrementAndGet() > 3) { return value; } else { return null; } } return value; } public void setValue(Object value) { this.value = value; } public AtomicInteger getInvalidTimes() { return invalidTimes; } public void setInvalidTimes(AtomicInteger invalidTimes) { this.invalidTimes = invalidTimes; } }
本地缓存
public class LocalCache { LRUHashMap cacheArea = new LRUHashMap(20); public Object get(String key) { CacheObject cacheObject = (CacheObject) cacheArea.get(key); return cacheObject == null ? null : cacheObject.getValue(); } public void put(String key, Object value, long lifeTime) { CacheObject cacheObject = new CacheObject(lifeTime, value); cacheArea.put(key, cacheObject); } }
参考http://www.cnblogs.com/redcreen/archive/2011/02/15/1955248.html
相关推荐
ThinkMake 2020-11-13
学习web前端 2020-11-09
天空一样的蔚蓝 2020-10-23
curiousL 2020-08-03
sochrome 2020-07-29
SoarFly00 2020-06-28
LeoHan 2020-06-02
拭血 2020-06-02
lengyu0 2020-05-20
GimmeS 2020-05-15
逸璞丷昊 2020-03-08
lengyu0 2020-05-10
viewerlin 2020-05-10
DAV数据库 2020-05-07
程序员俱乐部 2020-05-06
Vampor 2020-05-01
ROES 2020-04-22
lcyangcss 2020-04-21