由HBase的数据删除方式联想到JVM垃圾回收机制及磁盘碎片整理机制

    这几天重读《HBase权威指南》,看到HBase的数据模型及数据操作机制中的数据删除。当接收到数据删除指令后,系统并没有立即删除HFile中存储的数据,而是设置一个标志位标志其被删除(在HDFS中数据删除时被移到/trash文件夹缓冲区),此时系统会根据标志位响应客户端的访问请求,待系统的下一次大合并(major campaction)将被标志的数据块删除,这才算彻底的完成数据的删除。
   
     由标志删除到大合并彻底删除这个过程我联想到了JVM中垃圾回收过程二者有相似之处。在《深入理解JVM》中有介绍:
         对象死亡的标记过程:

        在可达性分析算法中不可达的对象,并非是“非死不可”的,这时候它们暂时处于“缓刑”阶段,要真            正宣告一个对象死亡,至少要经历两次标记过程:                                                                                                 

        1)如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将这两种情况都视为“没有必要执行”。

    

        2)如果这个对象被判定为有必要执行finalize()方法,那么这个对象将会放置在一个叫做F-Queue的队列之中,并在稍后由一个由虚拟机自动建立的、低优先级的Finalizer线程去执行它。这里所谓的“执行”是指虚拟机会触发这个方法,但并不承诺会等待它运行结束,这样做的原因是,如果一个对象在finalize()方法中执行缓慢,或者发生了死循环(更极端的情况),将很可能会导致F-Queue队列中其他对象永久处于等待,甚至导致整个内存回收系统崩溃。

      

        3)finalize()方法是对象逃脱死亡命运的最后一次机会,稍后GC将对F-Queue中的对象进行第二次小规模的标记,如果对象要在 finalize()中成功拯救自己——只要重新与引用链上的任何一个对象建立关联即可,譬如把自己(this关键字)赋值给某个类变量或者对象的成员变量,那在第二次标记时它将被移除出“即将回收”的集合;如果对象这时候还没有逃脱,那基本上它就真的被回收了。

【引用自 http://www.jianshu.com/p/424e12b3a08f
        
         综上可见HBase数据删除和JVM垃圾回收一样并非一次彻底删除,都是先标记在删除。但二者采取这种机制的目的似乎不同:1)HBase这样做是为了避免频繁的数据块移动影响系统的正常IO带宽和效率。2)至于JVM为什么要标记两次(在finalize()中会有所作为?),这个暂时还没查到...有待考证。
    
        还有,HBase的大合并(major compaction)机制也让我联想到了操作系统中的磁盘碎片整理。我们在访问磁盘数据时经历:寻址->磁头寻道->定位数据扇区->传读数据过程。我们日常也会对计算机中存储的文件进行增删操作,期间必然会使数据不连续地分布在磁盘中的各个磁道和扇区。在访问数据的过程中相对来说几乎所有时间都花费在了寻道定位数据上。所以如果数据存储不连续,将会降低磁盘读写效率,同时磁头频繁的移动也会对硬盘性能和寿命造成一定的影响。由此可见,磁盘碎片整理非常有必要,将不连续分布的数据移动到连续的存储空间,从而提高磁盘的访问效率。这个工作由操作系统完成,同时这也是一个很耗时的操作。磁盘碎片整理过程和大合并过程类似,都是将有用数据移动到连续的存储区域形成大的占用分区同时也由零碎的空闲分区形成一个大的空闲分区【有机会再把操作系统空间分配策略看一遍】...。
        
        以上是个人粗见,若有不到之处,还望指正,谢谢!

你可能感兴趣的:(Java编程,操作系统,HBase)