HBase 0.1.0 Put流程源码分析

17 篇文章 0 订阅
16 篇文章 0 订阅
本文详细分析了HBase 0.1.0中Put流程,遵循LSM-Tree理论,Put操作先写入内存sortedmap,批量写入磁盘。内容包括:1) hlog记录操作;2) memcache的size管理和flush机制;3) 写入过程中的锁机制;4) 数据安全性及高读性能的实现。
摘要由CSDN通过智能技术生成

put的过程相对比较简单,因为根据LSM-Tree的理论,写入操作会写入到内存中,然后再batch的写入磁盘。

HBase的实现也是如此。


首先,从客户端的batch操作中提取出所有的put操作并放在一个sortedmap中(localput):

Text row = b.getRow();
    long lockid = obtainRowLock(row);

    long commitTime =
      (timestamp == LATEST_TIMESTAMP) ? System.currentTimeMillis() : timestamp;
      
    try {
      List<Text> deletes = null;
      for (BatchOperation op: b) {
        HStoreKey key = new HStoreKey(row, op.getColumn(), commitTime);
        byte[] val = null;
        if (op.isPut()) {
          val = op.getValue();
          if (HLogEdit.isDeleted(val)) {
            throw new IOException("Cannot insert value: " + val);
          }
        } else {
          if (timestamp == LATEST_TIMESTAMP) {
            // Save off these deletes
            if (deletes == null) {
              deletes = new ArrayList<Text>();
            }
            deletes.add(op.getColumn());
          } else {
            val = HLogEdit.deleteBytes.get();
          }
        }
        if (val != null) {
          localput(lockid, key, val);
        }
      }
localput将batch中的put操作的数据存放在targetColumns中,再用update方法update到每个HStore的memcache中:

TreeMap<HStoreKey, byte[]> edits = this.targetColumns.remove(Long.valueOf(lockid));
      if (edits != null && edits.size() > 0) {
        update(edits);
      }
update的过程分为以下几个步骤:

1.hlog增加此次操作的信息
2.遍历每个edit信息。取出key和value,增加memcache的size
3.添加key和value到memcache里
4.如果size大于memcacheflushsize则强制flush

this.log.append(regionInfo.getRegionName(),
          regionInfo.getTableDesc().getName(), updatesByColumn);

long size = 0;
for (Map.Entry<HStoreKey, byte[]> e: updatesByColumn.entrySet()) {
HStoreKey key = e.getKey();
byte[] val = e.getValue();
size = this.memcacheSize.addAndGet(key.getSize() +
    (val == null ? 0 : val.length));
stores.get(HStoreKey.extractFamily(key.getColumn())).add(key, val);
}
if (this.flushListener != null && size > this.memcacheFlushSize) {
// Request a cache flush
this.flushListener.flushRequested(this);
}

总结:

1.put操作因为只put到内存的sortedmap中就返回,因此速度非常快,这也是HBase的LSM-Tree引以为豪的地方之一

2.写入memcache时会先加读锁,但好像没加写锁,这是为啥。。。是因为memcache里的sortedmap是Collections.synchronizedSortedMap的吗?

3.可以看出是put的过程是先写hlog再写内存的,因此只要写到内存的数据就可以认为是安全的了

4.每次写入memcache都会check是否到了flush的size,如果到了就会触发flush。

5.flush会将内存中的数据写入hdfs文件系统。这种定期batch的写文件效率是非常高的,而且在没有flush时不占读的io,无形中留了很多io给读操作,增加了读的性能




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值