Cassandra Leveled Compaction源码阅读

笔记都是写给未来的自己看的。

Cassandra为什么要有Compaction的机制Cassandra是BigTable的列族(Column Family)存储方式,这是一种非常灵活的存储模型,即使在同一个表中,不同的key也可以有不同的列,而且列不是对齐存储的,节省了空间。在Cassandra中,insert和update在底层都是追加的方式实现的,例如,数据key1对应column1,column2两列,要更新key1数据,更新内容为column2,c0lumn3。column1不变,column2更新,column是新加的。并且由于追加的方式,原数据和更新数据分别在两个sstable文件中,cassandra的追加的写方式,保证了写性能,但是因为同一个key的数据,会出现在多个sstable中,会严重影响读的性能,就必须进行compaction操作。进行compaction操作的另一个原因是,从memtable flush到磁盘的sstable比较小,个数很多,要均衡文件的个数,也要进行compaction。这样,compaction主要有两个目的:

  1. 合并更新的数据,尽量保证数据只在一个sstable中出现,减少read时候seek磁盘的次数,提升读性能
  2. 合并小文件
Cassandra的Compaction机制
Cassandra1.0以后,主要有两种compaction机制:1)SizeTieredCompactionStrategy,2)LeveledCompactionStrategy。第一个是Cassandra开始自带的compaction机制,唯一的优点,就是适合insert操作比较多的场景,或者说绝大多数是insert操作,极少量更新操作的场景。主要的缺点有:
  1. 同一个key的数据,会出现在多个sstable中,情况比LeveledCompactionStrategy严重,不仅层和层之间有,层之内也会重复出现
  2. compaction操作比较浪费空间,需要预留出数据一倍的空间,用来做compaction操作。
LeveledCompactionStrategy是1.0之后引入的,LevelDB的compaciton机制。主要的特点是:
  1. 占用空间比较少,只需要全部数据10%的额外空间;
  2. 每一层内,是没有重复key的,能够保证90%的读只需要读一个sstable文件
  3. 10T数据,只需要7层,也就是单机存储10T数据,最多只需要读7个sstable文件
LeveledCompactionStrategy机制主要应对的是update操作相对较多的场景,对于,insert较多操作场景,并不适合,主要原因如下是,当写操作很多的时候,会生成太多的L0的文件(L0层是会有重复key数据的)来不及compaction,导致读性能下降。解决这个问题一些常用的方法:
  1. 加大memtable的大小;
  2. 采用多线程的compaction机制
这些方案,都有自己的缺点,在实际引用中并不理想。
Leveled Compaction源码阅读
Leveled Compaction机制最核心的代码在LeveledManifest中,如下:
public synchronized Collection getCompactionCandidates()
    {
        // LevelDB gives each level a score of how much data it contains vs its ideal amount, and
        // compacts the level with the highest score. But this falls apart spectacularly once you
        // get behind.  Consider this set of levels:
        // L0: 988 [ideal: 4]
        // L1: 117 [ideal: 10]
        // L2: 12  [ideal: 100]
        //
        // The problem is that L0 has a much higher score (almost 250) than L1 (11), so what we'll
        // do is compact a batch of MAX_COMPACTING_L0 sstables with all 117 L1 sstables, and put the
        // result (say, 120 sstables) in L1. Then we'll compact the next batch of MAX_COMPACTING_L0,
        // and so forth.  So we spend most of our i/o rewriting the L1 data with each batch.
        //
        // If we could just do *all* L0 a single time with L1, that would be ideal.  But we can't
        // -- see the javadoc for MAX_COMPACTING_L0.
        //
        // LevelDB's way around this is to simply block writes if L0 compaction falls behind.
        // We don't have that luxury.
        //
        // So instead, we force compacting higher levels first.  This may not minimize the number
        // of reads done as quickly in the short term, but it minimizes the i/o needed to compact
        // optimially which gives us a long term win.
        for (int i = generations.length - 1; i >= 0; i--)
        {
            List sstables = generations[i];
            if (sstables.isEmpty())
                continue; // mostly this just avoids polluting the debug log with zero scores
            double score = SSTableReader.getTotalBytes(sstables) / maxBytesForLevel(i);
            logger.debug("Compaction score for level {} is {}", i, score);

            // L0 gets a special case that if we don't have anything more important to do,
            // we'll go ahead and compact even just one sstable
            if (score > 1.001 || i == 0)
            {
                Collection candidates = getCandidatesFor(i);
                if (logger.isDebugEnabled())
                    logger.debug("Compaction candidates for L{} are {}", i, toString(candidates));
                return candidates;
            }
        }

        return Collections.emptyList();
    }
代码比较好懂,只说几点:
  1. 每一层score计算为所有sstable的大小除以理想的大小
  2. L0层最多有MAX_COMPACTION_L0个文件参与compaction,这主要是为了避免OOM异常
  3. 每次只选择分数最高的level进行compaction
  4. 最终参与compaction的操作只有level层一些时间比较久的文件,和level+1层与之有重叠的sstable文件

转载于:https://www.cnblogs.com/sing1ee/archive/2012/02/20/2765018.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值