Base上关于CMS、GC碎片、大缓存的一种解决方案:Bucket Cache----没看懂

2024-05-24 09:38

本文主要是介绍Base上关于CMS、GC碎片、大缓存的一种解决方案:Bucket Cache----没看懂,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

介绍BucketCache前,先对HBase的Cache做个介绍: 
一.HBase在读取时,会以Block为单位进行cache,用来提升读的性能; 


二.Block可以分类为DataBlock(默认大小64K,存储KV)、BloomBlock(默认大小128K,存储BloomFilter数据)、IndexBlock(默认大小128K,索引数据,用来加快Row所在DataBlock的定位) 




三.对于一次随机读,Block的访问顺序为BloomBlock、IndexBlock、DataBlock,如果Region下面的StoreFile数目为2个,那么一次随机读至少访问2次BloomBlock+1次IndexBlock+1次DataBlock 


四.我们通常将BloomBlock和IndexBlock统称为MetaBlock,MetaBlock线上系统中基本命中率都是100% 


五.Block的cache命中率对HBase的读性能影响十分大,所以DataBlockEncoding将KV在内存中进行压缩,对于单行多列和Row相似的场景,可以提高内存使用率,增加读性能 


六.HBase中管理缓存的Block的类为BlockCache,其实现目前主要是下面三种: 



6.1 LruBlockCache,默认的BlockCache实现,也是目前使用的BlockCache,使用一个HashMap维护Block Key到Block的映射,采用严格的LRU算法来淘汰Block,初始化时会指定容量大小,当使用量达到85%的时候开始淘汰block至75%的比例。 
优点:直接采用jvm提供的HashMap来管理Cache,简单可依赖;内存用多少占多少,JVM会帮你回收淘汰的BlOCK占用的内存 
缺点: 
1.一个Block从被缓存至被淘汰,基本就伴随着Heap中的位置从New区晋升到Old区 
2.晋升在Old区的Block被淘汰后,最终由CMS进行垃圾回收,随之带来的是Heap碎片 
3.因为碎片问题,随之而来的是GC时晋升失败的FullGC,我们的线上系统根据不同的业务特点,因为这个而发生FullGC的频率,有1天的,1周的,1月半年的都有。对于高频率的, 

在运维上通过在半夜手工触发FullGC来缓解 
4.如果缓存的速度比淘汰的速度快,很不幸,现在的代码有OOM的风险(这个可以修改下代码避免) 



6.2 SlabCache,针对LruBlockCache的碎片问题一种解决方案,使用堆外内存,处于实验性质,真实测试后,我们定位为不可用。说下它的原理:它由多个SingleSizeCache组成(所谓SingleSizeCache,就是只缓存固定大小的block,其内部维护一个ByteBuffer List,每个ByteBuffer的空间都是一样的,比如64K的SingleSizeCache,ByteBuffer的空间都是64K,cache Block时把Block的内容复制到ByteBuffer中,所以block的大小必须小于等于64K才能被这个SingleSizeCache缓存;淘汰block的时候只需要将相应的ByteBuffer标记为 

空闲,下次cache的时候对其上的内存直接进行覆盖就行了),cache Block的时候,选择一个小于且最接近的SingleSizeCache进行缓存,淘汰block亦此。由于SingleSize的局限性,其使用上和LruBlockCache搭配使用,叫做DoubleBlockCache,cache block的时候LruBlockCache和SlabCache都缓存一份,get block的时候顺序为LruBlockCache、SlabCache,如果只有SlabCache命中,那么再将block缓存到LruBlockCache中(本人觉得它的这个设计很费,你觉得呢) 

优点:其思想:申请固定内存空间,Block的读写都在这片区域中进行 
缺点: 
1.cache block和 get block的时候,需要内存复制 
2.SingleSizeCache的设计,导致内存使用率很低 
3.与LruBlockCache搭配使用不合理,导致所有的block都会去LruBlockCache中逗留一下,结果是CMS和碎片都不能有所改善 


6.3 BucketCache,可以看成是对SlabCache思想在实现上的一种改进及功能扩展,其优点是解决LruBlockCache的缺点及支持面向高性能读的大缓存空间. 



1.何谓大缓存?缓存Block的存储介质不再仅仅依赖在内存上,而是可以选择为Fusion-io、SSD等高速磁盘,我们称之为二级缓存 



2.何谓Bucket?我们将缓存空间划分为一个个的Bucket,每个Bucket都贴上一个size标签,将Block缓存在最接近且小于size的bucket中(和SingleSizeCache很相似) 



3.怎么解决CMS 碎片问题?Block存储在Bucket中,而每个Bucket的物理存储是不变的,也就是说系统刚启动的时候,我们就申请了一堆Bucket内存空间,而这些内存空间是一直在Old区,block的Get/Cache动作只是对这片空间的访问/覆写,CMS/碎片自然大大减少 



4.怎么使用?上面的描述指出BucketCache可以有两种用法: 
4.1 与LruBlockCache搭配,作为主要的内存cache方案使用 




 


4.2 作为二级缓存使用,将Block缓存在我们的高速盘(Fusion-IO)中 




 


5.BucketCache中的Cache/Get Block逻辑? 



 



 



简单地描述下: 
CacheBlock的时候,将Block放在一个RAMMap和一个Queue中,然后WriterThread异步从Queue中remove Block写入到IOEngine(内存或高速盘)中,并将BlockKey及其位置、长度等信息记录在backingMap 
GetBlock的时候,先访问RAMMap,然后访问backingMap获取block的位置及长度,从IOEngine读取数据 


6.Block在IOEngine中的位置是怎么分配的? 




 


我们将物理空间划分为一堆等大的Bucket,每一个Bucket有一个序号及一个size标签,于是Block所在bucket的序号及其在bucket中的offset与block在物理空间的offset就形成了一一对应。我们通过BucketAllocator为指定大小的Block寻找一个Bucket进行存放,于是就得到了其在物理空间上的位置。 



上图描述了BucketAllocator对于Bucket的组织管理: 

6.1 每个Bucket都有一个size标签,目前对于size的分类,是在启动时候就确定了,如默认的有(8+1)K、(16+1)K、(32+1)K、(40+1)K、(48+1)K、(56+1)K、(64+1)K、(96+1)K ... (512+1)K 


6.2 相同size标签的Bucket由同一个BucketSizeInfo管理 


6.3 Bucket的size标签可以动态调整,比如64K的block数目比较多,65K的bucket被用完了以后,其他size标签的完全空闲的bucket可以转换成为65K的bucket,但是至少保留一个该size的bucket 




6.4 如果最大size的bucket为513K,那么超过这个大小的block无法存储,直接拒绝 


6.5 如果某个size的bucket用完了,那么会依照LRU算法触发block淘汰 



问题: 

6.6.如果系统一开始都是某个size的block,突然变成另外个size的block(不能存在同个size的bucket中),根据6.5不是会不停地进行淘汰算法? 
是的,但是由于淘汰是异步的,影响不大,而且随着淘汰进行,bucket的大小会逐渐向那个block size大小bucket转移,最终稳定 



6.7 BucketAllocator中allocate block的流程? 



 





 



6.8 BucketAllocator中free block的流程? 



 


6.9 第一种使用的测试结果 



 


6.10 第二种使用的测试结果 




 


6.11 更多细节,尽在代码中 

https://issues.apache.org/jira/browse/HBASE-7404 

 

这篇关于Base上关于CMS、GC碎片、大缓存的一种解决方案:Bucket Cache----没看懂的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/998041

相关文章

缓存雪崩问题

缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。 解决方案: 1、使用锁进行控制 2、对同一类型信息的key设置不同的过期时间 3、缓存预热 1. 什么是缓存雪崩 缓存雪崩是指在短时间内,大量缓存数据同时失效,导致所有请求直接涌向数据库,瞬间增加数据库的负载压力,可能导致数据库性能下降甚至崩溃。这种情况往往发生在缓存中大量 k

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

js异步提交form表单的解决方案

1.定义异步提交表单的方法 (通用方法) /*** 异步提交form表单* @param options {form:form表单元素,success:执行成功后处理函数}* <span style="color:#ff0000;"><strong>@注意 后台接收参数要解码否则中文会导致乱码 如:URLDecoder.decode(param,"UTF-8")</strong></span>

Redis中使用布隆过滤器解决缓存穿透问题

一、缓存穿透(失效)问题 缓存穿透是指查询一个一定不存在的数据,由于缓存中没有命中,会去数据库中查询,而数据库中也没有该数据,并且每次查询都不会命中缓存,从而每次请求都直接打到了数据库上,这会给数据库带来巨大压力。 二、布隆过滤器原理 布隆过滤器(Bloom Filter)是一种空间效率很高的随机数据结构,它利用多个不同的哈希函数将一个元素映射到一个位数组中的多个位置,并将这些位置的值置

一种改进的red5集群方案的应用、基于Red5服务器集群负载均衡调度算法研究

转自: 一种改进的red5集群方案的应用: http://wenku.baidu.com/link?url=jYQ1wNwHVBqJ-5XCYq0PRligp6Y5q6BYXyISUsF56My8DP8dc9CZ4pZvpPz1abxJn8fojMrL0IyfmMHStpvkotqC1RWlRMGnzVL1X4IPOa_  基于Red5服务器集群负载均衡调度算法研究 http://ww

明明的随机数处理问题分析与解决方案

明明的随机数处理问题分析与解决方案 引言问题描述解决方案数据结构设计具体步骤伪代码C语言实现详细解释读取输入去重操作排序操作输出结果复杂度分析 引言 明明生成了N个1到500之间的随机整数,我们需要对这些整数进行处理,删去重复的数字,然后进行排序并输出结果。本文将详细讲解如何通过算法、数据结构以及C语言来解决这个问题。我们将会使用数组和哈希表来实现去重操作,再利用排序算法对结果

UE5 半透明阴影 快速解决方案

Step 1: 打开该选项 Step 2: 将半透明材质给到模型后,设置光照的Shadow Resolution Scale,越大,阴影的效果越好

防止缓存击穿、缓存穿透和缓存雪崩

使用Redis缓存防止缓存击穿、缓存穿透和缓存雪崩 在高并发系统中,缓存击穿、缓存穿透和缓存雪崩是三种常见的缓存问题。本文将介绍如何使用Redis、分布式锁和布隆过滤器有效解决这些问题,并且会通过Java代码详细说明实现的思路和原因。 1. 背景 缓存穿透:指的是大量请求缓存中不存在且数据库中也不存在的数据,导致大量请求直接打到数据库上,形成数据库压力。 缓存击穿:指的是某个热点数据在

PHP APC缓存函数使用教程

APC,全称是Alternative PHP Cache,官方翻译叫”可选PHP缓存”。它为我们提供了缓存和优化PHP的中间代码的框架。 APC的缓存分两部分:系统缓存和用户数据缓存。(Linux APC扩展安装) 系统缓存 它是指APC把PHP文件源码的编译结果缓存起来,然后在每次调用时先对比时间标记。如果未过期,则使用缓存的中间代码运行。默认缓存 3600s(一小时)。但是这样仍会浪费大量C

缓存策略使用总结

缓存是提高系统性能的最简单方法之一。相对而言,数据库(or NoSQL数据库)的速度比较慢,而速度却又是致胜的关键。 如果使用得当,缓存可以减少相应时间、减少数据库负载以及节省成本。本文罗列了几种缓存策略,选择正确的一种会有很大的不同。缓存策略取决于数据和数据访问模式。换句话说,数据是如何写和读的。例如: 系统是写多读少的吗?(例如基于时间的日志)数据是否是只写入一次并被读取多次?(例如用户配