`
javaG
  • 浏览: 554574 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

关于大量缓存对象回收的思考

    博客分类:
  • java
阅读更多

前几天面试,被问到了一个问题,如果当前有数亿条记录,但是缓存最多放100万条记录,怎么保证缓存很好的被利用(大概是个这个意思,具体的问题记得不太清楚了).当时一下没回答出来,就随便说了一下,利用类似java虚拟机的垃圾回收算法来实现缓存的回收.
回来后苦思冥想,相出一个简单的方案.
首先,利用HaspMap(考虑用ConcurrentHashMap,并发下这个map效率高)来存放缓存对象,每次被缓存的对象用一个CacheObject封装.封装的目的主要是给这个个缓存对象添加一些属性信息,如果被命中的次数,过期的之间之类的.

public class CacheObject {
    private Object cache;//被cache的对象
    private int hit;//命中次数
    private long expire;//过期时间
  
    public CacheObject(Object object){
        this.cache = object;
    }
            
    public Object getCache() {
        return cache;
    }
    
    public void setCache(Object cache) {
        this.cache = cache;
    }
    //这里我就不实现如何生成hashCode的策略了
    public Integer getHashCode(){
        return null;
    }

    public int getHit() {
        return hit;
    }
    
    public void setHit(int hit) {
        this.hit = hit;
    }

    public long getExpire() {
        return expire;
    }

    public void setExpire(long expire) {
        this.expire = expire;
    }


然后在建立几个LinkedList对象,来模拟jvm回收中的分代机制.下面是jvm分代示意图:

Heap = {Old + NEW = { Eden , from, to } }

 

JVM 内存模型中分两大块,一块是 NEW Generation, 另一块是 Old Generation. New Generation 中,有一个叫 Eden 的空间,主要是用来存放新生的对象,还有两个 Survivor Spaces(from,to), 它们用来存放每次垃圾回收后存活下来的对象。在 Old Generation 中,主要存放应用程序中生命周期长的内存对象,还有个 Permanent Generation ,主要用来放 JVM 自己的反射对象,比如类对象和方法对象等。

垃圾回收描述:
现在我们用LinkedList对象来模拟JVM中的Old,Eden , from, to对象,来实现我们的缓存垃圾回收.新被添加进缓存的对象(CacheObject)的引用都被存放在Eden对象的队列的头部里,如果要回收缓存对象时,从Eden队列的尾部开始扫描.如果扫描时发现这个CacheObject没有被命中,就把这个CacheObject对应在缓存中的数据删掉,并把这个CacheObject从Eden中删掉;如果发现这个CacheObject被命中了,就把它挪到from的队列的首部.最后命中次数多的CacheObject会被移动到Old队列里面.
回收的时候我们可以模拟JVM里面的回收分级,例如:0级为全部(Full)的垃圾回收,会回收OLD段中的垃圾;1级或以上为部分垃圾回收,只会回收NEW中的垃圾.
这里的Old,Eden , from, to在垃圾回收的时候都是FIFO模式,新的对象放队首,回收的时候从队尾开始回收.

我这里就给个简单的思路,希望大侠们指正.

===========
原来的写文章时候对缓存的写法理解不够深刻,其实没必要把算法搞的如此复杂,只需要用一个链表实现就好.然后再用以下清理策略来清理.
1.设置一个自动清理的线程,定时启动检查.
2.设置一个缓存数目最大值,超过这个最大值就启动清理(优先清理命中率低的).
3.设置一个最大超时时间,超过这个时间,必须回收此缓存.
4.设置一个清理比率a,每次清理到缓存数目  最大值*(1-a) 就停止清理.
5.命中一次就把此缓存丢到链表的尾部,每次新的元素都丢到链表的尾部.
6.清理时,先遍历整个缓存,把超时的全部清理掉.如果清理完超时的还不够,就从头部开始往后删除元素超过范围的元素.(因为是链表,直接算出要删除多少条数据,然后把头部直接指向那条记录就完成了删除,效率很高)
分享到:
评论
1 楼 ll648322446 2012-04-26  
楼主对java的Garbage理解很深哈,只是这种关于缓存的利用率要结合具体的访问模式和对象属性吧

相关推荐

    .NET 性能优化方法总结

    - **1.1.1.3 使用常量避免创建对象**:例如,`new Decimal(0)`这样的代码会导致小对象频繁创建及回收。正确的做法是使用`Decimal.Zero`这样的常量,这可以避免不必要的对象创建和销毁开销。 - **1.1.1.4 使用...

    .net性能优化宝典

    在C#中,不必要的对象创建会增加垃圾回收的压力,从而影响应用程序的整体性能。以下是一些避免对象创建的建议: - **减少临时对象的创建**:例如,在循环中避免重复创建相同类型的临时对象。 - **复用对象**:当...

    java工程师面试题大全及答案

    Java工程师面试题大全及答案,这是一份专为准备Java面试者精心整理的资源,涵盖了大量知名企业的面试问题。这份资料对于那些希望在Java开发领域深入发展或正在寻找新工作机会的程序员来说,无疑是一份宝贵的复习材料...

    字节跳动大数据面试题汇总(精华版).pdf

    - 如何在实际工作中利用Kafka处理大量实时数据流。 3. **字符串处理算法题** - 一般考察字符串操作的基本能力和算法优化技巧。 综上所述,字节跳动的大数据面试题覆盖了从Hadoop生态系统的基础知识到高级应用的...

    JSP企业电子投票系统(源代码+论文+开题报告+文献综述).rar

    12. **性能优化**:对于高并发的投票场景,系统需要进行性能优化,如缓存策略、负载均衡、数据库查询优化等,以确保在大量用户访问时仍能保持高效运行。 这个JSP企业电子投票系统不仅涵盖了多种IT技术的应用,还...

    内存管理内存管理内存管理

    不过,您可能没有用一些时间去思考它们在您的操作系统中是如何实现的。本节将向您展示 malloc 和 free 的一个最简化实现的代码,来帮助说明管理内存时都涉及到了哪些事情。 要试着运行这些示例,需要先复制本...

    操作系统(内存管理)

    不过,您可能没有用一些时间去思考它们在您的操作系统中是如何实现的。本节将向您展示 malloc 和 free 的一个最简化实现的代码,来帮助说明管理内存时都涉及到了哪些事情。 要试着运行这些示例,需要先 复制本代码...

    阿里巴巴校园招聘历年经典面试题汇总:C++研发 1

    23. **对象复用**:如对象池技术,通过预先创建和缓存对象,避免频繁创建和销毁带来的性能损失。 24. **零拷贝**:在数据传输中,通过避免不必要的数据复制,提高I/O操作的效率,常见于网络传输和文件操作。 25. *...

    .net网站开发面试题必备

    - **自动垃圾回收机制**:自动管理内存,减少内存泄漏的风险。 #### 17. WebService的创建方法 - **使用WSDL.exe工具**:生成Web服务描述文件。 - **使用Visual Studio的Add Web Reference功能**:添加对现有...

Global site tag (gtag.js) - Google Analytics