1. Cache 读写 

调用逻辑: 

hmaster.handleCreateTable->HRegion.createHRegion-> HRegion. initialize->initializeRegionInternals->instantiateHStore 

->Store.Store->new CacheConfig(conf, family)-> CacheConfig.instantiateBlockCache->new LruBlockCache 

传入参数

  1. /**
  2. * Configurable constructor.  Use this constructor if not using defaults.
  3. * @param maxSize maximum size of this cache, in bytes
  4. * @param blockSize expected average size of blocks, in bytes
  5. * @param evictionThread whether to run evictions in a bg thread or not
  6. * @param mapInitialSize initial size of backing ConcurrentHashMap
  7. * @param mapLoadFactor initial load factor of backing ConcurrentHashMap
  8. * @param mapConcurrencyLevel initial concurrency factor for backing CHM
  9. * @param minFactor percentage of total size that eviction will evict until
  10. * @param acceptableFactor percentage of total size that triggers eviction
  11. * @param singleFactor percentage of total size for single-access blocks
  12. * @param multiFactor percentage of total size for multiple-access blocks
  13. * @param memoryFactor percentage of total size for in-memory blocks
  14. */
  15. public LruBlockCache(long maxSize, long blockSize, boolean evictionThread,
  16. int mapInitialSize, float mapLoadFactor, int mapConcurrencyLevel,
  17. float minFactor, float acceptableFactor,
  18. float singleFactor, float multiFactor, float memoryFactor)

new LruBlockCache时除了设置默认的参数外,还会创建evictionThread并wait和一个定时打印的线程StatisticsThread

当执行HFileReaderV2的readBlock时,会先看判断是否开户了Cache ,如果开启,则使用cache中block

  1. // Check cache for block. If found return.
  2. if (cacheConf.isBlockCacheEnabled()) {
  3. // Try and get the block from the block cache.  If the useLock variable is true then this
  4. // is the second time through the loop and it should not be counted as a block cache miss.
  5. HFileBlock cachedBlock = (HFileBlock)
  6. cacheConf.getBlockCache().getBlock(cacheKey, cacheBlock, useLock);
  7. if (cachedBlock != null) {
  8. BlockCategory blockCategory =
  9. cachedBlock.getBlockType().getCategory();
  10. getSchemaMetrics().updateOnCacheHit(blockCategory, isCompaction);
  11. if (cachedBlock.getBlockType() == BlockType.DATA) {
  12. HFile.dataBlockReadCnt.incrementAndGet();
  13. }
  14. validateBlockType(cachedBlock, expectedBlockType);
  15. // Validate encoding type for encoded blocks. We include encoding
  16. // type in the cache key, and we expect it to match on a cache hit.
  17. if (cachedBlock.getBlockType() == BlockType.ENCODED_DATA &&
  18. cachedBlock.getDataBlockEncoding() !=
  19. dataBlockEncoder.getEncodingInCache()) {
  20. throw new IOException(“Cached block under key ” + cacheKey + “ ” +
  21. “has wrong encoding: ” + cachedBlock.getDataBlockEncoding() +
  22. “ (expected: ” + dataBlockEncoder.getEncodingInCache() + “)”);
  23. }
  24. return cachedBlock;
  25. }
  26. // Carry on, please load.
  27. }

在getBlock方法中,会更新一些统计数据,重要的时更新

  1. BlockPriority.SINGLE为BlockPriority.MULTI
  2. public Cacheable getBlock(BlockCacheKey cacheKey, boolean caching, boolean repeat) {
  3. CachedBlock cb = map.get(cacheKey);
  4. if(cb == null) {
  5. if (!repeat) stats.miss(caching);
  6. return null;
  7. }
  8. stats.hit(caching);
  9. cb.access(count.incrementAndGet());
  10. return cb.getBuffer();
  11. }

——————— 

若是第一次读,则将block加入Cache.

  1. // Cache the block if necessary
  2. if (cacheBlock && cacheConf.shouldCacheBlockOnRead(
  3. hfileBlock.getBlockType().getCategory())) {
  4. cacheConf.getBlockCache().cacheBlock(cacheKey, hfileBlock,
  5. cacheConf.isInMemory());
  6. }

2. LRU evict

写入cache时就是将block加入到 一个 ConcurrentHashMap中,并更新Metrics,之后判断if(newSize > acceptableSize() && !evictionInProgress), acceptableSize是初始化时给的值(long)Math.floor(this.maxSize
* this.acceptableFactor),acceptableFactor是一个百分比,是可以配置的:”hbase.lru.blockcache.acceptable.factor”(0.85f), 这里的意思就是判断总Size是不是大于这个值,如果大于并且没有正在执行的eviction线程,
那么就执行evict。

  1. /**
  2. * Cache the block with the specified name and buffer.
  3. * <p>
  4. * It is assumed this will NEVER be called on an already cached block.  If
  5. * that is done, an exception will be thrown.
  6. * @param cacheKey block’s cache key
  7. * @param buf block buffer
  8. * @param inMemory if block is in-memory
  9. */
  10. public void cacheBlock(BlockCacheKey cacheKey, Cacheable buf, boolean inMemory) {
  11. CachedBlock cb = map.get(cacheKey);
  12. if(cb != null) {
  13. throw new RuntimeException(“Cached an already cached block”);
  14. }
  15. cb = new CachedBlock(cacheKey, buf, count.incrementAndGet(), inMemory);
  16. long newSize = updateSizeMetrics(cb, false);
  17. map.put(cacheKey, cb);
  18. elements.incrementAndGet();
  19. if(newSize > acceptableSize() && !evictionInProgress) {
  20. runEviction();
  21. }
  22. }

在evict方法中, 

1. 计算总size和需要free的size, minsize = (long)Math.floor(this.maxSize * this.minFactor);其中minFactor是可配置的”hbase.lru.blockcache.min.factor”(0.75f);

  1. long currentSize = this.size.get();
  2. long bytesToFree = currentSize - minSize();

2. 初始化三种BlockBucket:bucketSingle,bucketMulti,bucketMemory并遍历map,按照三种类型分别add进各自的queue(MinMaxPriorityQueue.expectedSize(initialSize).create();)中, 并按照访问的次数逆序。 

三种类型的区别是: 

    SINGLE对应第一次读的 

    MULTI对应多次读 

    MEMORY是设定column family中的IN_MEMORY为true的

  1. // Instantiate priority buckets
  2. BlockBucket bucketSingle = new BlockBucket(bytesToFree, blockSize,
  3. singleSize());
  4. BlockBucket bucketMulti = new BlockBucket(bytesToFree, blockSize,
  5. multiSize());
  6. BlockBucket bucketMemory = new BlockBucket(bytesToFree, blockSize,
  7. memorySize());

其中三种BlockBuckt Size大小分配比例默认是: 

  static final float DEFAULT_SINGLE_FACTOR = 0.25f; 

  static final float DEFAULT_MULTI_FACTOR = 0.50f; 

  static final float DEFAULT_MEMORY_FACTOR = 0.25f;

  1. private long singleSize() {
  2. return (long)Math.floor(this.maxSize * this.singleFactor * this.minFactor);
  3. }
  4. private long multiSize() {
  5. return (long)Math.floor(this.maxSize * this.multiFactor * this.minFactor);
  6. }
  7. private long memorySize() {
  8. return (long)Math.floor(this.maxSize * this.memoryFactor * this.minFactor);
  9. }

并将三种BlockBuckt 加入到优先队列中,按照totalSize – bucketSize排序,,再计算需要free大小,执行free:

  1. PriorityQueue<BlockBucket> bucketQueue =
  2. new PriorityQueue<BlockBucket>(3);
  3. bucketQueue.add(bucketSingle);
  4. bucketQueue.add(bucketMulti);
  5. bucketQueue.add(bucketMemory);
  6. int remainingBuckets = 3;
  7. long bytesFreed = 0;
  8. BlockBucket bucket;
  9. while((bucket = bucketQueue.poll()) != null) {
  10. long overflow = bucket.overflow();
  11. if(overflow > 0) {
  12. long bucketBytesToFree = Math.min(overflow,
  13. (bytesToFree - bytesFreed) / remainingBuckets);
  14. bytesFreed += bucket.free(bucketBytesToFree);
  15. }
  16. remainingBuckets–;
  17. }

free方法中一个一个取出queue中block,由于是按照访问次数逆序,所以从后面取出就是先取出访问次数少的,将其在map中一个一个remove, 并更新Mertrics.

  1. public long free(long toFree) {
  2. CachedBlock cb;
  3. long freedBytes = 0;
  4. while ((cb = queue.pollLast()) != null) {
  5. freedBytes += evictBlock(cb);
  6. if (freedBytes >= toFree) {
  7. return freedBytes;
  8. }
  9. }
  10. return freedBytes;
  11. }
  12. otected long evictBlock(CachedBlock block) {
  13. map.remove(block.getCacheKey());
  14. updateSizeMetrics(block, true);
  15. elements.decrementAndGet();
  16. stats.evicted();
  17. return block.heapSize();

3. HBase LruBlockCache的特点是针对不同的访问次数使用不同的策略,避免频繁的更新的Cache(便如Scan),这样更加有利于提高读的性能。

HBase BlockCache的更多相关文章

  1. hbase实践(十六) BlockCache

    0 引言 和其他数据库一样,优化IO也是HBase提升性能的不二法宝,而提供缓存更是优化的重中之重. 根据二八法则,80%的业务请求都集中在20%的热点数据上,因此将这部分数据缓存起就可以极大地提升系 ...

  2. HBase 查询导致RegionServer OOM故障复盘

    背景:我司作为某运营商公司的技术咨询公司,发现有第三方开发公司在使用HBase 1.1.2 (HDP 2.4.2.258版本)一段时间使用正常后,从某一天开始报OOM,从而导致RegionServer ...

  3. HBase的BlockCache

    BlockCache 首先要明白Block,在HBase里面存储的最小单元:在memstore向硬盘刷的时候,如果目标block的大小+size之后大于MAX_SIZE,将会新创建一个block来存储 ...

  4. HBase之BlockCache数据读取(转)

    转自:http://blog.csdn.net/u014297175/article/details/47976909 Hbase上Regionserver的内存分为两个部分,一部分作为Memstor ...

  5. hbase伪分布式平台搭建(centos 6.3)

    搭建完<hadoop伪分布式平台>后就开始搭建hbase伪分布式平台了.有了hadoop环境,搭建hbase就变得很容易了. 一.Hbase安装 1.从官网下载最新版本Hbase安装包1. ...

  6. HBase change split policy on an existing table

    hbase(main)::> create 'test_table_region', 'username' row(s) in 1.2150 seconds hbase(main)::> ...

  7. HBase的基本架构及其原理介绍

    1.概述:最近,有一些工程师问我有关HBase的基本架构的问题,其实这个问题仅仅说架构是非常简单,但是需要理解.在这里,我觉得可以用HDFS的架构作为借鉴.(其实像Hadoop生态系统中的大部分组建的 ...

  8. HBase设计与开发性能优化(转)

    本文主要是从HBase应用程序设计与开发的角度,总结几种常用的性能优化方法.有关HBase系统配置级别的优化,这里涉及的不多,这部分可以参考:淘宝Ken Wu同学的博客. 1. 表的设计 1.1 Pr ...

  9. hive与hbase整合过程

    实现目标 Hive可以实时查询Hbase中的数据. hive中的表插入数据会同步更新到hbase对应的表中. 可以将hbase中不同的表中的列通过 left 或 inner join 方式映射到hiv ...

随机推荐

  1. 【IOS 开发】基本 UI 控件详解 (UIDatePicker | UIPickerView | UIStepper | UIWebView | UIToolBar )

    转载注明出处 : http://blog.csdn.net/shulianghan/article/details/50348982 一. 日期选择器 (UIDatePicker) UIDatePic ...

  2. UNIX网络编程——SOCKET API和TCP STATE的对应关系_三次握手_四次挥手及TCP延迟确认

    在socket系统调用中,如何完成三次握手和四次挥手: SOCK_DGRAM即UDP中的connect操作知识在内核中注册对方机器的IP和PORT信息,并没有建立连接的过程,即没有发包,close也不 ...

  3. Activity之间的数据传递-android学习之旅(四十七)

    activity之间的数据传递主要有两种,一种是直接发送数据,另一种接受新启动的activity返回的数据,本质是一样的 使用Bundle传递数据 Intent使用Bundle在activity之间传 ...

  4. 【Unity技巧】开发技巧(技巧篇)

    写在前面 和备忘录篇一样,这篇文章旨在总结Unity开发中的一些设计技巧,当然这里只是我通过所见所闻总结的东西,如果有不对之处欢迎指出. 技巧1:把全局常量放到一个单独的脚本中 很多时候我们需要一些常 ...

  5. C#中的泛型化方法的实现

    在一个基本数据类型的方法中求解最大值或者最小值是一件很方便,同时也是很简单的事.但是如果你想复用这个方法,我们就需要使用到泛型编程的概念了.这就好比是C++中的模板函数,或者java中的泛型操作.相比 ...

  6. JDK6和JDK7中String的substring()方法及其差异

    翻译人员: 铁锚 翻译日期: 2013年11月2日 原文链接: The substring() Method in JDK 6 and JDK 7   在JDK6与JDK7这两个版本中,substri ...

  7. PA 项目关联项目经理

    ---- 项目关联项目经理 DECLARE p_project_id NUMBER := 155233; l_project_role_id NUMBER := ''; p_employee_id N ...

  8. 【Android 应用开发】Android 网络编程 API笔记 - java.net 包 权限 地址 套接字 相关类 简介

    Android 网络编程相关的包 : 9 包, 20 接口, 103 类, 6 枚举, 14异常; -- Java包 : java.net 包 (6接口, 34类, 2枚举, 12异常); -- An ...

  9. 【嵌入式开发】向开发板中烧写Linux系统-型号S3C6410

    作者 : 万境绝尘 转载请著名出处 终于拿到板子了, 嵌入式开发正式开启. 板子型号 : 三星 S3C6410 基于ARM11, 指令集基于arm6指令集; 为毛不是 Cortext A9的板子; 烧 ...

  10. H5学习之旅-H5的样式(5)

    样式的引入方式 外部样式表 link rel = "stylesheet" type = "text/css" href = "mystyle.css ...