技术开发 频道

剖析Jive的缓存机制


IT168技术文档】 
    lastAccessedListNode记录着一个缓存节点的Key值,是构成lastAccessedList链表的基本元素,在lastAccessedList链表中,经常被访问到的节点总是在最前面。ageListNode记录着缓存节点的加入时间,是构成ageList链表的基本元素。而ageList链表是按时间先后排序,先加入的节点总是在最后面。lastAccessedListNode和ageListNode本来可以分写成两个类,毕竟lastAccessedListNode并不需要ageListNode的成员变量timestamp,但是为了简化程序,Jive把它们写成了一个类。这也是值得注意的一个地方。

 现在来看缓存机制中最关键的一个类Cache的部分代码,其中主要是add()和get()方法。有关这两个方法的介绍请参考代码中的注释。
public class Cache implements Cacheable { protected static long currentTime = CacheTimer. currentTime; protected HashMap cachedObjectsHash; protected LinkedList lastAccessedList; protected LinkedList ageList; //缓存元素的最大尺寸128KB,可修改 protected int maxSize = 128 * 1024; //整个缓存的大小 protected int size = 0; //缓存元素的最大保存时间,用Cache(long maxLifetime)初始化 protected long maxLifetime = -1; //记录cache的命中次数和未命中次数 protected long cacheHits, cacheMisses = 0L; ...... //向哈希表中添加一个关键字为Key的缓存对象object public synchronized void add(Object key, Cacheable object) { //先把原来的对象remove掉 remove(key); int objectSize = object.getSize(); //如果对象太大,则不加入缓存 if (objectSize > maxSize * .90) { return; } size += objectSize; //新建一个缓存对象,并放入哈希表中 CacheObject cacheObject = new CacheObject(object, objectSize); cachedObjectsHash.put(key, cacheObject); // 把缓存元素的Key放到lastAccessed List链表的最前面 LinkedListNode lastAccessedNode = lastAccessedList.addFirst(key); cacheObject.lastAccessedListNode = lastAccessedNode; //把缓存元素的Key放到ageList链表的最前面,并记下当前时间 LinkedListNode ageNode = ageList.addFirst(key); ageNode.timestamp = System.currentTimeMillis(); cacheObject.ageListNode = ageNode; // 在cullCache()中,先调用deleteExpiredEntries()把过期对象删掉, 如果缓存还是太满,则调用 remove(lastAccessedList.getLast().object)把 lastAccessedList中不常访问的对象删掉 cullCache(); } //在哈希表中得到一个关键字为Key的缓存对象object public synchronized Cacheable get(Object key) { // 清理过期对象 deleteExpiredEntries(); CacheObject cacheObject = (CacheObject)cachedObjectsHash.get(key); if (cacheObject == null) { //没找到则未命中次数加一 cacheMisses++; return null; } //找到则命中次数加一 cacheHits++; //将该缓存对象从lastAccessedList链表中取下并插入到链表头部 cacheObject.lastAccessedListNode.remove(); lastAccessedList.addFirst(cacheObject.lastAccessedListNode); return cacheObject.object; } }
 到这里,第一部分的Java类实现就介绍完了。正如上文提到的那样,第二部分的Java类实现与第一部分基本上没有什么差别,因此就不再赘述。下面给出第二部分的类图(见图1),以供读者参考。


 中间层

 中间层是联系上层访问接口和低层数据结构的纽带。它的主要功能就是根据ID(对应于数据库中的编号)到缓存中找相应的对象。如果缓存中有该对象就直接得到,没有则去读数据库生成一个新的对象,再把该对象放入缓存中,以便下次访问时能直接得到。图2是相关类的类图。



0
相关文章