hbase 源代码解析(23)truncate 和truncate_preserve流程分析

来源:互联网 发布:mac qq 编辑:程序博客网 时间:2024/05/18 02:26
原文地址:http://blog.csdn.net/chenfenggang/article/details/78335970
命令作用:清空表数据,但是保留表结构,
分析原因:今天定位一个奇怪的现象,当hbase建立4个region的表,然后用truncate命令时,出现1个region在线而有4个region offline,
然后继续put数据,制定split到4个region时,使用truncate_preserve发现出现9个offline,7个failed,并且再put数据时出现表不存在,
问题还在定位中。所以需要分析源码。
1)truncate shell命令入口
  1. module Shell
  2. module Commands
  3. class Truncate < Command
  4. def help
  5. return <<-EOF
  6. Disables, drops and recreates the specified table.
  7. EOF
  8. end
  9. def command(table)
  10. format_simple_command do
  11. puts "Truncating '#{table}' table (it may take a while):"
  12. admin.truncate(table) { |log| puts " - #{log}" }
  13. end
  14. end
  15. end
  16. end
  17. end

2)客户端有HBaseAdmin 发起,经MasterRpcServices转接,由HMaster执行,主要代码如下:preserveSplits是命令truncate_preserve时,保留region个数。否则region变为1.
  1. MasterProcedureUtil.submitProcedure(
  2. new MasterProcedureUtil.NonceProcedureRunnable(this, nonceGroup, nonce) {
  3. @Override
  4. protected void run() throws IOException {
  5. getMaster().getMasterCoprocessorHost().preTruncateTable(tableName);
  6. LOG.info(getClientIdAuditPrefix() + " truncate " + tableName);
  7. long procId = submitProcedure(new TruncateTableProcedure(procedureExecutor.getEnvironment(),
  8. tableName, preserveSplits));
  9. ProcedureSyncWait.waitForProcedureToComplete(procedureExecutor, procId);
  10. getMaster().getMasterCoprocessorHost().postTruncateTable(tableName);
  11. }

这里可以分两步,
第一个submitProcedure怎么运行的。
第二个truncateTableprocedure里的具体流程是什么

1、submitProcedure
这个流程主要如下:
1)从Hmaster获取ProcedureExecutor
2)ProcedureExecutor 是在HMaster 启动时执行的startProcedureExecutor();
3)startProcedureExecutor里面调用了,procedureExecutor.start(numThreads, abortOnCorruption);
4)start里面调用一个循环execLoop(); ----(类ProcedureExecutor中
5)execLoop里面是循环,不断从集合ProcedureRunnableSet runnables里拿到进程然后执行execLoop(proc);
6)execLoop(proc)主要执行 execProcedure(procStack, proc); ----(类ProcedureExecutor中
7)最终会调用 procedure.doExecute(getEnvironment());
8)doExecute 会调用execute(env); (类Procedure中
9)在execute(env)中会调用 executeFromState (类StateMachineProcedure中)
所以只需要关心procedure的executeFromState方法就行。
2、TruncateTableprocedure
在这个类里面主要关心方法executeFromState:
1)TRUNCATE_TABLE_PRE_OPERATION(0, 1),   准备动作:regions=ProcedureSyncWait.getRegionsFromMeta(env, getTableName());
        这里还做了写协处理器问题。getRegionsFromMeta就只一个查询动作
2)TRUNCATE_TABLE_REMOVE_FROM_META(1, 2),
     在META表中删除数据:DeleteTableProcedure.deleteFromMeta(env, getTableName(), regions);
                这个就是一些delete操作
3)TRUNCATE_TABLE_CLEAR_FS_LAYOUT(2, 3),
        清除File:DeleteTableProcedure.deleteFromFs(env, getTableName(), regions, true);
                    这里主要注意的是如果设置里归档,会将记录进行归档,否则直接会删除
         重新创建regionInfo:regions= recreateRegionInfo(regions);
                    这里如果保留regions的分区,采用的这个方法,如果不是,就直接new一个regionInfo startkey 和endkey都为null
4)TRUNCATE_TABLE_CREATE_FS_LAYOUT(3, 4),
  重新创建FS目录,主要根据region建立:regions=CreateTableProcedure.createFsLayout(env, hTableDescriptor, regions);
5)TRUNCATE_TABLE_ADD_TO_META(4, 5),
    将新的region信息添加到META表: regions =CreateTableProcedure.addTableToMeta(env, hTableDescriptor, regions);
 
6)TRUNCATE_TABLE_ASSIGN_REGIONS(5, 6),
    分配region给regionServer:CreateTableProcedure.assignRegions(env, getTableName(), regions);
        这个是createTable必须做的事情。
7)TRUNCATE_TABLE_POST_OPERATION(6, 7), 
        处理一些协处理器: postTruncate(env);
完整代码如下:
  1. @Override
  2. protected Flow executeFromState(final MasterProcedureEnv env, TruncateTableState state)
  3. throws InterruptedException {
  4. try {
  5. switch (state) {
  6. case TRUNCATE_TABLE_PRE_OPERATION:
  7. // Verify if we can truncate the table
  8. if (!prepareTruncate(env)) {
  9. assert isFailed() : "the truncate should have an exception here";
  10. return Flow.NO_MORE_STATE;
  11. }
  12. // TODO: Move out... in the acquireLock()
  13. LOG.debug("waiting for '" + getTableName() + "' regions in transition");
  14. regions = ProcedureSyncWait.getRegionsFromMeta(env, getTableName());
  15. assert regions != null && !regions.isEmpty() : "unexpected 0 regions";
  16. ProcedureSyncWait.waitRegionInTransition(env, regions);
  17. // Call coprocessors
  18. preTruncate(env);
  19. setNextState(TruncateTableState.TRUNCATE_TABLE_REMOVE_FROM_META);
  20. break;
  21. case TRUNCATE_TABLE_REMOVE_FROM_META:
  22. hTableDescriptor = env.getMasterServices().getTableDescriptors().get(tableName);
  23. DeleteTableProcedure.deleteFromMeta(env, getTableName(), regions);
  24. DeleteTableProcedure.deleteAssignmentState(env, getTableName());
  25. setNextState(TruncateTableState.TRUNCATE_TABLE_CLEAR_FS_LAYOUT);
  26. break;
  27. case TRUNCATE_TABLE_CLEAR_FS_LAYOUT:
  28. DeleteTableProcedure.deleteFromFs(env, getTableName(), regions, true);
  29. if (!preserveSplits) {
  30. // if we are not preserving splits, generate a new single region
  31. regions = Arrays.asList(ModifyRegionUtils.createHRegionInfos(hTableDescriptor, null));
  32. } else {
  33. regions = recreateRegionInfo(regions);
  34. }
  35. setNextState(TruncateTableState.TRUNCATE_TABLE_CREATE_FS_LAYOUT);
  36. break;
  37. case TRUNCATE_TABLE_CREATE_FS_LAYOUT:
  38. regions = CreateTableProcedure.createFsLayout(env, hTableDescriptor, regions);
  39. CreateTableProcedure.updateTableDescCache(env, getTableName());
  40. setNextState(TruncateTableState.TRUNCATE_TABLE_ADD_TO_META);
  41. break;
  42. case TRUNCATE_TABLE_ADD_TO_META:
  43. regions = CreateTableProcedure.addTableToMeta(env, hTableDescriptor, regions);
  44. setNextState(TruncateTableState.TRUNCATE_TABLE_ASSIGN_REGIONS);
  45. break;
  46. case TRUNCATE_TABLE_ASSIGN_REGIONS:
  47. CreateTableProcedure.assignRegions(env, getTableName(), regions);
  48. setNextState(TruncateTableState.TRUNCATE_TABLE_POST_OPERATION);
  49. hTableDescriptor = null;
  50. regions = null;
  51. break;
  52. case TRUNCATE_TABLE_POST_OPERATION:
  53. postTruncate(env);
  54. LOG.debug("truncate '" + getTableName() + "' completed");
  55. return Flow.NO_MORE_STATE;
  56. default:
  57. throw new UnsupportedOperationException("unhandled state=" + state);
  58. }
  59. } catch (HBaseException|IOException e) {
  60. LOG.warn("Retriable error trying to truncate table=" + getTableName() + " state=" + state, e);
  61. }
  62. return Flow.HAS_MORE_STATE;
  63. }



http://blog.csdn.net/chenfenggang/article/details/78335970














阅读全文
0 0