hbase 源代码分析 (7) put 过程 详解
来源:互联网 发布:sql 报表开发工具 编辑:程序博客网 时间:2024/06/07 21:54
上一章节: hbase 源代码分析(6)get 过程 详解
http://blog.csdn.net/chenfenggang/article/details/75042658
put 过程:
1)首先根据获得一个客户端的BufferedMutator;
2)当数据量到一定时,或者关闭table,或者手动提交时才开始提交。
3)提前全会分布获取每个put记录的ServiceName,然后建立一个Map<ServiceName,List<ROW>>。分别并行将记录发往各个regionService
4) regionService 获得信息之后,发给个region。数据put的只是放在内存memstore中,当达到阈值之后写入HFile。
这里将逐步分析这个过程。
入口。
Put put = new Put("rowkey".getBytes();
put.addColumn("family".getBytes(),"qualifier".getBytes(),"value".getBytes());
htable.put(put);
@Override
public void put(final Put put) throws IOException {
getBufferedMutator().mutate(put);
if (autoFlush) {
flushCommits();
}
}
获取缓存器,这里是个单例。一个Htable维持一份BufferedMutator,如果自动刷新就会执行flushCommits();
private void backgroundFlushCommits(boolean synchronous) throws
InterruptedIOException,
...
if (!synchronous) {
异步提交。
ap.submit(tableName, buffer, true, null, false);
- .......
}
//否则可以同步。同步需要等待buffer为空。
if (synchronous || ap.hasError()) {
while (!buffer.isEmpty()) {
ap.submit(tableName, buffer, true, null, false);
}
...
}
// 因为中间可以没有提交成功,需要重新计算这部分占用的空间。
} finally {
for (Mutation mut : buffer) {
long size = mut.heapSize();
currentWriteBufferSize.addAndGet(size);
dequeuedSize -= size;
writeAsyncBuffer.add(mut);
}
}
}
提交之前会将消息分组,就好物流分货一样,发往深圳放一堆。
public <CResult> AsyncRequestFuture submit(ExecutorService pool, TableName tableName,
List<? extends Row> rows, boolean atLeastOne, Batch.Callback<CResult> callback,
boolean needResults) throws InterruptedIOException {
...
Map<ServerName, MultiAction<Row>> actionsByServer =
new HashMap<ServerName, MultiAction<Row>>();
....
. do {
//等待有空线程,如果没有会一直等下去
waitForMaximumCurrentTasks(maxTotalConcurrentTasks - 1, tableName.getNameAsString());
- .....
- RegionLocations locs = connection.locateRegion(
tableName, r.getRow(), true, true, RegionReplicaUtil.DEFAULT_REPLICA_ID);
//这个方法,会将相同
getServerName ,row 放在一起。addAction(loc.getServerName(), regionName, action, actionsByServer, nonceGroup);
} while (retainedActions.isEmpty() && atLeastOne && (locationErrors == null));
if (retainedActions.isEmpty()) return NO_REQS_RESULT;
return submitMultiActions(tableName, retainedActions, nonceGroup, callback, null, needResults,
locationErrors, locationErrorRows, actionsByServer, pool);
}
发送前生成
Runnable runnable =
new SingleServerRequestRunnable(runner.getActions(), numAttempt, server,
都包含各种的需要发送的ROW 已经ServiceName
SingleServerRequestRunnable 实现的runnable ,有执行器执行。跑里面的run方法。在里面创建了callable,和caller
由caller调用call(callable).代码如下:caller很多地方将到来,所以不再详细说明。
@Override
public void run() {
...//new 一个callable
callable = createCallable(server, tableName, multiAction);
..//caller
RpcRetryingCaller<MultiResponse> caller = createCaller(callable, rpcTimeout);
... //调用
res = caller.callWithoutRetries(callable, operationTimeout);
...
- // 检查返回结果
receiveMultiAction(multiAction, server, res, numAttempt);
...
}
在callable的call方法里有个
responseProto = getStub().multi(controller, requestProto);
这里就是发送到RegionService。通过clientprotos 。
下面是服务端。
@Override
public MultiResponse multi(final RpcController rpcc, final MultiRequest request)
throws ServiceException {
...
这里主要做些解析过程,已经认证。
for (RegionAction regionAction : request.getRegionActionList()) {
region = getRegion(regionAction.getRegion());
按region又分一次
ClientProtos.RegionLoadStats stats = mutateRows(region, regionAction.getActionList(),
cellScanner);
}
}
里面再建立批量RowMutations,而且不用区分delete和put
然后
@Override
public void processRowsWithLocks(RowProcessor<?,?> processor, long timeout,
long nonceGroup, long nonce) throws IOException {
- //主要是处理协处理钩子
- startRegionOperation();
//行锁。
Collection<byte[]> rowsToLock = processor.getRowsToLock();
//写
WALKeydoProcessRowWithTimeout(
processor, now, this, mutations, walEdit, timeout);
- //多版本
- // 7. Start mvcc transaction
writeEntry = walKey.getWriteEntry();
mvccNum = walKey.getSequenceId();
- //写入内存
- // 8. Apply to memstore
for (Mutation m : mutations) {
for (CellScanner cellScanner = m.cellScanner(); cellScanner.advance();) {
Store store = getStore(cell);
addedSize += store.add(cell);
}
}
}
所以数据put都放在内存中。当addedSize的尺寸大于阈值时会spit到HFile里面。
这个后面再讲。
到此put过程结束。
未完待续...
阅读全文
0 0
- hbase 源代码分析 (7) put 过程 详解
- hbase 源代码分析(5)regionLocator 获取region过程 详解
- hbase 源代码分析(6)get 过程 详解
- hbase 源代码分析 (8) delete 过程 详解
- HBase源码分析:HTable put过程
- hbase 源代码分析 (15)compact 过程
- hbase 源代码分析 (17)MapReduce 过程
- hbase 源代码分析 (9) hbase启动过程
- hbase 源代码分析 (12) Master和RegionService 启动过程
- hbase中Put源码分析
- hbase put regionserver处理分析
- HBase分析之Put操作
- hbase 源代码分析 (19) HMaster 启动负载均衡过程分析
- HBase 0.99 源代码分析 - Master启动过程(1)
- HBase 0.99 源代码分析 - Master启动过程(2)
- HBase 0.1.0 Put流程源码分析
- HBase-put写操作源码分析
- HBase put操作client端分析
- 221. Maximal Square
- hdu1711(kmp算法)
- Java 将一个list按照某个字段分组后放入到一个新的list里面
- POJ 1364 King
- Hook Android C代码基础总结
- hbase 源代码分析 (7) put 过程 详解
- fdisk对一个块设备进行分区
- 把数组排成最小的数
- Linux系统编程——线程同步与互斥:读写锁
- Java经典算法40例(二十一)
- day_07C语言运算符及流程控制
- 使用Hammer做一个类似于苹果手机多的AssistiveTouch一样的东西,可以随意拖动
- 【内功篇】C语言的输入输出浅析(三)
- 算法之插入排序