画像体系之-HBase缓存漫谈

对着背影说爱祢 提交于 2020-01-14 04:42:18


背景

用户/内容画像的对存储的要求其实是比较高的:

    能批量更新(比如更新所有用户某个属性)
    大量随机读取(甚至可能没有热点数据)
    随机属性更新/添加
    可持久化
    易于横向扩展解决性能问题

上一次重度使用HBase已经是两年前了。HBase能够满足上面五个要求,所以用HBase作为画像体系的主要存储引擎便水到渠成。
问题

因为有批量更新,随机属性的更新/添加,那么必然会缓存失效,从而触发磁盘IO导致读取响应时间受到影响。在画像体系里,随机读取量大,比如召回了1000个id,然后你需要取这1000个id的属性集合,并且要求响应时间能够控制在100ms。基本只要碰到磁盘IO就歇菜了。所以现在我们希望HBase能够把所有数据都缓存住。
HBase读缓存特色

HBase的缓存目前我所了解的是Block Cache. Block Cache是什么概念的呢,我们知道HBase的最小文件单元是HFile, HFile是有结构的,主要包含:

    索引,可以是多层
    数据
    元数据

当然还有一个布隆过滤器,方便确定一个元素是不是在HFile里。

并且只会有三个动作:

    新增HFile
    HFile 合并
    HFile的分裂

这里需要注意HFile一旦生成里面的元素就不会被改变。

一个HFile的数据会被切分成多个Block,每个Block一般而言都会有一些元信息。当然这些切分其实是逻辑上的。Block Cache就是前面三部分的Cache. 在HBase里,当打开一个HFile时,默认会cache住一些索引信息,文件信息,读取时则会连数据都会Cache起来。当然你也可以通过参数让HBase在打开时就把数据Cache住。

如果是传统意义上的缓存,如果有更新,那么必然会导致一个问题:缓存失效。但是HBase其实并没有这个问题。一个简单的Get请求,HBase的读取方式是读MemStore 和HFile,读HFile的时候会看数据是不是已经在BlockCache里。

    MemStore,这个是写缓存,但是是有结构的,可以直接查。
    BlockCache, 这个是读缓存,也是有结构的,可以直接查。
    HFile,这个就是HDFS文件,会touch到IO。

假设我在读取的时候,MemStore没有进行flush,那么可能不会触碰到磁盘,虽然BlockCache的数据已经是老版本的了,MemStore里却有最新版本的数据,所以HBase简单的到MemStore/BlockCache都拿一遍。第二次再来拿,假设正好碰到MemStore flush生成新的HFile,这个时候就触发磁盘IO了。当然,其他如Compaction也会导致触发磁盘。
解决方案

下面解决方案的前提是,可用于BlockCache的内存大于你的数据。在画像体系里,这点可以做到的,因为内容和用户都是有限的。

根据前面的描述,为了能够保证随机读不触发磁盘IO操作,那么我们在生成新HFile的同时,也需要让它写进BlockCache,HBase也提供了相关参数让你完成这个功能:

    hfile.block.index.cacheonwrite  写HFile时把索引加入到Cache
    hfile.block.bloom.cacheonwrite 写HFile时把布隆过滤器加入到Cache
    hbase.rs.cacheblocksonwrite 写HFile时把数据也写入到Cache里

这里我们基本知道写Cache的几个时机点:

    打开HFile
    读HFile
    写HFile
 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!