cassandra row的快速检索3—keycache

cassandra的应用中最主要的查询一般是带着rowkey所进行的查询,所以这个查询最主要的就是通过rowkey找到对应数据的位置。而cassandra是流动型的nosql DB,这样数据只有在一个sstable中才会将每个rowkey对应的row进行合并处理,那么查询的时候,即使带着rowkey,也需要查询出每个sstable中对应的rowkey的位置。

cassandra的一组sstable中虽然index.db已经记录了rowkey所在data.db文件中的位置,但是index.db是磁盘文件,如果每次查询都要通过该文件查询得到,那么查询就必然增加一次IO,所以就有了keycache,这个记录了sstable中rowkey对应的data.db文件中的位置,并且存储在内存中,减少一次IO来加快通过rowkey的检索速度。

在cassandra运行中,cache的总体管理和控制主要由CacheService管理

public final AutoSavingCache<KeyCacheKey, RowIndexEntry> keyCache;

而一组sstable就会对应在内存中映射出一个SSTableReader对象进行对应SSTable的控制。

所以在SSTableReader中就会有相应的指针指向keycache

private InstrumentingCache<KeyCacheKey, RowIndexEntry> keyCache;

1、keycache的初始化,是在CF创建生成内存对象ColumnFamilyStore的时候,根据cache的配置参数而进行开启的。

keycache的相关属性介绍如下:

keycache的内存容量:cassandra.yaml文件中的配置项key_cache_size_in_mb:如果不为空,则keycache在内存中的容量即使这个配置值,否则如果总量内存的5%如果大于100MB,则取100MB,否则取总量内存的5%。

keycache的内存结构:public final AutoSavingCache<KeyCacheKey, RowIndexEntry> keyCache;为一个AutoSavingCache对象。AutoSavingCache是继承父类InstrumentingCache<K, V>,

首先InstrumentingCache<K, V>中有四个属性分别是:

private volatile boolean capacitySetManually;判断是否进行过手动更改cache容量的

    private final ICache<K, V> map;主要是内存中存放cache数据的内存结构,keycache的主要实现类就是org.apache.cassandra.cache.ConcurrentLinkedHashCache<KeyCacheKey, RowIndexEntry>.主要是存放KeyCacheKey与 RowIndexEntry的对应关系,而KeyCacheKey主要是rowkey与SStable的信息,而RowIndexEntry则是rowkey对应sstable所在data.db文件中的偏移量。

    private final String type;cache的类型,现在cassandra中主要有两种一种是keycache,一种是rowcache。

  private CacheMetrics metrics;cache的度量器,主要是cache的命中几率等等记录

然后是AutoSavingCache中有四个属性:

    public static final Set<CacheService.CacheType> flushInProgress = new NonBlockingHashSet<CacheService.CacheType>();主要是记录的正在flush的cache的任务,在同一时刻只允许一个cache进行flush

    protected volatile ScheduledFuture<?> saveTask; 保存cache的任务,后面详细介绍

    protected final CacheService.CacheType cacheType; cache的类型

private CacheSerializer<K, V> cacheLoader; cache数据的序列化器,Keycache的实现主要是KeyCacheSerializer,在keycache进行持久化的时候,进行调用其序列化方法将keycache进行序列化。序列化格式主要是:

rowkey的长度 rowkey sstable的标示ssid 标示是否进行index升级的版本 如果升级过index则需要序列化RowIndexEntry,如果没有就返回

    RowIndexEntry的序列化已经在indexinfo中介绍过了。

其次KeyCacheKey的属性

 public final Descriptor desc;sstable的相关属性
   
public final byte[] key;rowkey信息

/**
     * We can use Weighers.singleton() because Long can't be leaking memory
     * @return auto saving cache object
     */
    private AutoSavingCache<KeyCacheKey, RowIndexEntry> initKeyCache()
    {
        logger.info("Initializing key cache with capacity of {} MBs.", DatabaseDescriptor.getKeyCacheSizeInMB());

        long keyCacheInMemoryCapacity = DatabaseDescriptor.getKeyCacheSizeInMB() * 1024 * 1024;

        // as values are constant size we can use singleton weigher
        // where 48 = 40 bytes (average size of the key) + 8 bytes (size of value)
        ICache<KeyCacheKey, RowIndexEntry> kc;
        if (MemoryMeter.isInitialized())
        {
            kc = ConcurrentLinkedHashCache.create(keyCacheInMemoryCapacity);
        }
        else
        {
            logger.warn("MemoryMeter uninitialized (jamm not specified as java agent); KeyCache size in JVM Heap will not be calculated accurately. " +
                        "Usually this means cassandra-env.sh disabled jamm because you are using a buggy JRE; upgrade to the Sun JRE instead");
            /* We don't know the overhead size because memory meter is not enabled. */
            EntryWeigher<KeyCacheKey, RowIndexEntry> weigher = new EntryWeigher<KeyCacheKey, RowIndexEntry>()
            {
                public int weightOf(KeyCacheKey key, RowIndexEntry entry)
                {
                    return key.key.length + entry.serializedSize();
                }
            };
            kc = ConcurrentLinkedHashCache.create(keyCacheInMemoryCapacity, weigher);
        }
        AutoSavingCache<KeyCacheKey, RowIndexEntry> keyCache = new AutoSavingCache<KeyCacheKey, RowIndexEntry>(kc, CacheType.KEY_CACHE, new KeyCacheSerializer());

        int keyCacheKeysToSave = DatabaseDescriptor.getKeyCacheKeysToSave();

        logger.info("Scheduling key cache save to each {} seconds (going to save {} keys).",
                DatabaseDescriptor.getKeyCacheSavePeriod(),
                    keyCacheKeysToSave == Integer.MAX_VALUE ? "all" : keyCacheKeysToSave);

        keyCache.scheduleSaving(DatabaseDescriptor.getKeyCacheSavePeriod(), keyCacheKeys
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值