前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Hbase Memstore 读写及 flush 源码分析

Hbase Memstore 读写及 flush 源码分析

原创
作者头像
sundyxiong
修改2017-08-23 09:42:17
3.1K0
修改2017-08-23 09:42:17
举报
文章被收录于专栏:熊训德的专栏熊训德的专栏

导语

本文档主要从源码的角度分析了,hbase的写缓存的读写以及flush过程。因为在分析wal的过程中已经把写分析的比较详尽了,而因为memstore是内存结构读的过程比较简单,本文档概要说明memstore的读写,着重分析flush过程。

写的角度

1.准备工作,主要是和Coprocessor相关

2.获得行锁,把所有要更新的行锁都拿到通过getRowLockInternal(byte[] row, boolean waitForLock),这个方法会在每个锁上都轮询一直拿到所有row的锁。

有关原理可以参考:

http://blog.csdn.net/lipeng_bigdata/article/details/50458771

3.获得region的update锁,具体的说是java.util.concurrent.locks包中ReentrantReadWriteLock的读锁。

HRegion中声明了两个锁,分别是lock和updatelock,这里解释下。这两个锁均为ReentrantReadWriteLock类型的读写锁,其中,lock用于Region的close、compact、flush等的并发控制,它控制的是Region的整体行为,更具体的,compact()和flushCache()方法中,用的是lock的读锁--共享锁,而doClose()方法中,用的是lock的写锁--独占锁,这也就意味着,在Region下线,执行doClose()方法时,它必须等待compact()和flushCache()方法调用完,且一旦它获得了lock的写锁,后续Region将不会再执行Region的compact和flush,当然,doClose()内部仍然会在下线前flush掉它的memstore,同时共享锁业也实现了Region的flush和compact在理论上可以同时进行。而updatesLock则用于Region数据更新方面,在flush的核心方法internalFlushcache()中,则是使用的updatesLock的写锁。

doProcessRowWithTimeout-》让 processor(MultiRowMutationProcessor 用于执行多个 put/delete)扫描rows,生成mutations和waledits。(Let the processor scan the rows, generate mutations and add waledits)

主要是检查cf并生成时间戳并把同一行的更新Cell放到一个WALEdit中。

这里又生成一个mutations的原因是区分put和delete

6.mvcc 开始处理,也即是把通过生成的mvccId生成写Id并把当前cell放入mvcc的写队列。hbase的mvcc机制将结合行锁在后面的hbase效率的源码分析中具体分析。可先参考:

http://m.blog.csdn.net/article/details?id=43836701

7.预处理

8.和memstore应用的相关,遍历mutations,通过getStore获得HStore实例,把这些cell添加到store中。memstore中根据不同的CF对应了不同的HStore实例,HStore实例又对应了多个HFile。memstore的实际内存映射就是这些HStore。

8.append到Hlog中,准确的应该是append到RingBuffer中。详见WAL的文章

9.释放region的update锁,即3中获得的锁。

10.释放所有的row锁,即2中获得的锁。

11.同步editlog,准确的说是通知RingBuffer。

调用完成了Put的回调

-------------------->写的过程中通过调用requestFlush()方法来进行memstore的刷写。

调用所在RegionServer的MemStoreFlusher。requestFlush方法进行刷写。

读的角度

hbase的读需要从要读三个位置,blockcache、memstore和hfile着手。

大概过程是先从blockcache中读,如果没有则去memstore和hfile中去读,先用布隆过滤器把一定不可能的hfile去除,再使用scanner按时间降序扫描到需要的keyvalues,最后把相应块加到blockcache中去并发还给client端。

因为包括了整个读过程。

原理参考:

http://hbasefly.com/2016/12/21/hbase-getorscan/

http://blackproof.iteye.com/blog/2007981

和《权威指南》P327

http://hbasefly.com/2016/04/26/hbase-blockcache-2/

接下来分析本文档的重点:

Flush的角度

从memstore刷写时机(上一篇文档着重叙述)来看,有六种情况:单个memstore,一个region中,整个regionserver,Hlog,定期,和人工。

尽管触发memstore的条件很多,但实际执行memstore的flush是调用对应的HRegion的flushcache方法开始的。它的原型如下:

调用这个方法,只有在cache(memstore)为空,region已经关闭,当前flush正在进行和不能写情况下。

其调用基本过程如下:

其中flushcache()和internalFlushcache都是HRegion中的方法。

1.最开始flushcache会使用HRegion用于应对region并发控制的lock(前面有介绍)加锁。2.然后使用synchronize获得WriteState结构的状态,这个类主要用于保证Region级别的flush、compact时的状态一致。即是说有多个线程调用flushcache时,先获得这个对象的去flush。3.获取需要去flush的HStore,如果参数forceFlushAllStores为true的话,就会flush当前region上的所有stores,如果为false的话,根据配置的FlushPolicy(hbase.regionserver.flush.policy,默认是FlushLargeStoresPolicy)选择部分stores来flush。

然后调用internalFlushCache方法,这个方法实际去执行,选择一些stores到hfile(图中蓝色部分)。当刷写成功后将标记成功的memstore,并通知因writeState而阻塞的线程。最后释放lock。

在internalFlushCache方法中把flush memstore分成两部分,第一部分是准备(interPrepareFlushCache):主要是去准备一些中间数据结构和以及当前memstore的快照,这个快照的作用是在flush memstore的同时并不妨碍client对memstore的读写;第二部分是把快照刷写到一个临时目录中,然后再把临时目录中数据移到正式目录,要把具体的刷写分成这两步的就像是两阶段提交,刷写到临时目录就是确认过程而后一步就是提交过程。

我们知道hbase通过精心的设计成一个以顺序写见长的数据存储系统,而memstore刷写时的快照即是其中精心设计的部分。原理其实很简单,为了不中断读写,在prepare部分,新建一个新的memstore(HStore)并把相关指标清零,旧的memstore就作为快照刷入HFile。因为memstore都是内存操作,所以这个转换是很快的。当然在转换的过程中,update的操作会被暂停一段时间。

prepare部分另一个中间数据结构分别为:totalFlushableSizeOfFlushableStores,storeFlushCtxs,committedFiles,storeFlushableSize,比较重要的是storeFlushCtxs和committedFiles。他们都被定义为以CF做key的TreeMap,分别代表了store的CF实际执行(StoreFlusherImpl)和最终刷写的HFlile文件:

StoreFlusherImpl是HStore的内部类,它实现了StoreFlushContext的prepare,flushCache以及commit方法,这几个方法用于完成准备和刷写HStore的操作。其类图如下:

在第二部分的internalFlushCacheAndCommit刷写Hfile到临时目录和转到正式目录就比较清晰了,使用两阶段提交直接调用StoreFusherImpl的flushCache和commit方法。

稍微需要注意的是,在flush的时候有可能会失败,这时候意味着memstore未被持久化,则wal需要去重做,会启动一个单独且唯一的线程去做这个,从源码注释上看,当前只有regionserver重启会发生这种事情。

至此,memstore的读写已经刷入源码分析就结束了,可以看到memstore作为hbase写缓存为了实现快速顺序写做出的设计努力。下一篇文档将分析哪些情况下memstore会被刷写。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导语
  • 写的角度
  • 读的角度
  • Flush的角度
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档