# Devs 的 AMv2 描述

HBase Master 中的 AssignmentManager（AM）管理 RegionServers 集群上的区域分配。

AMv2 项目是 Assignment 的重做，旨在解决生产中许多操作问题的根本原因，即缓慢分配和有问题的会计，使得地区错位在臭名昭着的 _ 转型区域（ RIT）_ 肢体状态。

以下是关于 AMv2 关键方面的开发人员的注释，没有特别的顺序。

## 188.背景

HBase 1.x 中的分配在操作中存在问题。不难看出原因。区域状态保存在 ZooKeeper 中 RPC 的另一端（终端状态 - 即 OPEN 或 CLOSED - 发布到 _hbase：meta_ 表）。在 HBase-1.x.x 中，state 有多个编写器，Master 和 RegionServers 都能同时进行状态编辑（在 _hbase：meta_ 表中并在 ZooKeeper 上输出）。如果时钟错误或观察者错过，则可以跳过或覆盖状态更改。锁定 HBase 实体 - 表，区域 - 并不全面，因此表操作 - 禁用/启用 - 可能与区域级操作发生冲突;拆分或合并。区域状态是分布式的，难以推理和测试。分配操作很慢，因为每个分配都涉及通过转换移动远程 znode。群集大小往往超过几十万个区域;除此之外，集群启动/停止需要数小时，并且容易出现损坏。

AMv2（AssignmentManager 版本 2）是 hbase-1.x AssignmentManager 的重构（ [HBASE-14350](https://issues.apache.org/jira/browse/HBASE-14350) ），它基于 [ProcedureV2（HBASE-12439）](https://issues.apache.org/jira/browse/HBASE-12439)。 ProcedureV2（Pv2）_，_ 是一个笨拙命名的系统，允许描述和运行多步状态机。它具有高效性并且可以将所有状态保存到可以在崩溃后恢复的商店。有关 ProcedureV2 系统的更多信息，请参见[程序框架（Pv2）：](#pv2) [HBASE-12439](https://issues.apache.org/jira/browse/HBASE-12439) 的配套章节。

在 AMv2 中，所有赋值，崩溃处理，拆分和合并都重新编写为过程（v2）。 ZooKeeper 从混合中清除。和以前一样，最终的赋值状态被发布到 _hbase：meta_ ，非主参与者读取（所有客户端）中间状态保存在本地 Pv2 基于 WAL 的“商店”但只有活跃的主人一个单一的作家，演变国家。 Master 的内存中集群映像是权限，如果不一致，RegionServers 将被强制遵守。 Pv2 添加了所有核心 HBase 实体的共享/独占锁定 - 名称空间，表和区域 - 以确保一个进程一次访问并防止操作争用资源（移动/拆分，禁用/分配等）。

在一个有目的的高性能状态机的 AM 上面的重做，所有操作都采用具有单个状态写入器的通用过程表单，仅将我们的 AM 移动到新的弹性和规模级别。

## 189.新制度

区域的每个区域分配或取消分配现在都是一个过程。移动（区域）程序是程序的复合;它是运行 Unassign Procedure 然后是 Assign Procedure。移动过程产生系列中的分配和取消分配，然后等待它们的完成。

等等。 ServerCrashProcedure 生成 WAL 拆分任务，然后将作为子过程托管在崩溃服务器上的所有区域重新分配。

AMv2 过程由 Master 在 ProcedureExecutor 实例中运行。所有程序都使用 Pv2 框架提供的实用程序。

例如，Procedures 将每个状态转换持久保存到框架的 Procedure Store。默认实现是在 HDFS 上保留的 WAL。在崩溃时，我们重新打开 Store 并重新运行 Procedure 过程的所有 WAL，以使 Assignment State Machine 恢复到崩溃前的状态。然后我们继续执行程序。

在新系统中，Master 是所有事物分配的权威。以前我们很暧昧;例如 RegionServer 负责拆分业务。 Master 保留 Region 状态和服务器的内存映像。如果分歧，师父总是占上风;在极端情况下，它会杀死存在分歧的 RegionServer。

新的 RegionStateStore 类负责将终端 Region 状态（无论是 OPEN 还是 CLOSED）发布到 _hbase：meta _ 表 _ ._

RegionServers 现在在 Connection 上报告其运行版本。此版本在 AM 中可用，用于运行迁移滚动重新启动。

## 190.程序细节

### 190.1。指定/取消指定

分配和取消分配公共 RegionTransitionProcedure 的子类。由于 RTP 实例对区域进行锁定，因此每个区域一次只能运行一个 RegionTransitionProcedure。 RTP 基础程序有三个步骤;存储过程步骤（REGION_TRANSITION_QUEUE）;调度程序打开或关闭，然后暂停等待远程区域服务器报告成功打开或失败（REGION_TRANSITION_DISPATCH）或通知服务器发出请求崩溃;最后在 hbase：meta（REGION_TRANSITION_FINISH）中注册成功的打开/关闭。

以下是区域 56f985a727afe80a184dac75fbf6860c 在日志中的分配方式。分配是由服务器崩溃引起的（进程 ID 1176 或 pid = 1176，当它是过程的父级时，它被标识为 ppid = 1176）。 assign 是 pid = 1179，两者的第二个区域由此服务器崩溃分配。

```
2017-05-23 12:04:24,175 INFO  [ProcExecWrkr-30] procedure2.ProcedureExecutor: Initialized subprocedures=[{pid=1178, ppid=1176, state=RUNNABLE:REGION_TRANSITION_QUEUE; AssignProcedure table=IntegrationTestBigLinkedList, region=bfd57f0b72fd3ca77e9d3c5e3ae48d76, target=ve0540.halxg.example.org,16020,1495525111232}, {pid=1179, ppid=1176, state=RUNNABLE:REGION_TRANSITION_QUEUE; AssignProcedure table=IntegrationTestBigLinkedList, region=56f985a727afe80a184dac75fbf6860c, target=ve0540.halxg.example.org,16020,1495525111232}] 
```

接下来，我们通过使用框架排队（'注册'）过程来开始赋值。

```
2017-05-23 12:04:24,241 INFO  [ProcExecWrkr-30] assignment.AssignProcedure: Start pid=1179, ppid=1176, state=RUNNABLE:REGION_TRANSITION_QUEUE; AssignProcedure table=IntegrationTestBigLinkedList, region=56f985a727afe80a184dac75fbf6860c, target=ve0540.halxg.example.org,16020,1495525111232; rit=OFFLINE, location=ve0540.halxg.example.org,16020,1495525111232; forceNewPlan=false, retain=false 
```

通过跟踪其进程 ID 来跟踪日志中的过程运行 - 此处为 pid = 1179。

接下来，我们转到调度阶段，我们更新 hbase：meta 表，将区域状态设置为服务器 ve540 上的 OPENING。然后我们向 ve540 发送一个 rpc，要求它打开该区域。此后我们暂停分配，直到我们从 ve540 收到一条消息，告知它是否已成功打开该区域（或不成功）。

```
2017-05-23 12:04:24,494 INFO  [ProcExecWrkr-38] assignment.RegionStateStore: pid=1179 updating hbase:meta row=IntegrationTestBigLinkedList,H\xE3@\x8D\x964\x9D\xDF\x8F@9\x0F\xC8\xCC\xC2,1495566261066.56f985a727afe80a184dac75fbf6860c., regionState=OPENING, regionLocation=ve0540.halxg.example.org,16020,1495525111232
2017-05-23 12:04:24,498 INFO  [ProcExecWrkr-38] assignment.RegionTransitionProcedure: Dispatch pid=1179, ppid=1176, state=RUNNABLE:REGION_TRANSITION_DISPATCH; AssignProcedure table=IntegrationTestBigLinkedList, region=56f985a727afe80a184dac75fbf6860c, target=ve0540.halxg.example.org,16020,1495525111232; rit=OPENING, location=ve0540.halxg.example.org,16020,1495525111232 
```

下面我们记录该区域在 ve540 上成功打开的传入报告。程序被唤醒（您可以通过线程的名称，它的 ProcedureExecutor 线程，ProcExecWrkr-9 告诉它程序正在运行）。唤醒过程更新 hbase：meta 中的状态以表示该区域在 ve0540 上打开。然后报告完成和退出。

```
2017-05-23 12:04:26,643 DEBUG [RpcServer.default.FPBQ.Fifo.handler=46,queue=1,port=16000] assignment.RegionTransitionProcedure: Received report OPENED seqId=11984985, pid=1179, ppid=1176, state=RUNNABLE:REGION_TRANSITION_DISPATCH; AssignProcedure table=IntegrationTestBigLinkedList, region=56f985a727afe80a184dac75fbf6860c, target=ve0540.halxg.example.org,16020,1495525111232; rit=OPENING, location=ve0540.halxg.example.org,16020,1495525111232                                                                                                                                                                       2017-05-23 12:04:26,643 INFO  [ProcExecWrkr-9] assignment.RegionStateStore: pid=1179 updating hbase:meta row=IntegrationTestBigLinkedList,H\xE3@\x8D\x964\x9D\xDF\x8F@9\x0F\xC8\xCC\xC2,1495566261066.56f985a727afe80a184dac75fbf6860c., regionState=OPEN, openSeqNum=11984985, regionLocation=ve0540.halxg.example.org,16020,1495525111232
2017-05-23 12:04:26,836 INFO  [ProcExecWrkr-9] procedure2.ProcedureExecutor: Finish suprocedure pid=1179, ppid=1176, state=SUCCESS; AssignProcedure table=IntegrationTestBigLinkedList, region=56f985a727afe80a184dac75fbf6860c, target=ve0540.halxg.example.org,16020,1495525111232 
```

取消分配看起来类似，因为它基于 RegionTransitionProcedure。它具有相同的状态转换，并且基本上执行相同的步骤，但具有不同的状态名称（CLOSING，CLOSED）。

大多数其他过程是 Pv2 StateMachine 实现的子类。我们有 Table 和 Region 聚焦的 StateMachines 类型。

## 191.用户界面

沿着 Master 上的顶栏，您现在可以找到一个'Procedures＆amp; Locks'选项卡，它会将您带到一个丑陋但有用的页面。它转储当前正在运行的过程和框架锁。当你无法确定卡住的东西时，请看这个;它至少会识别有问题的程序（拿起 pid 并 grep 日志......）。寻找已经长时间运行的 ROLLEDBACK 或 pids。

## 192.记录

程序将他们的进程 id 记录为 pid =和他们的父 ID（ppid =）无处不在。工作已经完成，因此您可以 grep pid 并查看过程操作的历史记录。

## 193.实施说明

在本节中，我们注意到一些操作的特性，试图为您节省一些麻烦。

### 193.1。区域转换 RPC 和 RS 心跳可以在 Master 上同时到达

报告 RegionServer 上的区域转换现在是一个不同于 RS 心跳的 RPC（'RegionServerServices'服务）。心跳和状态更新可以在大约同一时间到达主服务器。 Master 将更新其 Region 的内部状态，但在心跳处理时会检查相同的状态。我们可能会发现意外;即一个刚刚报告为关闭的地区，因此心跳惊讶地发现 RS 报告背面的区域为 OPEN。在新系统中，所有奴隶都必须了解大师对群集状态的理解;主人将杀死/关闭任何未对齐的实体。

为了解决上述问题，我们为内存中的主状态添加了 lastUpdate。在我们采取行动之前，让一个地区的国家有一些年份（目前是一秒）。

### 193.2。 Master 作为 RegionServer 或 RegionServer 只执行系统表

AMv2 仅强制执行 HMaster 承载系统表的当前主分支默认值;即，HBase 集群中的 Master 也作为 RegionServer，它只是 _hbase：meta_ ， _hbase：namespace_ 等表的独占主机，核心系统表。这导致了一些测试失败，因为 AMv1，虽然它不应该，允许移动 hbase：meta 关闭 Master 而 AMv2 没有。

## 194.新配置

当你改变它们时，这些配置都需要 doc。

### 194.1。 hbase.procedure.remote.dispatcher.threadpool.size

默认值为 128

### 194.2。 hbase.procedure.remote.dispatcher.delay.msec

默认 150 毫秒

### 194.3。 hbase.procedure.remote.dispatcher.max.queue.size

默认 32

### 194.4。 hbase.regionserver.rpc.startup.waittime

默认为 60 秒。

## 195.工具

HBASE-15592 打印程序 WAL 内容

[HBASE-18152](https://issues.apache.org/jira/browse/HBASE-18152) [AMv2]损坏程序 WAL 文件中的补丁;无序存储的程序数据 [https://issues.apache.org/jira/secure/attachment/12871066/reading_bad_wal.patch](https://issues.apache.org/jira/secure/attachment/12871066/reading_bad_wal.patch)

### 195.1。 MasterProcedureSchedulerPerformanceEvaluation

用于在过程调度程序中独立于其他框架组件测试锁和队列的性能的工具。在 proc 系统进行任何实质性更改后运行此命令。打印好的输出：

```
******************************************
Time - addBack     : 5.0600sec
Ops/sec - addBack  : 1.9M
Time - poll        : 19.4590sec
Ops/sec - poll     : 501.9K
Num Operations     : 10000000

Completed          : 10000006
Yield              : 22025876

Num Tables         : 5
Regions per table  : 10
Operations type    : both
Threads            : 10
******************************************
Raw format for scripts

RESULT [num_ops=10000000, ops_type=both, num_table=5, regions_per_table=10, threads=10, num_yield=22025876, time_addback_ms=5060, time_poll_ms=19459] 
```