HBase写流程源码--1.4.11

这些肯定不全是自己的,但是参考别人的文章加上自己的独立思考,一定能有新的收获

这里主打讲一下写入流程的源码,以及给出自己的参考资料~ 然后谈一下自己rowkey设计的想法好了,其实我没设计过多少rowkey,每次都是业务自己设计的哈哈哈(然后一堆热点问题mmd)

所以规范业务的行为也是十分重要的,包括重要的列族设计,以及rowkey设计,如果业务不规范使用出问题了那就不是咱的问题

写流程概览图

(客户端连接zookeeper --> 寻找meta --> 找到对应的RS --> RS写入请求)

连接zookeeper就不再赘述了,那么meta怎么就知道你的region在哪里呢?

因为hbase:meta中的信息是这样的,一个region对应的RS以及regionInfo都会存在于meta中,所以zookeeper中找到meta表之后对meta进行一次扫描就知道region在哪里啦,当然meta信息是会被缓存的,不然每次都scan一次小心把meta扫坏了(不会的不会的!)

这里就不赘述其中的主体过程了:看getTableRegionsAndLocations方法即可,可以看出扫描scan的过程,然后将其缓存

batch Put写入

单条put写入即直接找到对应的region,发送到该regionServer即可

batch Put写入需要先找到对应的所有region,然后通过region对其中的RS进行分组,发往不同的RS进行相关的处理,这个地方每一个RS packet都需要一个RPC调用

所以连续发送300条单条put和批量300的put需要的RPC调用次数是差距很大的,不过客户端是可以进行缓存put的,但是这个缓存如果客户端宕机的话会丢失。但是batch size也不要太大了,因为RS处理每一个regionAction是串行处理的哟

通过RSRpcServices中的multi来处理批量请求,根据请求的类型进行不同的操作

RS传递给自家region进行mutate(其实就是写入啦),但是总感觉比write高级不少的样子

重点方法:processRowsWithLocks,这里就涉及核心的写入方式了

1.拿锁 包括行锁和region锁 

acquiredRowLocks 以及 lock region

2.设置所有的写入时间为当前的系统时间(KV时间)

  得到系统时间并且设置成即将写入的WAL的值

long now = EnvironmentEdgeManager.currentTime();

3.构建WALEDIT并且写入WAL,但是不需要同步即可进行下一步(高效生产消费者队列),写入WAL的时候,如果是multi那么所有的KV都会被构建为一条WALEDIT,这样回滚也会很方便

processor.preBatchMutate(this, walEdit);
walKey = new HLogKey(this.getRegionInfo().getEncodedNameAsBytes(),
  this.htableDescriptor.getTableName(), WALKey.NO_SEQUENCE_ID, now,
  processor.getClusterIds(), nonceGroup, nonce, mvcc);
txid = this.wal.append(this.htableDescriptor, this.getRegionInfo(),
    walKey, walEdit, true);

4.开始mvcc事务

writeEntry = walKey.getWriteEntry();
mvccNum = walKey.getSequenceId();

5.写入memStore

for (Mutation m : mutations) {
  // Handle any tag based cell features
  rewriteCellTags(m.getFamilyCellMap(), m);

  for (CellScanner cellScanner = m.cellScanner(); cellScanner.advance();) {
    Cell cell = cellScanner.current();
    CellUtil.setSequenceId(cell, mvccNum);
    Store store = getStore(cell);
    if (store == null) {
      checkFamily(CellUtil.cloneFamily(cell));
      // unreachable
    }
    addedSize += store.add(cell);
  }
}

6.释放region锁和行锁
if (locked) {
  this.updatesLock.readLock().unlock();
  locked = false;
}

// 10. Release row lock(s)
releaseRowLocks(acquiredRowLocks);

7.sync WAL,WAL如果sync失败则直接回滚,包括memStore也需要回滚

syncOrDefer(txid, getEffectiveDurability(processor.useDurability()));

8.mvcc前进,此时数据才是真的可以被查询了

mvcc.completeAndWait(writeEntry);

hhh本来准备打算仔细梳理一下流程的,但是发现非常非常繁琐,不如了解一个大概就行,如果哪天出现问题知道怎么排查就好!

之后的流程就是memStore的刷写以及写入HFile,然后是HFile的comapction,compaction会造成写入的二次放大,所以在设计上可以避免的事情就尽量避免~

参考资料:

HBase原理与实践

一条数据的HBase之旅,简明HBase入门教程-Write全流程 | NoSQL漫谈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值