hbase教程

这里写自定义目录标题

欢迎使用Markdown编辑器

HBase 教程

HBase 概述

HBase是Hadoop的生态系统,是建立在Hadoop文件系统(HDFS)之上的分布式、面向列的数据库,通过利用Hadoop的文件系统提供容错能力。如果你需要进行实时读写或者随机访问大规模的数据集的时候,请考虑使用HBase!

HBase作为Google Bigtable的开源实现,Google Bigtable利用GFS作为其文件存储系统类似,则HBase利用Hadoop HDFS作为其文件存储系统;Google通过运行MapReduce来处理Bigtable中的海量数据,同样,HBase利用Hadoop MapReduce来处理HBase中的海量数据;Google Bigtable利用Chubby作为协同服务,HBase利用Zookeeper作为对应。

//img.mukewang.com/wiki/5bf4fed109ca49aa03710213.jpg

HBase处理数据

虽然Hadoop是一个高容错、高延时的分布式文件系统和高并发的批处理系统,但是它不适用于提供实时计算;HBase是可以提供实时计算的分布式数据库,数据被保存在HDFS分布式文件系统上,由HDFS保证期高容错性,但是再生产环境中,HBase是如何基于hadoop提供实时性呢? HBase上的数据是以StoreFile(HFile)二进制流的形式存储在HDFS上block块儿中;但是HDFS并不知道的HBase用于存储什么,它只把存储文件认为是二进制文件,也就是说,HBase的存储数据对于HDFS文件系统是透明的。

HBase与HDFS

在下面的表格中,我们对HDFS与HBase进行比较:

HDFSHBase
HDFS适于存储大容量文件的分布式文件系统。HBase是建立在HDFS之上的数据库。
HDFS不支持快速单独记录查找。HBase提供在较大的表快速查找
HDFS提供了高延迟批量处理;没有批处理概念。HBase提供了数十亿条记录低延迟访问单个行记录(随机存取)。
HDFS提供的数据只能顺序访问。HBase内部使用哈希表和提供随机接入,并且其存储索引,可将在HDFS文件中的数据进行快速查找。

HBase 数据模型

HBase通过表格的模式存储数据,每个表格由列和行组成,其中,每个列又被划分为若干个列族(row family),请参考下面的图:

//img.mukewang.com/wiki/5bf4ffa409a96dfa05030324.jpg

现在我们来看看HBase的逻辑数据模型与物理数据模型(实际存储的数据模型):

逻辑数据模型

//img.mukewang.com/wiki/5bf5001709476ac505040205.jpg

物理数据模型

//img.mukewang.com/wiki/5bf5004609cc843604380393.jpg

HBase 架构

下图显示了HBase的组成结构:

//img.mukewang.com/wiki/5bf5005d098493a304880267.jpg

通过上图我们可以得出Hbase中的每张表都按照一定的范围被分割成多个子表(HRegion),默认一个HRegion超过 256M 就要被分割成两个,由 HRegionServer管理,管理哪些HRegion由HMaster分配。 

现在我们来介绍一下HBase中的一些组成部件以及它们起到的作用:

  • Client:包含访问HBase的接口,并维护cache来加快对HBase的访问。- Zookeeper:HBase依赖Zookeeper,默认情况下HBase管理Zookeeper实例(启动或关闭Zookeeper),Master与RegionServers启动时会向Zookeeper注册。Zookeeper的作用如下:
    • - 保证任何时候,集群中只有一个master
      Zookeeper:HBase依赖Zookeeper,默认情况下HBase管理Zookeeper实例(启动或关闭Zookeeper),Master与RegionServers启动时会向Zookeeper注册。Zookeeper的作用如下:
  • 存储所有Region的寻址入口- 实时监控Region server的上线和下线信息。并实时通知给master- 存储HBase的schema和table元数据
    HRegionServer:用来维护master分配给他的region,处理对这些region的io请求;负责切分正在运行过程中变的过大的region。

HRegion:HBase表在行的方向上分隔为多个Region。Region是HBase中分布式存储和负载均衡的最小单元,即不同的region可以分别在不同的Region Server上,但同一个Region是不会拆分到多个server上。Region按大小分隔,每个表一般是只有一个region,当region的某个列族达到一个阈值(默认256M)时就会分成两个新的region。

Store:每一个Region由一个或多个Store组成,至少是一个Store,HBase会把一起访问的数据放在一个Store里面,即为每个ColumnFamily建一个Store,如果有几个ColumnFamily,也就有几个Store。一个Store由一个memStore和0或者多个StoreFile组成。Store的大小被HBase用来判断是否需要切分Region。

StoreFile:memStore内存中的数据写到文件后就是StoreFile,StoreFile底层是以HFile的格式保存。 

HLog:HLog记录数据的所有变更,可以用来恢复文件,一旦region server 宕机,就可以从log中进行恢复。

LogFlusher:一个LogFlusher的类是用来调用HLog.optionalSync()的。

HRegionServer:用来维护master分配给他的region,处理对这些region的io请求;负责切分正在运行过程中变的过大的region。

HRegion:HBase表在行的方向上分隔为多个Region。Region是HBase中分布式存储和负载均衡的最小单元,即不同的region可以分别在不同的Region Server上,但同一个Region是不会拆分到多个server上。Region按大小分隔,每个表一般是只有一个region,当region的某个列族达到一个阈值(默认256M)时就会分成两个新的region。

Store:每一个Region由一个或多个Store组成,至少是一个Store,HBase会把一起访问的数据放在一个Store里面,即为每个ColumnFamily建一个Store,如果有几个ColumnFamily,也就有几个Store。一个Store由一个memStore和0或者多个StoreFile组成。Store的大小被HBase用来判断是否需要切分Region。

StoreFile:memStore内存中的数据写到文件后就是StoreFile,StoreFile底层是以HFile的格式保存。 

HLog:HLog记录数据的所有变更,可以用来恢复文件,一旦region server 宕机,就可以从log中进行恢复。

LogFlusher:一个LogFlusher的类是用来调用HLog.optionalSync()的。

HBase 的应用

  • HBase是用来当有需要写重的应用程序。- HBase可以帮助快速随机访问数据。- HBase被许多公司所采纳,例如,Facebook、Twitter、Yahoo!、Adobe、OpenPlaces、WorldLingo等等。
    HBase可以帮助快速随机访问数据。

HBase 快速启动

HBase 入门——独立式HBase

在本节中,你将首先学习单节点、独立的HBase的设置,并且学会运行单节点、独立的HBase实例!

在一个独立的HBase实例中,它具有所有的HBase系统服务程序:Master、RegionServers 和 ZooKeeper(在一个持续到本地文件系统的单一 JVM 中运行)。这是我们最基本的部署配置文件。我们将向您展示如何使用 HBase shell CLI 在 HBase 中创建表,在表中插入行,对表执行放置和扫描操作,启用或禁用表,以及启动和停止 HBase。除了下载 HBase,只要10分钟就可以完成以下的操作。

注意:在HBase 0.94.x之前,HBase预计环回IP地址为127.0.0.1。Ubuntu和其他一些发行版默认为127.0.1.1,这会给你带来问题。

以下/etc/hosts文件可以在Ubuntu的HBase 0.94.x及更早版本上正确运行。如果遇到麻烦,请将其作为模板使用。

127.0.0.1 localhost 
ubuntu.ubuntu-domain Ubuntu下的127.0.0.1

这个问题已经在hbase-0.96.0及更高版本中得到修复。

JDK版本要求

HBase要求安装JDK

HBase下载与启动

选择一个Apache 下载镜像,下载 HBase Releases。点击stable目录,然后下载后缀为.tar.gz的二进制文件到你的到本地文件系统;例如 hbase-0.95-SNAPSHOT.tar.gz。

解压下载的文件,然后进入到那个要解压的目录。

$ tar xfz hbase-0.95-SNAPSHOT.tar.gz 
$ cd hbase-0.95-SNAPSHOT

在你启动HBase之前,需要先设置 JAVA_HOME 环境变量。您可以通过操作系统的常规机制来设置变量,但HBase提供了一个中心机制 conf/hbase-env.sh,编辑此文件,取消注释以下行JAVA_HOME,并将其设置为您的操作系统的适当位置,JAVA_HOME 变量应设置为包含可执行文件 bin/JAVA 的目录。大多数现代 Linux 操作系统都提供了一种机制,例如在 RHEL 或 CentOS 上的替代方法,用于在 Java 等可执行版本之间进行透明切换。在这种情况下,您可以将 JAVA_HOME 设置为包含指向 bin/JAVA 的符号链接的目录,这通常是:/usr。

JAVA_HOME=/usr

编辑conf/hbase-site.xml,这是HBase的主要配置文件。此时,您只需要在HBase和ZooKeeper写入数据的本地文件系统上指定目录即可。默认情况下,在/tmp下创建一个新目录。许多服务器被配置为在重启时删除/tmp的内容,所以你应该在其他地方存储数据。以下配置将把HBase的数据存储在hbase目录下的testuser用户主目录中。将<property>标签粘贴到标签下<configuration>,在新的HBase安装中应该是空的。

独立HBase的hbase-site.xml:

<configuration>
   <property>     
   <name>hbase.rootdir</name>     
   <value>file:///home/testuser/hbase</value>   
   </property>   
   <property>     
   <name>hbase.zookeeper.property.dataDir</name>     
   <value>/home/testuser/zookeeper</value>   
   </property> 
 </configuration>

您不需要创建HBase数据目录,HBase会为你做这个。

注意:上述示例中的hbase.rootdir指向本地文件系统中的一个目录。'file:/'前缀是我们如何表示本地文件系统。要在现有的HDFS实例上安装HBase,请将hbase.rootdir设置为指向您实例上的目录:例如,hdfs://namenode.example.org:8020/hbase。有关更多信息,请参见下面关于独立 HBase HDFS 的部分。

提供了bin/start-hbase.sh脚本来方便的启动HBase。发出命令,如果一切正常,则会将消息记录到标准输出,显示HBase已成功启动。您可以使用该jps命令来验证您是否有一个名为 HMaster 的正在运行的进程。在独立模式下,HBase在单个JVM中运行所有守护进程,即HMaster,单个HRegionServer和ZooKeeper守护进程。

为此,打开HBase主文件夹,然后运行HBase启动脚本,如下所示:

$cd /usr/local/HBase/bin 
$./start-hbase.sh

如果一切顺利,当运行HBase启动脚本,它会提示一条消息:HBase已经启动

starting master, logging to /usr/local/HBase/bin/../logs/hbase-tpmaster-
localhost.localdomain.out

提示:Java需要安装并可用。如果您得到一个错误,指示Java未安装,但它位于您的系统上(可能位于非标准位置),请编辑conf/hbase-env.sh文件,并将该JAVA_HOME设置修改为指向包含在你的系统上的bin/Java。

shell练习——首次使用HBase

1、连接到HBase。使用HBase shell命令连接到您的 HBase 运行实例,位于HBase安装的bin/目录中。在本例中,省略了启动HBase Shell时打印的一些用法和版本信息。

$ ./bin/hbase shell 
hbase(main):001:0>

2、显示HBase Shell帮助文本。键入“help”并按“Enter”,以显示HBase Shell的一些基本用法信息以及几个示例命令。请注意,表名、行、列都必须用引号字符括起来。

3、创建一个表。使用该“create”命令来创建一个新的表。您必须指定表名称和ColumnFamily名称。

hbase(main):001:0> create 'test', 'cf' 
0 row(s) in 0.4170 seconds 
 
=> Hbase::Table - test

4、列出关于您的表的信息,通过使用“list”命令来实现:

hbase(main):002:0> list 'test' 
TABLE 
test 
1 row(s) in 0.0180 seconds 
 
=> ["test"]

5、把数据放到你的表中。要将数据放入表中,请使用该“put”命令。

hbase(main):003:0> put 'test', 'row1', 'cf:a', 'value1' 
0 row(s) in 0.0850 seconds 
 
hbase(main):004:0> put 'test', 'row2', 'cf:b', 'value2' 
0 row(s) in 0.0110 seconds 
 
hbase(main):005:0> put 'test', 'row3', 'cf:c', 'value3'  
0 row(s) in 0.0100 seconds

在这里,我们插入三个值,一次一个。第一个插入是在row1,列cf:a,值为value1。HBase 中的列由列族前缀组成,在此示例中为cf,后跟一个冒号,然后是一个列限定符后缀(在本例中为 a)。

6、一次扫描表中的所有数据。从HBase获取数据的方法之一是扫描。使用该“scan”命令扫描表中的数据。你可以限制你的扫描,但现在,所有的数据都被提取。

hbase(main):006:0> scan 'test' 
ROW                                      COLUMN+CELL  
row1                                    column=cf:a, timestamp=1421762485768, 
value=value1  
row2                                    column=cf:b, timestamp=1421762491785, 
value=value2  
row3                                    column=cf:c, timestamp=1421762496210, 
value=value3 
3 row(s) in 0.0230 seconds

7、获取一行的数据。要一次获取一行数据,请使用该“get”命令。

hbase(main):007:0> get 'test', 'row1' 
COLUMN                                   CELL  
cf:a                                    timestamp=1421762485768, value=value1 
1 row(s) in 0.0350 seconds

8、禁用表格。如果您想删除表格或更改其设置以及其他一些情况,则需要先使用“disable”命令禁用表格。您可以使用该“enable”命令重新启用它。

hbase(main):008:0> disable 'test' 
0 row(s) in 1.1820 seconds 
 
hbase(main):009:0> enable 'test'  
0 row(s) in 0.1770 seconds

如果您测试了上面的“enable”命令,请再次禁用表格:

hbase(main):010:0> disable 'test' 
0 row(s) in 1.1820 seconds

9、删除表。要删除表,请使用该“drop”命令。

hbase(main):011:0> drop 'test' 
0 row(s) in 0.1370 seconds

10、退出 HBase Shell。要退出HBase Shell并断开与群集的连接,请使用该“quit”命令。HBase仍然在后台运行。

停止HBase

1、与提供bin / start-hbase.sh脚本以便方便地启动所有HBase守护进程相同,你可以使用bin/stop-hbase.sh脚本停止它们。

$ ./bin/stop-hbase.sh 
stopping hbase.................... 
$

2、发出命令后,进程关闭可能需要几分钟的时间。使用jps要确保HMASTER和HRegionServer进程被关闭。

以上向您展示了如何启动和停止一个独立的HBase实例。在接下来的部分中,我们将简要介绍一下HBase部署的其他模式。

在伪分布式模式安装HBase

在通过快速启动HBase的独立模式工作之后,您可以重新配置HBase以伪分布式模式运行。伪分布模式意味着HBase仍然在单个主机上完全运行,但是每个HBase守护进程(HMaster,HRegionServer和ZooKeeper)作为一个单独的进程运行:在独立模式下,所有守护进程都运行在一个jvm进程/实例中。默认情况下,除非按照快速启动HBase的独立模式中所述配置hbase.rootdir属性,否则您的数据仍存储在/tmp/中。在本演练中,我们将数据存储在HDFS中,假设您有HDFS可用。您可以跳过HDFS配置,继续将数据存储在本地文件系统中。

**Hadoop配置 **

此过程假定您已在本地系统或远程系统上配置Hadoop和HDFS,并且它们正在运行且可用。它还假定您正在使用Hadoop 2。

1、请停止HBase,如果它正在运行。如果刚刚完成快速启动HBase的独立模式并且HBase仍在运行,请停止它。这个过程将创建一个全新的目录,HBase将存储它的数据,所以你之前创建的任何数据库都将丢失。

2、配置HBase。编辑hbase-site.xml配置。首先,添加以下指示HBase以分布式模式运行的属性,每个守护进程有一个JVM实例。

<property>
   <name>hbase.cluster.distributed</name>   
   <value>true</value>  
</property>

接下来,将 hbase rootdir 从本地文件系统更改为您的 HDFS 实例的地址,使用 HDFS:或 URI 语法。在这个例子中,HDFS在端口8020的本地主机上运行。

<property>
   <name>hbase.rootdir</name>   
   <value>hdfs://localhost:8020/hbase</value>  
</property>

您不需要在HDFS中创建目录。HBase会为你做这个。如果你创建了这个目录,HBase会试图做一个迁移,这不是你想要的。

3、启动 HBase。使用bin/start-hbase.sh命令启动HBase。如果您的系统配置正确,该jps命令应显示HMaster和HRegionServer进程正在运行。

4、检查HDFS中的HBase目录。如果一切正常,HBase在HDFS中创建它的目录。在上面的配置中,它存储在HDFS上的/hbase/中。您可以使用 hadoop 的 bin/目录中的 hadoop fs 命令来列出此目录。

$ ./bin/hadoop fs -ls /hbase 
Found 7 items 
drwxr-xr-x   - hbase users          0 2014-06-25 18:58 /hbase/.tmp 
drwxr-xr-x   - hbase users          0 2014-06-25 21:49 /hbase/WALs 
drwxr-xr-x   - hbase users          0 2014-06-25 18:48 /hbase/corrupt 
drwxr-xr-x   - hbase users          0 2014-06-25 18:58 /hbase/data 
-rw-r--r--   3 hbase users         42 2014-06-25 18:41 /hbase/hbase.id 
-rw-r--r--   3 hbase users          7 2014-06-25 18:41 /hbase/hbase.version 
drwxr-xr-x   - hbase users          0 2014-06-25 21:49 /hbase/oldWALs

5、创建一个表并使用数据填充它。您可以使用HBase Shell创建一个表,使用数据填充它,使用与shell练习中相同的步骤扫描并从中获取值。

6、启动和停止备份HBase主(HMaster)服务器。

注意:在同一个硬件上运行多个HMaster实例在生产环境中是没有意义的,就像运行伪分布式集群对于生产没有意义一样。此步骤仅供测试和学习之用。

HMaster服务器控制HBase集群。你可以启动最多9个备份HMaster服务器,这个服务器总共有10个HMaster计算主服务器。要启动备份HMaster,请使用local-master-backup.sh。对于要启动的每个备份主节点,请添加一个表示该主节点的端口偏移量的参数。每个HMaster使用三个端口(默认情况下为16010,16020和16030)。端口偏移量被添加到这些端口,因此使用偏移量2,备份HMaster将使用端口16012,16022和16032。以下命令使用端口:16012/16022/16032,16013/16023/16033和16015/16025/16035启动3个备份服务器。

$ ./bin/local-master-backup.sh 2 3 5

要在不杀死整个群集的情况下杀死备份主机,则需要查找其进程ID(PID)。PID存储在一个名为/tmp/hbase-USER-X-master.pid的文件中。该文件的唯一内容是PID。您可以使用该kill -9命令来杀死该PID。以下命令将终止具有端口偏移1的主服务器,但保持群集正在运行:

$ cat /tmp/hbase-testuser-1-master.pid |xargs kill -9

7、启动和停止其他RegionServers。HRegionServer按照HMaster的指示管理StoreFiles中的数据。通常,一个HRegionServer在集群中的每个节点上运行。在同一个系统上运行多个HRegionServers对于伪分布式模式下的测试非常有用。该local-regionservers.sh命令允许您运行多个RegionServer。它以类似的local-master-backup.sh命令的方式工作,因为您提供的每个参数都代表实例的端口偏移量。每个RegionServer需要两个端口,默认端口是16020和16030。但是,由于HMaster使用默认端口,所以其他RegionServers的基本端口不是默认端口,而HMaster自从HBase版本1.0.0以来也是RegionServer。基本端口是16200和16300。您可以在服务器上运行另外99个不是HMaster或备份HMaster的RegionServer。以下命令将启动另外四个RegionServers,它们在从16202/16302(基本端口16200/16300加2)开始的顺序端口上运行。

$ .bin/local-regionservers.sh start 2 3 4 5		

要手动停止RegionServer,请使用带有stop参数和服务器偏移量的local-regionservers.sh命令停止。

$ .bin/local-regionservers.sh stop 3

8、停止HBase。您可以使用bin/stop-hbase.sh命令以与快速启动独立式HBase过程相同的方式停止HBase 。

在完全分布式模式测试HBase

实际上,您需要一个完全分布式的配置来全面测试HBase,并将其用于实际场景中。在分布式配置中,集群包含多个节点,每个节点运行一个或多个HBase守护进程。这些包括主要和备份主实例,多个ZooKeeper节点和多个RegionServer节点。

此高级快速入门将两个以上的节点添加到您的群集。架构如下:

节点名称MasterZooKeeperRegionServer
node-a.example.com没有
node-b.example.com备用
node-c.example.com没有

这个快速入门假定每个节点都是虚拟机,并且它们都在同一个网络上。它基于之前的快速入门、伪分布式本地安装,假设您在该过程中配置的系统是现在node-a。继续之前,在node-a停止HBase 。

提示:请确保所有节点都具有完全的通信访问权限,并且没有任何防火墙规则可以阻止它们相互交谈。如果您看到任何错误,如no route to host,请检查您的防火墙。

配置无密码SSH访问

node-a需要能够登录node-b和node-c(和自己)才能启动守护进程。实现这一点的最简单的方法是在所有主机上使用相同的用户名,并配置无密码的SSH登录,从node-a到其他的。

1、在node-a,生成一个密钥对。以运行HBase的用户身份登录时,使用以下命令生成SSH密钥对:

$ ssh-keygen -t rsa

如果命令成功,密钥对的位置将打印到标准输出。公钥的默认名称是id_rsa.pub。

2、创建将在其他节点上保存的共享密钥的目录。在node-b和上node-c,以HBase用户身份登录,并在用户主目录中创建一个.ssh/目录(如果尚不存在)。如果它已经存在,请注意它可能已经包含其他键。

3、将公钥复制到其他节点。通过使用scp或其他一些安全的手段,安全地将公钥从node-a复制到每个节点。在其他每个节点上,创建一个名为.ssh/authorized_keys的新文件(如果该文件尚不存在),并将id_rsa.pub文件的内容附加到该文件的末尾。请注意,你也需要为node-a本身执行此项。

$ cat id_rsa.pub >> ~/.ssh/authorized_keys

4、测试无密码登录。如果您正确执行了此过程,则node-a在使用相同用户名从其他任一节点进行SSH连接时,不应提示您输入密码。

5、由于node-b将运行备份主机,请重复上述过程,在你看到node-a的任何地方替换node-b。请确保不要覆盖现有的.ssh / authorized_keys文件,而是使用>>运算符,而不是>运算符将新密钥连接到现有文件。

准备 node-a

node-a将运行您的主要主服务器和ZooKeeper进程,但不运行RegionServers。从node-a停止启动RegionServer。

1、编辑conf/regionservers并删除包含localhost的行。为node-b和node-c加入具有主机名或IP地址线。即使你想在node-a运行一个RegionServer,你也应该用其他服务器用来与之通信的主机名来引用它。在这种情况下,那将是node-a.example.com。这使您可以将配置分发给群集中的每个节点,而不会造成任何主机名冲突。保存文件。

2、配置HBase以将node-b作为备份主机。在conf/调用backup-masters中创建一个新文件,并添加一个新的行,其中的主机名为node-b。在这个演示中,主机名是node-b.example.com。

3、配置ZooKeeper。实际上,你应该仔细考虑你的ZooKeeper配置。您可以在zookeeper部分找到更多关于配置ZooKeeper的信息。这个配置将指示HBase在集群的每个节点上启动和管理一个ZooKeeper实例。在node-a上,编辑conf/hbase-site.xml并添加下列属性。

<property>
   <name>hbase.zookeeper.quorum</name>   
   <value>node-a.example.com,node-b.example.com,node-c.example.com</value> 
</property> 
<property>
   <name>hbase.zookeeper.property.dataDir</name>   
   <value>/usr/local/zookeeper</value> 
</property>

4、在您的配置中,您已经将node-a作为localhost引用,将引用改为指向其他节点用来引用node-a的主机名。在这些例子中,主机名是node-a.example.com。

准备 node-b 和 node-c

node-b 将运行一个备份主服务器和一个ZooKeeper实例。

1、下载并解压HBase。将HBase下载并解压到node-b,就像您为独立和伪分布式快速入门所操作的一样。

2、将配置文件从node-a复制到node-b和node-c。您的群集的每个节点都需要具有相同的配置信息。将conf /目录下的内容复制到node-b和node-c上的conf/目录中。

启动并测试群集

1、确保HBase没有在任何节点上运行。如果您在之前的测试中忘记停止HBase,您将会遇到错误。通过使用该jps命令检查HBase是否在任何节点上运行。寻找HMaster,HRegionServer和HQuorumPeer的进程。如果他们存在,删除他们。

2、启动群集。在node-a,发出start-hbase.sh命令。您的输出将类似于下面的输出。

$ bin/start-hbase.sh 
node-c.example.com: starting zookeeper, logging to /home/hbuser/hbase-0.98.3-
hadoop2/bin/../logs/hbase-hbuser-zookeeper-node-c.example.com.out 
node-a.example.com: starting zookeeper, logging to /home/hbuser/hbase-0.98.3-
hadoop2/bin/../logs/hbase-hbuser-zookeeper-node-a.example.com.out 
node-b.example.com: starting zookeeper, logging to /home/hbuser/hbase-0.98.3-
hadoop2/bin/../logs/hbase-hbuser-zookeeper-node-b.example.com.out 
starting master, logging to /home/hbuser/hbase-0.98.3-hadoop2/bin/../logs/hbase-
hbuser-master-node-a.example.com.out 
node-c.example.com: starting regionserver, logging to /home/hbuser/hbase-0.98.3-
hadoop2/bin/../logs/hbase-hbuser-regionserver-node-c.example.com.out 
node-b.example.com: starting regionserver, logging to /home/hbuser/hbase-0.98.3-
hadoop2/bin/../logs/hbase-hbuser-regionserver-node-b.example.com.out  
node-b.example.com: starting master, logging to /home/hbuser/hbase-0.98.3-
hadoop2/bin/../logs/hbase-hbuser-master-nodeb.example.com.out

ZooKeeper首先启动,然后是master,然后是RegionServers,最后是backup masters。

3、验证进程是否正在运行。在群集的每个节点上,运行该jps命令并验证每台服务器上是否运行了正确的进程。如果用于其他用途,您可能会看到在您的服务器上运行的其他Java进程。

例子:node-a jps输出:

$ jps 
20355 Jps 
20071 HQuorumPeer  
20137 HMaster

示例:node-b jps输出:

$ jps 
15930 HRegionServer 
16194 Jps 
15838 HQuorumPeer  
16010 HMaster

例子:node-c jps输出:

$ jps 
13901 Jps 
13639 HQuorumPeer  
13737 HRegionServer

ZooKeeper进程名称这个HQuorumPeer过程是一个由HBase控制和启动的ZooKeeper实例。如果以这种方式使用ZooKeeper,则每个群集节点仅限于一个实例,并且仅适用于测试。如果ZooKeeper在HBase之外运行,则调用该进程QuorumPeer。

4、浏览到Web UI。Web UI端口更改Web UI端口更改在 HBase 更新的0.98.x 中,HBase Web UI使用的HTTP端口从主服务器的60010和每个RegionServer的60030变为主服务器的16010和RegionServer的16030。如果一切设置正确,您应该能够使用Web浏览器连接到Master(http://node-a.example.com:16010/)或Secondary Master的UI(http://node-b.example.com:16010/)。如果您可以通过localhost而不是从另一台主机连接,请检查您的防火墙规则。您可以在端口16030的IP地址中查看每个RegionServers的Web UI,也可以通过单击Master的Web UI中的链接来查看。

5、测试节点或服务消失时会发生什么。在配置了三节点群集后,事情不会很有弹性。您仍然可以通过关闭进程并查看日志来测试主Master或RegionServer的行为。


Apache HBase配置文件

本节是本章内容的开篇,我们首先来认识Apache HBase中有哪些需要的配置文件!

Apache HBase使用与Apache Hadoop相同的配置系统。所有配置文件都位于conf/目录中,需要保持群集中每个节点的同步。

HBase配置文件说明

  • backup-masters

    默认情况下不存在。这是一个纯文本文件,其中列出了主服务器应在其上启动备份主进程的主机,每行一台主机。

  • hadoop-metrics2-hbase.properties

    用于连接HBase Hadoop的Metrics2框架。有关Metrics2的更多信息,请参阅Hadoop Wiki条目。默认情况下只包含注释出的示例。

  • hbase-env.cmd 和 hbase-env.sh

    用于Windows和Linux/Unix环境的脚本,以设置HBase的工作环境,包括Java、Java选项和其他环境变量的位置。该文件包含许多注释示例来提供指导。

  • hbase-policy.xml

    RPC服务器使用默认策略配置文件对客户端请求进行授权决策。仅在启用HBase安全性的情况下使用。

  • hbase-site.xml

    主要的HBase配置文件。该文件指定覆盖HBase的默认配置的配置选项。您可以在docs/hbase-default.xml中查看(但不要编辑)默认配置文件。您还可以在HBase Web UI的HBase配置选项卡中查看群集的整个有效配置(默认和覆盖)。

  • log4j.properties

    通过log4j进行HBase日志记录的配置文件。

  • regionservers

    包含应该在HBase集群中运行RegionServer的主机列表的纯文本文件。默认情况下,这个文件包含单个条目localhost。它应该包含主机名或IP地址列表,每行一个,如果集群中的每个节点将在其localhost接口上运行RegionServer的话,则只应包含localhost。
    默认情况下不存在。这是一个纯文本文件,其中列出了主服务器应在其上启动备份主进程的主机,每行一台主机。

检查XML有效性

在编辑XML时,最好使用支持XML的编辑器,以确保您的语法正确且XML格式良好。您还可以使用该xmllint实用程序检查您的XML格式是否正确。默认情况下,xmllint重新流动并将XML打印到标准输出。要检查格式是否正确,并且只在存在错误时才打印输出,请使用命令xmllint -noout filename.xml。

在群集之间保持同步配置

当在分布式模式下运行时, 在对HBase配置进行编辑后,请确保将conf/目录的内容复制到群集的所有节点。HBase不会为你这么做的。请使用 rsync、scp 或其他安全机制将配置文件复制到你的节点。对于大多数配置, 服务器需要重新启动才能成功更改。动态配置是这方面的一个例外,在之后的内容将对此进行说明。


HBase 基础条件

在本节中,我们列出了使用HBase时所需要的服务和一些必需的系统配置。

安装Java

Java是Hadoop和HBase主要先决条件。首先应该使用"java -verion"检查java是否存在在您的系统上。 java -version 命令的语法如下。

$ java -version

如果一切正常,它会得到下面的输出。

java version "1.7.0_71" 
Java(TM) SE Runtime Environment (build 1.7.0_71-b13) 
Java HotSpot(TM) Client VM (build 25.0-b02, mixed mode)

如果Java还没有安装在系统中,请你安装Java!

HBase版本与JDK

在下表中你可以看到HBase版本与其对应支持的JDK版本:

HBase版本JDK 7JDK 8
2.0不支持支持
1.3支持支持
1.2支持支持
1.1支持使用JDK 8运行将会正常工作,但是没有得到很好的测试

注意:HBase不会使用Java 6构建或编译,并且,您必须在群集的每个节点上设置JAVA_HOME,hbase-env.sh 提供了一个方便的机制来做到这一点。

操作系统

SSH

(必须的)HBase广泛使用安全Shell(ssh)命令和实用程序在集群节点之间进行通信。集群中的每台服务器都必须运行ssh,以便可以管理Hadoop和HBase后台进程。您必须能够使用共享密钥而不是密码,通过SSH(包括本地节点)从主服务器和任何备份主服务器连接到所有节点。您可以在Linux或Unix系统中的“Procedure:Configure Passwordless SSH Access ”(配置无密码SSH访问)中看到这种设置的基本方法。如果群集节点使用OS X,请参阅Hadoop wiki上的,SSH:设置远程桌面和启用自登录

DNS

HBase使用本地主机名来自行报告其IP地址。正向和反向DNS解析必须在0.92.0之前的HBase版本中工作。hadoop-dns-checker 工具,可以用来验证DNS在集群上是否正常工作。项目README文件提供了有关使用的详细说明。

Loopback IP

在hbase-0.96.0之前,HBase只使用IP地址127.0.0.1来引用localhost,而这是不可配置的。有关更多详细信息,请参阅Loopback IP。

NTP

群集节点上的时钟应该同步。少量的变化是可以接受的,但是大量的不同会导致不稳定和意外的行为。如果在群集中看到无法解释的问题,则时间同步是首先要检查的事项之一。建议您在群集上运行网络时间协议(NTP)服务或其他时间同步机制,并且所有节点都查找相同的服务以进行时间同步。请参阅Linux文档项目(TLDP)中的基本NTP配置以设置NTP。

文件和进程数限制(ulimit)

Apache HBase是一个数据库。它需要能够一次打开大量的文件。许多Linux发行版限制了允许单个用户打开的文件数量1024(或者256,在旧版本的OS X上)。当以运行 HBase 的用户身份登录时,您可以通过在服务器上运行ulimit -n命令来检查服务器上的限制。您也可能会注意到以下错误:

2010-04-06 03:04:37,542信息org.apache.hadoop.hdfs.DFSClient:异常``increateBlockOutputStream java.io.EOFException ``2010-04-06 03:04:37,542 INFO org.apache.hadoop.hdfs.DFSClient:放弃块``blk_-6935524980745310745_1391901

建议将ulimit提高到至少10,000,但更可能是10,240,因为该值通常以1024的倍数表示。每个ColumnFamily至少有一个StoreFile,如果该区域处于加载状态,则可能有多于六个的StoreFile。所需的打开文件的数量取决于ColumnFamilies的数量和区域的数量。以下是计算RegionServer上打开的文件的潜在数量的粗略公式。

计算打开文件的潜在数量:

(每个ColumnFamily的StoreFiles)x(每个RegionServer的区域)

例如,假设一个模式的每个区域有3个ColumnFamilies,每个ColumnFamily平均有3个StoreFiles,每个RegionServer有100个区域,则JVM将打开3 * 3 * 100 = 900文件描述符,不包括打开的JAR文件、配置文件等等。打开一个文件不需要很多资源,而且允许用户打开太多文件的风险很小。

另一个相关设置是允许用户同时运行的进程数量。在Linux和Unix中,使用该ulimit -u命令设置进程的数量。这不应与nproc命令混淆,该命令控制给定用户可用的CPU数量。在负载下,ulimit -u太低会导致OutOfMemoryError异常。

为运行HBase进程的用户配置文件描述符和进程的最大数量是操作系统配置,而不是HBase配置。确保为实际运行HBase的用户更改设置也很重要。要查看哪个用户启动了HBase,以及该用户的ulimit配置,请查看该实例的HBase日志的第一行。

示例:ulimit在Ubuntu上的设置

要在Ubuntu上配置ulimit设置,请编辑:/etc/security/limits.conf,它是一个由四列组成的空格分隔的文件。在以下示例中,第一行将用户名为hadoop的操作系统用户的打开文件数(nofile)的软限制和硬限制设置为32768。第二行将同一用户的进程数设置为32000。

hadoop - nofile 32768 
hadoop - nproc 32000

这些设置仅适用于可插入身份验证模块(PAM)环境指示使用它们的情况。要配置PAM以使用这些限制,请确保/etc/pam.d/common-session文件包含以下行:

session required  pam_limits.so

Linux Shell

所有HBase附带的shell脚本都依赖于 GNU Bash shell。

Windows

在HBase 0.96之前,在Microsoft Windows上运行HBase仅限于测试目的。不建议在Windows计算机上运行生产系统。

Hadoop

下表总结了每个HBase版本支持的Hadoop版本。基于HBase的版本,您应该选择最合适的Hadoop版本。

建议使用 Hadoop 2.x:Hadoop 2.x 速度更快,包括短路读取功能,这将有助于提高您的 HBase 随机读取配置文件;Hadoop 2.x 还包括重要的 bug 修复,可以改善您的整体 HBase 体验;HBase 不支持使用早期版本的 Hadoop 运行;有关特定于不同 HBase 版本的要求,请参见下表;Hadoop 3.x 仍处于早期访问版本中,尚未被 HBase 社区对生产用例进行充分测试。

使用以下的注解来解释下面的这个表格:

Hadoop版本支持矩阵:

  • “S”=支持
  • “X”=不支持
  • “NT”=未测试
  • “X”=不支持
HBase的-1.1.x中HBase的-1.2.x的HBase的-1.3.x的HBase的-2.0.x版本
Hadoop-2.0.x-alphaXXXX
Hadoop-2.1.0-betaXXXX
Hadoop-2.2.0NTXXX
Hadoop-2.3.xNTXXX
Hadoop-2.4.xSSSX
Hadoop-2.5.xSSSX
Hadoop-2.6.0XXXX
Hadoop-2.6.1+NTSSS
Hadoop-2.7.0XXXX
Hadoop-2.7.1+NTSSS
Hadoop-2.8.0XXXX
Hadoop-2.8.1XXXX
Hadoop-3.0.0NTNTNTNT

Hadoop Pre-2.6.1 和 JDK 1.8 Kerberos

在 Kerberos 环境中使用 pre-2.6.1 Hadoop 版本和 JDK 1.8 时,HBase 服务器可能因 Kerberos keytab relogin 错误而失败并中止。JDK 1.7 (1.7. 0_80) 的后期版本也有问题。在这种情况下考虑升级到Hadoop 2.6.1+。

Hadoop 2.6.x

如果您计划在 HDFS 加密区域的顶部运行 HBase,则基于 2.6.x 行的 Hadoop 发行版必须具有 HADOOP-11710 应用。如果不这样做,将导致群集故障和数据丢失。此修补程序存在于Apache Hadoop 2.6.1+版本中。

Hadoop 2.7.x

Hadoop 2.7.0版本未经测试或不受支持,因为Hadoop PMC明确将该版本标记为不稳定。

Hadoop 2.8.x

Hadoop 2.8.0和2.8.1版本未经测试或不受支持,因为Hadoop PMC明确标记版本不稳定。

更换与 HBase 捆绑的 Hadoop

因为 HBase 依赖于Hadoop,它将Hadoop jar的一个实例捆绑在其 lib 目录下。捆绑的 jar 仅用于在独立模式下使用。在分布式模式下,群集上的 Hadoop 版本与 HBase 下的内容相匹配是至关重要的。将在 HBase lib 目录中找到的 hadoop jar 替换为您在群集上运行的 hadoop jar,以避免版本不匹配问题。确保在整个集群中替换 HBase 中的 jar。

dfs.datanode.max.transfer.threads

HDFS DataNode在任何时候都会有一个文件数上限。在进行任何加载之前,请确保您已经配置了Hadoop的conf / hdfs-site.xml,并将该dfs.datanode.max.transfer.threads值设置为至少如下的值:

<property>
   <name>dfs.datanode.max.transfer.threads</name>   
   <value>4096</value> 
</property>

进行上述配置后,务必重新启动HDFS。

没有这个配置就会造成奇怪的故障。其中一种表现是对缺失区块的投诉。例如:

10``/12/08` `20:10:31 INFO hdfs.DFSClient: Could not obtain block
      ``blk_XXXXXXXXXXXXXXXXXXXXXX_YYYYYYYY from any node: java.io.IOException: No 
live nodes 
      ``contain current block. Will get new block locations from namenode and retry...

ZooKeeper要求

动物园管理员3.4.x 是必需的。HBase 使用的多功能, 只可从动物园管理员3.4.0。hbase.zookeeper.useMulti 配置属性默认为 true。参考 HBASE-12241 (在采用deadserver的复制队列时会中断复制的regionServer的崩溃) 和 HBASE-6775 (在可用于HBASE-6710 0.92 / 0.94兼容性修补程序时使用ZK.multi)。该属性被弃用,并且在 HBase 2.0 中始终启用 useMulti。


HBase 运行模式

HBase运行模式:独立式和分布式

HBase有两种运行模式:独立式和分布式。HBase以独立模式运行。无论您的模式如何,您都需要通过编辑HBase conf目录中的文件来配置HBase 。至少,您必须编辑conf/hbase-env.sh来告诉HBase要使用哪个java。在这个文件中,你设置了HBase环境变量,比如JVM的heapsize和其他选项,日志文件的首选位置等等。设置JAVA_HOME以指向你的java安装的根目录。

独立式HBase

默认情况下使用的是独立式的HBase。在“快速启动HBase”一节中,我们已经介绍过独立模式。在独立模式下,HBase不使用HDFS,而是使用本地文件系统,是在同一个JVM中运行所有HBase守护进程和本地ZooKeeper。ZooKeeper绑定到一个众所周知的端口,通过该端口,客户端可以和HBase进行通信。

独立于HBFS的HBase

有时在独立的hbase上有一个有用的变体,它的所有的守护进程都在一个JVM中运行,而不是坚持到本地文件系统,而是坚持到一个HDFS实例。

当您打算使用简单的部署配置文件时,您可能会考虑使用此配置文件,加载很轻松,但是数据必须在节点的出入之间持续存在。向 HDFS 写入数据的地方可以确保后者。

要配置此独立变体,请编辑hbase-site.xml,设置hbase.rootdir以指向HDFS实例中的某个目录,然后将hbase.cluster.distributed设置为false。例如:

xml<configuration>
   <property>
        <name>hbase.rootdir</name>     
        <value>hdfs://namenode.example.org:8020/hbase</value>   
    </property>   
    <property>
         <name>hbase.cluster.distributed</name>     
         <value>false</value>   
     </property> 
</configuration>

分布式HBase

分布式模式可以细分为分布式、伪分布式(所有守护进程都在单个节点上运行)、完全分布式(守护进程分布在集群中的所有节点上)。其中,伪分布式模式与完全分布式的命名来自于Hadoop。

伪分布式模式可以针对本地文件系统运行,也可以针对Hadoop分布式文件系统(HDFS)的实例运行。完全分布式模式只能在HDFS上运行。

伪分布式HBase

伪分布式模式的HBase就是在单个主机上运行的完全分布式模式。使用此HBase配置仅进行测试和原型设计。请勿将此配置用于生产或性能评估。

完全分布式

默认情况下,HBase以独立模式运行,独立模式和伪分布模式用于小规模测试。对于生产环境,建议使用分布式模式。在分布式模式下,HBase守护进程的多个实例在集群中的多个服务器上运行。

就像在伪分布式模式中一样,完全分布式的配置要求您将hbase.cluster.distributed属性设置为true。通常情况下,hbase.rootdir被配置为指向高可用性的HDFS文件系统。

此外,还配置了群集,以便多个群集节点成为RegionServer、ZooKeeper QuorumPeers和备份HMaster服务器。

分布式区域服务器(RegionServers)

通常,你的群集将包含多个运行在不同服务器上的RegionServer,以及主要和备份Master和ZooKeeper守护程序。主服务器上的conf/regionservers文件中包含一个主机列表,其RegionServers与该集群相关。每个主机都在一个单独的行上。当主服务器启动或停止时,此文件中列出的所有主机将启动和停止其RegionServer进程。

ZooKeeper和HBase

有关HBase的ZooKeeper设置说明,请参见ZooKeeper部分。

示例 - 分布式HBase集群示例

这是一个分布式HBase集群的简单的conf/hbase-site.xml。用于实际工作的群集将包含更多自定义配置参数。大多数HBase配置指令都具有默认值,除非在hbase-site.xml中覆盖该值,否则将使用这些默认值。有关更多信息,请参阅“配置文件”。

<configuration>
   <property>     
   <name>hbase.rootdir</name>     
   <value>hdfs://namenode.example.org:8020/hbase</value>   
   </property>   
   <property>     
   <name>hbase.cluster.distributed</name>     
   <value>true</value>   
   </property>   
   <property>     
   <name>hbase.zookeeper.quorum</name>     
   <value>node-a.example.com,node-b.example.com,node-c.example.com</value>   
   </property> 
</configuration>

这是conf/regionservers文件的示例,其中包含应在集群中运行RegionServer的节点的列表。这些节点需要安装HBase,他们需要使用与主服务器相同的conf/目录内容:

node-a.example.com 
node-b.example.com 
node-c.example.com

这是conf/backup-masters文件的示例,其中包含应运行备份主实例的每个节点的列表。除非主主站变为不可用,否则备份主站实例将处于空闲状态。

node-b.example.com 
node-c.example.com

分布式HBase快速入门

请参阅快速入门 - 完全分布,了解包含多个ZooKeeper、备份HMaster和RegionServer实例的简单三节点群集配置。

HDFS客户端配置

值得注意的是,如果您在Hadoop集群上进行了HDFS客户端配置更改(例如,HDFS客户端的配置指令),而不是服务器端配置,则必须使用以下方法之一来启用HBase以查看和使用这些配置更改:

  • 在hbase-env.sh中添加一个指向你HADOOP_CONF_DIR的HBASE_CLASSPATH环境变量的指针;
  • 在$ {HBASE_HOME}/conf下添加一个hdfs-site.xml(或hadoop-site.xml)或更好的符号链接;
  • 如果只有一小部分HDFS客户端配置,请将它们添加到hbase-site.xml。

这种HDFS客户端配置的一个例子是dfs.replication。例如,如果希望以5的复制因子运行,则HBase将创建缺省值为3的文件,除非您执行上述操作以使配置可用于HBase。


HBase 开始运行

运行HBase

保证HDFS第一次运行,你需要通过在HADOOP_HOME目录中运行bin/start-hdfs.sh来启动和停止Hadoop HDFS守护进程。你确保它正确启动的方法是通过在 Hadoop 文件系统中测试文件的put和get。HBase通常不使用MapReduce或YARN守护进程,因此它们不需要启动。

如果您正在管理您自己的ZooKeeper,请启动它并确认它正在运行,否则HBase将启动ZooKeeper作为其启动过程的一部分。

你可以从HBASE_HOME目录使用以下命令来启动HBase:

bin/start-hbase.sh

您现在应该有一个正在运行的HBase实例。HBase日志可以在日志子目录中找到。检查出来,特别是如果HBase启动困难。

HBase也提供了一个UI列出了重要的属性。默认情况下,它被部署在16010端口的主控主机上(默认情况下HBase RegionServers侦听端口16020,并在端口16030建立一个信息HTTP服务器)。如果主服务器(Master )在默认端口上指定的master.example.org主机上运行,请将浏览器指向http://master.example.org:16010以查看Web界面。

一旦HBase启动,请参阅下面的shell部分,了解创建表,添加数据,扫描插入内容以及最终禁用和删除表的一些操作命令。

退出HBase shell后停止HBase进入:

$ ./bin/stop-hbase.sh 
stopping hbase...............

关机可能需要稍等一些时间才能完成。如果您的集群由多台计算机组成,则可能需要更长的时间。如果您正在运行分布式操作,那么在停止Hadoop守护进程之前,一定要等到HBase完全关闭。

HBase Shell

使用Shell可以与HBase进行通信。HBase使用Hadoop文件系统来存储数据。它拥有一个主服务器和区域服务器。数据存储将在区域(表)的形式。这些区域被分割并存储在区域服务器。

主服务器管理这些区域服务器,所有这些任务发生在HDFS。下面给出的是一些由HBase Shell支持的命令。

Shell 通用命令

  • status: 提供HBase的状态,例如,服务器的数量。
  • version: 提供正在使用HBase版本。
  • table_help: 表引用命令提供帮助。
  • whoami: 提供有关用户的信息。

Shell 数据定义语言

下面列举了HBase Shell支持的可以在表中操作的命令。

  • create: 用于创建一个表。
  • list: 用于列出HBase的所有表。
  • disable: 用于禁用表。
  • is_disabled: 用于验证表是否被禁用。
  • enable: 用于启用一个表。
  • is_enabled: 用于验证表是否已启用。
  • describe: 用于提供了一个表的描述。
  • alter: 用于改变一个表。
  • exists: 用于验证表是否存在。
  • drop: 用于从HBase中删除表。
  • drop_all: 用于丢弃在命令中给出匹配“regex”的表。
  • Java Admin API: 在此之前所有的上述命令,Java提供了一个通过API编程来管理实现DDL功能。在这个org.apache.hadoop.hbase.client包中有HBaseAdmin和HTableDescriptor 这两个重要的类提供DDL功能。

Shell 数据操作语言

  • put: 用于把指定列在指定的行中单元格的值在一个特定的表。

  • get: 用于取行或单元格的内容。

  • delete:用于删除表中的单元格值。

  • deleteall: 用于删除给定行的所有单元格。

  • scan: 用于扫描并返回表数据。

  • count: 用于计数并返回表中的行的数目。

  • truncate: 用于禁用、删除和重新创建一个指定的表。

  • Java client API: 在此之前所有上述命令,Java提供了一个客户端API来实现DML功能,CRUD(创建检索更新删除)操作更多的是通过编程,在org.apache.hadoop.hbase.client包下。 在此包HTable 的 Put和Get是重要的类。

启动 HBase Shell

要访问HBase shell,你需要进入到HBase的主文件夹中:

cd /usr/localhost/ 
cd Hbase

然后通过使用“hbase shell”命令启动HBase shell:

./bin/hbase shell

如果已成功在系统中安装HBase,那么它会给出 HBase shell 提示符,如下图所示。

HBase Shell; enter 'help<RETURN>' for list of supported commands.
Type "exit<RETURN>" to leave the HBase Shell 
Version 0.94.23, rf42302b28aceaab773b15f234aa8718fff7eea3c, Wed Aug 27 00:54:09 UTC 2014 
 
hbase(main):001:0>

退出 HBase Shell

要退出shell命令,你可以通过键入 exit 或使用<Ctrl + C>实现。


HBase 默认配置

hbase-site.xml和hbase-default.xml

在Hadoop中将特定于站点的HDFS配置添加到hdfs-site.xml文件,那么对于HBase,特定于站点的配置文件为conf/hbase-site.xml。有关可配置属性的列表,请参见下面的HBase默认配置或查看src/main/resources的HBase源代码中的原始hbase-default.xml源文件。

并不是所有的配置选项都会将其发送到hbase-default.xml。一些配置只会出现在源代码中;因此识别这些更改的唯一方法是通过代码审查。

目前,这里的更改将需要为HBase重启集群来注意到这个变化。

HBase 默认配置

以下文档是使用默认的HBase配置文件hbase-default.xml作为源生成的。

  • hbase.tmp.dir

    这是本地文件系统上的临时目录。将此设置更改为指向比“/tmp”更持久的位置,这是java.io.tmpdir的常见解决方案,因为在重新启动计算机时清除了“/tmp”目录。默认为:  j a v a . i o . t m p d i r / h b a s e − {java.io.tmpdir}/hbase- java.io.tmpdir/hbase{user.name}

  • hbase.rootdir

    这个目录是region servers共享的目录,HBase保持不变。该URL应该是“完全限定的”以包括文件系统的scheme。例如,要指定HDFS实例的"/hbase"目录,namenode运行在namenode.example.org的9000端口,请将此值设置为:hdfs://namenode.example.org:9000 / hbase。默认情况下,我们会写$ {hbase.tmp.dir},通常是/tmp - 所以改变这个配置,否则所有的数据在计算机重启时都会丢失。默认为:${hbase.tmp.dir}/hbase

  • hbase.cluster.distributed

    群集所处的模式。对于独立模式,可能的值为false,对于分布式模式,可能的值为true。如果为false,启动将在一个JVM中一起运行所有HBase和ZooKeeper守护程序。默认为:false

  • hbase.zookeeper.quorum

    使用逗号分隔的ZooKeeper集合中的服务器列表(这个配置应该被命名为hbase.zookeeper.ensemble)。例如,“host1.mydomain.com,host2.mydomain.com,host3.mydomain.com”。默认情况下,对于本地和伪分布式操作模式,将其设置为localhost。对于完全分布式安装,应将其设置为ZooKeeper集成服务器的完整列表。如果在hbase-env.sh中设置HBASE_MANAGES_ZK,这是hbase将作为群集启动/停止的一部分来启动/停止ZooKeeper的服务器列表。客户端,我们将把这个集合成员的列表,并把它与hbase.zookeeper.property.clientPort配置放在一起。并将其作为connectString参数传递给zookeeper构造函数。默认为:localhost

  • zookeeper.recovery.retry.maxsleeptime

    在重试 zookeeper操作之前的最大睡眠时间(以毫秒为单位),这里需要最大时间,以便睡眠时间不会无限增长。默认为:60000

  • hbase.local.dir

    将本地文件系统上的目录用作本地存储。默认为:${hbase.tmp.dir}/local/

  • hbase.master.port

    HBase Master应该绑定的端口。默认为:16000

  • hbase.master.info.port

    HBase Master Web UI的端口。如果您不想运行UI实例,请将其设置为-1。默认为:16010

  • hbase.master.info.bindAddress

  • HBase Master Web UI的绑定地址默认为:0.0.0.0

  • hbase.master.logcleaner.plugins

    由LogsCleaner服务调用的BaseLogCleanerDelegate的逗号分隔列表。这些WAL清理是按顺序调用的。要实现您自己的BaseLogCleanerDelegate,只需将其放入HBase的类路径中,并在此添加完全限定的类名。始终在列表中添加上面的默认日志清理工具。默认为:org.apache.hadoop.hbase.master.cleaner.TimeToLiveLogCleaner,org.apache.hadoop.hbase.master.cleaner.TimeToLiveProcedureWALCleaner

  • hbase.master.logcleaner.ttl

    WAL在归档({hbase.rootdir} / oldWALs)目录中保留多久,之后将由主线程清除。该值以毫秒为单位。默认为:600000

  • hbase.master.procedurewalcleaner.ttl

    程序WAL将在归档目录中保留多久,之后将由主线程清除。该值以毫秒为单位。默认为:604800000

  • hbase.master.hfilecleaner.plugins

    由HFileCleaner服务调用的BaseHFileCleanerDelegate的逗号分隔列表。这些HFile清理器按顺序调用。要实现您自己的BaseHFileCleanerDelegate,只需将其放入HBase的类路径中,并在此添加完全限定的类名。总是在列表中添加上面的默认日志清除程序,因为它们将被覆盖在hbase-site.xml中。默认为:org.apache.hadoop.hbase.master.cleaner.TimeToLiveHFileCleaner

  • hbase.master.infoserver.redirect

    Master是否监听Master Web UI端口(hbase.master.info.port)并将请求重定向到由Master和RegionServer共享的Web UI服务器。配置,当主服务区域(而不是默认)时是有意义的。默认为:true

  • hbase.master.fileSplitTimeout

    分割一个区域,在放弃尝试之前等待文件分割步骤需要多长时间。默认值:600000。这个设置在hbase-1.x中被称为hbase.regionserver.fileSplitTimeout。Split现在运行主端,因此重命名(如果找到’hbase.master.fileSplitTimeout’设置,将使用它来填充当前’hbase.master.fileSplitTimeout’配置。默认为:600000

  • hbase.regionserver.port

    HBase RegionServer绑定的端口。默认为:16020

  • hbase.regionserver.info.port

    HBase RegionServer Web UI的端口如果您不希望RegionServer UI运行,请将其设置为-1。默认为:16030

  • hbase.regionserver.info.bindAddress

    HBase RegionServer Web UI的地址默认为:0.0.0.0

  • hbase.regionserver.info.port.auto

    Master或RegionServer UI是否应搜索要绑定的端口。如果hbase.regionserver.info.port已被使用,则启用自动端口搜索。用于测试,默认关闭。默认为:false

  • hbase.regionserver.handler.count

    在RegionServers上启动RPC Listener实例的计数。Master使用相同的属性来处理主处理程序的数量。太多的处理者可能会适得其反。使其成为CPU数量的倍数。如果主要是只读的,处理程序计数接近CPU计数做得很好。从CPU数量的两倍开始,并从那里调整。默认为:30

  • hbase.ipc.server.callqueue.handler.factor

    确定呼叫队列数量的因素。值为0表示在所有处理程序之间共享单个队列。值为1意味着每个处理程序都有自己的队列。默认为:0.1

  • hbase.ipc.server.callqueue.read.ratio

    将调用队列分成读写队列。指定的时间间隔(应该在0.0到1.0之间)将乘以调用队列的数量。值为0表示不分割调用队列,这意味着读取和写入请求将被推送到相同的一组队列中。低于0.5的值意味着将比写入队列更少的读取队列。值为0.5意味着将有相同数量的读写队列。大于0.5的值意味着将有更多的读队列而不是写入队列。值为1.0意味着除了一个之外的所有队列都用于发送读取请求。示例:假设调用队列的总数为10,则read.ratio为0意味着:10个队列将同时包含读/写请求。0.3的读取比例意味着:3个队列将只包含读取请求,7个队列将只包含写入请求。0.5的read.ratio表示:5个队列将只包含读取请求,5个队列将只包含写入请求。0.8的read.ratio意味着:8个队列将只包含读取请求,2个队列将只包含写入请求。1的read.ratio表示:9个队列将只包含读取请求,1个队列将只包含写入请求。默认为:0

  • hbase.ipc.server.callqueue.scan.ratio

    考虑到读取的调用队列的数量(根据调用队列的总数乘以callqueue.read.ratio计算),scan.ratio属性将把读取的调用队列拆分为小读取和长读取队列。低于0.5的值意味着长读队列比短读队列少。值为0.5意味着将有相同数量的短读取和长读取队列。大于0.5的值意味着将会有比长读取队列更多的长读取队列。值0或1表示使用同一组队列进行获取和扫描。示例:给定读取调用队列的总数为8,scan.ratio为0或1意味着:8个队列将包含长读请求和短读请求。0.3的scan.ratio表示:2个队列只包含长读请求,6个队列只包含短读请求。0.5的scan.ratio表示:4个队列只包含长读请求,4个队列只包含短读请求。0.8的scan.ratio意味着:6个队列只包含长读请求,2个队列只包含短读请求。默认为:0

  • hbase.regionserver.msginterval

    从RegionServer到Master的消息间隔(以毫秒为单位)。默认为:3000

  • hbase.regionserver.logroll.period- 无论有多少次编辑,我们将滚动提交日志的时间段。默认为:3600000
    无论有多少次编辑,我们将滚动提交日志的时间段。

  • hbase.regionserver.logroll.errors.tolerated

    在触发服务器中止之前,我们将允许连续的WAL关闭错误的数量。如果在日志滚动过程中关闭当前WAL书写器失败,则设置为0将导致区域服务器中止。即使是一个很小的值(2或3)也会让区域服务器承担瞬间的HDFS错误。默认为:2

  • hbase.regionserver.hlog.reader.impl

    WAL文件读取器的实现。默认为:org.apache.hadoop.hbase.regionserver.wal.ProtobufLogReader

  • hbase.regionserver.hlog.writer.impl

    WAL文件编写器的实现。默认为:org.apache.hadoop.hbase.regionserver.wal.ProtobufLogWriter

  • hbase.regionserver.global.memstore.size

    在新更新被阻止并刷新之前,区域服务器中所有存储区的最大大小。默认为堆的40%(0.4)。更新被阻止,强制刷新直到区域服务器中的所有内存大小都达到hbase.regionserver.global.memstore.size.lower.limit。此配置中的默认值已被故意留空,以便兑现旧的hbase.regionserver.global.memstore.upperLimit属性(如果存在)。没有默认值。

  • hbase.regionserver.global.memstore.size.lower.limit

    强制刷新之前,区域服务器中所有存储区的最大大小。默认为hbase.regionserver.global.memstore.size(0.95)的95%。当由于内存限制而导致更新被阻塞时,此值的100%会导致最小可能的刷新。此配置中的默认值已被故意留空,以便兑现旧的hbase.regionserver.global.memstore.lowerLimit属性(如果存在)。没有默认值。

  • hbase.systemtables.compacting.memstore.type

    确定用于系统表(如META,名称空间表等)的memstore的类型。默认情况下,NONE是类型,因此我们对所有系统表使用默认的memstore。如果我们需要为系统表使用压缩存储器,那么将这个属性设置为:BASIC / EAGER默认值:NONE

  • hbase.regionserver.optionalcacheflushinterval

    在自动刷新之前,编辑在内存中的最长时间。默认为1小时。将其设置为0将禁用自动刷新。默认为:3600000

  • hbase.regionserver.dns.interface

    区域服务器应从中报告其IP地址的网络接口的名称。默认为:default

  • hbase.regionserver.dns.nameserver

    域名服务器应使用的名称服务器(DNS)的主机名或IP地址,以确定主机用于通信和显示的主机名。默认为:default

  • hbase.regionserver.region.split.policy

    分割策略决定了一个区域应该何时拆分。当前可用的各种其他拆分策略是:BusyRegionSplitPolicy,ConstantSizeRegionSplitPolicy,DisabledRegionSplitPolicy,DelimitedKeyPrefixRegionSplitPolicy,KeyPrefixRegionSplitPolicy和SteppingSplitPolicy。DisabledRegionSplitPolicy会阻止手动区域分割。默认为:org.apache.hadoop.hbase.regionserver.SteppingSplitPolicy

  • hbase.regionserver.regionSplitLimit

    限制区域数量,之后不再发生区域分割。这并不是硬性限制区域数量,而是作为区域服务商在一定限度之后停止分裂的指导方针。默认设置为1000。默认为:1000

  • zookeeper.session.timeout

    ZooKeeper会话超时(以毫秒为单位)。它使用两种不同的方式。首先,这个值用于HBase用来连接到集合的ZK客户端。当它启动一个ZK服务器时它也被HBase使用,并且它被作为’maxSessionTimeout’传递。请参阅http://hadoop.apache.org/zookeeper/docs/current/zookeeperProgrammers.html#ch_zkSessions。例如,如果HBase区域服务器连接到也由HBase管理的ZK集合,那么会话超时将是由此配置指定的。但是,连接到以不同配置管理的集成的区域服务器将受到该集合的maxSessionTimeout的限制。所以,尽管HBase可能会建议使用90秒,但是整体的最大超时时间可能会低于此值,并且会优先考虑。ZK目前的默认值是40秒,比HBase的低。默认为:90000

  • zookeeper.znode.parent

    ZooKeeper中用于HBase的Root ZNode。所有配置了相对路径的HBase的ZooKeeper文件都会在这个节点下。默认情况下,所有的HBase的ZooKeeper文件路径都被配置为一个相对路径,所以它们将全部进入这个目录下,除非被改变。默认为:/hbase

  • zookeeper.znode.acl.parent

    Root ZNode用于访问控制列表。默认为:acl

  • hbase.zookeeper.dns.interface

    ZooKeeper服务器应从中报告其IP地址的网络接口的名称。默认为:default

  • hbase.zookeeper.dns.nameserver

    名称服务器(DNS)的主机名或IP地址,ZooKeeper服务器应使用该名称服务器来确定主机用于通信和显示的主机名。默认为:default

  • hbase.zookeeper.peerport

    ZooKeeper同伴使用的端口进行彼此会话。有关更多信息,请参阅http://hadoop.apache.org/zookeeper/docs/r3.1.1/zookeeperStarted.html#sc_RunningReplicatedZooKeeper。默认为:2888

  • hbase.zookeeper.leaderport

    ZooKeeper用于leader选举的端口。有关更多信息,请参阅http://hadoop.apache.org/zookeeper/docs/r3.1.1/zookeeperStarted.html#sc_RunningReplicatedZooKeeper。默认为:3888

  • hbase.zookeeper.property.initLimit

    来自ZooKeeper的配置zoo.cfg的属性。初始同步阶段可以采用的时钟(ticks)周期数。默认为:10

  • hbase.zookeeper.property.syncLimit

    来自ZooKeeper的配置zoo.cfg的属性。发送请求和获取确认之间可以传递的时钟(ticks)数量。默认为:5

  • hbase.zookeeper.property.dataDir

    来自ZooKeeper的配置zoo.cfg的属性。快照存储的目录。默认为:${hbase.tmp.dir}/zookeeper

  • hbase.zookeeper.property.clientPort

    来自ZooKeeper的配置zoo.cfg的属性。客户端将连接的端口。默认为:2181

  • hbase.zookeeper.property.maxClientCnxns

    来自ZooKeeper的配置zoo.cfg的属性。限制由IP地址标识的单个客户端的并发连接数量(在套接字级别)可能会对ZooKeeper集合的单个成员产生影响。设置为高,以避免独立运行和伪分布式运行的zk连接问题。默认为:300

  • hbase.client.write.buffer

    BufferedMutator写入缓冲区的默认大小(以字节为单位)。一个更大的缓冲区需要更多的内存 - 在客户端和服务器端,因为服务器实例化传递的写入缓冲区来处理它 - 但更大的缓冲区大小减少了RPC的数量。对于估计使用的服务器端内存,计算:hbase.client.write.buffer * hbase.regionserver.handler.count 默认为:2097152

  • hbase.client.pause

    一般客户端pause值。在运行失败的get,region lookup等的重试之前,主要用作等待的值。默认为:100

  • hbase.client.pause.cqtbe

    是否为CallQueueTooBigException(cqtbe)使用特殊的客户端pause。如果您观察到来自同一个RegionServer的频繁的CQTBE,并且其中的调用队列保持充满,则将此属性设置为比hbase.client.pause更高的值没有默认值。

  • hbase.client.retries.number

    最大重试次数。用作所有可重试操作(如获取单元格值,启动行更新等)的最大值。重试间隔是基于hbase.client.pause的粗略函数。首先,我们在这段时间重试,但后来退后,我们很快就达到每十秒钟重试一次。请参阅HConstants#RETRY_BACKOFF了解备份如何提升。改变这个设置和hbase.client.pause来适应你的工作负载。默认为:15

  • hbase.client.max.total.tasks

    单个HTable实例发送到集群的最大并发突变任务数。默认为:100

  • hbase.client.max.perserver.tasks

    单个HTable实例将发送到单个区域服务器的并发突变任务的最大数量。默认为:2

  • hbase.client.max.perregion.tasks

    客户端将维护到单个Region的最大并发突变任务数。也就是说,如果已经有hbase.client.max.perregion.tasks写入这个区域,那么新的放入将不会被发送到这个区域,直到一些写入完成。默认为:1

  • hbase.client.perserver.requests.threshold

    所有客户端线程(进程级别)中一个服务器的并发未决请求的最大数量。超过请求将立即抛出ServerTooBusyException,以防止用户的线程被占用和只被一个缓慢的区域服务器阻止。如果使用固定数量的线程以同步方式访问HBase,请将此值设置为与线程数量相关的适当值,这些值将对您有所帮助。默认为:2147483647

  • hbase.client.scanner.caching

    如果从本地,客户端内存中未提供,则在扫描程序上调用next时尝试获取的行数。此配置与hbase.client.scanner.max.result.size一起使用,可以有效地使用网络。缺省值默认为Integer.MAX_VALUE,这样网络将填充由hbase.client.scanner.max.result.size定义的块大小,而不受特定行数的限制,因为行的大小随表格的不同而不同。如果您事先知道扫描中不需要超过一定数量的行,则应通过扫描#setCaching将此配置设置为该行限制。缓存值越高,扫描器的速度越快,但是会占用更多的内存,而当缓存空置时,下一次调用的时间可能会越来越长。请勿设置此值,以便调用之间的时间大于扫描器超时;即hbase.client.scanner.timeout.period,默认为:2147483647

  • hbase.client.keyvalue.maxsize

    指定KeyValue实例的组合的最大允许大小。这是为保存在存储文件中的单个条目设置上限。由于它们不能被分割,所以有助于避免因为数据太大而导致地区不能被分割。将此设置为最大区域大小的一小部分似乎是明智的。将其设置为零或更少将禁用检查。默认为:10485760

  • hbase.server.keyvalue.maxsize

    单个单元格的最大允许大小,包括值和所有关键组件。值为0或更小将禁用检查。默认值是10MB。这是保护服务器免受OOM情况的安全设置。默认为:10485760

  • hbase.client.scanner.timeout.period

    客户端扫描程序的租期以毫秒为单位。默认为:60000

  • hbase.client.localityCheck.threadPoolSize

    默认为:2

  • hbase.bulkload.retries.number

    最大重试次数,这是在面对分裂操作时尝试原子批量加载的最大迭代次数,0意味着永不放弃。默认为:10

  • hbase.master.balancer.maxRitPercent

    平衡时转换区域的最大百分比。默认值是1.0。所以没有平衡器节流。如果将此配置设置为0.01,则意味着在平衡时转换中最多有1%的区域。那么当平衡时,集群的可用性至少为99%。默认为:1.0

  • hbase.balancer.period

    区域平衡器在主站运行的时间段。默认为:300000

  • hbase.normalizer.period

    区域标准化程序在主程序中运行的时段。默认为:300000

  • hbase.regions.slop

    如果任何区域服务器具有平均值+(平均斜率)区域,则重新平衡。StochasticLoadBalancer(默认负载均衡器)中此参数的默认值为0.001,其他负载均衡器(即SimpleLoadBalancer)中的默认值为0.2。默认为:0.001
    如果任何区域服务器具有平均值+(平均
    斜率)区域,则重新平衡。StochasticLoadBalancer(默认负载均衡器)中此参数的默认值为0.001,其他负载均衡器(即SimpleLoadBalancer)中的默认值为0.2。

  • hbase.server.thread.wakefrequency

在两次搜索之间休息的时间(以毫秒为单位)。用作日志滚筒等服务线程的睡眠间隔。默认为:10000

  • hbase.server.versionfile.writeattempts

在放弃之前重试尝试写入版本文件的次数。每个尝试都由hbase.server.thread.wake频率毫秒分隔。默认为:3

  • hbase.hregion.memstore.flush.size

如果memstore的大小超过此字节数,Memstore将被刷新到磁盘。值由每个hbase.server.thread.wakefrequency运行的线程检查。默认为:134217728

  • hbase.hregion.percolumnfamilyflush.size.lower.bound.min

如果使用了FlushLargeStoresPolicy,并且有多个列族,那么每当我们达到完全的memstore限制时,我们就会找出所有memstore超过“下限”的列族,只有在保留其他内存的同时刷新它们。默认情况下,“下限”将是“hbase.hregion.memstore.flush.size/column_family_number”,除非该属性的值大于该值。如果没有一个族的memstore大小超过下限,所有的memstore都将被刷新(就像往常一样)。默认为:16777216

  • hbase.hregion.preclose.flush.size

如果我们关闭时某个区域的存储空间大于或等于这个大小,则可以运行“预先刷新(pre-flush)”来清除存储区,然后再放置区域关闭标记并使区域脱机。关闭时,在关闭标志下运行刷新以清空内存。在此期间,该地区处于离线状态,我们没有进行任何写入。如果memstore内容很大,则此刷新可能需要很长时间才能完成。这个预刷新是为了清理大部分的memstore,然后把关闭标志放到离线区域,这样在关闭标志下运行的刷新没有什么用处。默认为:5242880

  • hbase.hregion.memstore.block.multiplier

如果memstore具有hbase.hregion.memstore.block.multiplier乘以hbase.hregion.memstore.flush.size个字节,则阻止更新。在更新通信高峰期间有用的防止失控的memstore。如果没有上限,memstore就会填满,当刷新生成的flush文件需要很长时间才能压缩或拆分。默认为:4

  • hbase.hregion.memstore.mslab.enabled

启用MemStore-Local分配缓冲区,该功能可用于在繁重的写入负载下防止堆碎片。这可以减少在大堆停止全局GC pause的频率。默认为:true

  • hbase.hregion.max.filesize

最大HFile大小。如果一个地区的HFiles的总和已经超过了这个数值,这个地区就会被分成两部分。默认为:10737418240

  • hbase.hregion.majorcompaction

主要压缩之间的时间,以毫秒表示。设置为0可禁用基于时间的自动重要压缩。用户请求的和基于大小的主要压缩将仍然运行。这个值乘以hbase.hregion.majorcompaction.jitter,使压缩在一个给定的时间窗口内稍微随机的时间开始。默认值是7天,以毫秒表示。如果主要压缩导致您的环境中断,则可以将它们配置为在部署的非高峰时间运行,或者通过将此参数设置为0来禁用基于时间的主要压缩,并在cron作业或另一个外部机制。默认为:604800000

  • hbase.hregion.majorcompaction.jitter

应用于hbase.hregion.majorcompaction的乘数会导致压缩发生在给定的时间量的任何一侧的hbase.hregion.majorcompaction。数字越小,压缩将越接近hbase.hregion.majorcompaction时间间隔。默认为:0.50

  • hbase.hstore.compactionThreshold

如果任何一个Store中存在超过此数量的StoreFiles(每个MemStore刷新一个StoreFile),则会执行压缩以将所有StoreFile重写为单个StoreFile。较大的值会延迟压实,但是当压缩发生时,需要较长时间才能完成。默认为:3

  • hbase.hstore.flusher.count

刷新线程的数量。用更少的线程,MemStore刷新将排队。随着线程数量的增加,刷新将并行执行,增加了HDFS的负载,并可能导致更多的压缩。默认为:2

  • hbase.hstore.blockingStoreFiles

如果任何一个Store中存在超过此数量的StoreFiles(每次刷新MemStore时将写入一个StoreFile),则会阻止该区域的更新,直到压缩完成或超出hbase.hstore.blockingWaitTime。默认为:16

  • hbase.hstore.blockingWaitTime

在达到hbase.hstore.blockingStoreFiles定义的StoreFile限制后,区域将阻止更新的时间。经过这段时间后,即使压缩尚未完成,该地区也将停止阻止更新。默认为:90000

  • hbase.hstore.compaction.min

压缩可以运行之前,必须有符合进行压缩条件的最小StoreFiles数量。调整hbase.hstore.compaction.min的目标是避免使用太多的小型StoreFiles来压缩。如果将此值设置为2,则每次在Store中有两个StoreFiles时会导致轻微的压缩,这可能不合适。如果将此值设置得太高,则需要相应调整所有其他值。对于大多数情况下,默认值是适当的。在以前的HBase版本中,参数hbase.hstore.compaction.min被命名为hbase.hstore.compactionThreshold。默认为:3

  • hbase.hstore.compaction.max

无论符合条件的StoreFiles的数量如何,将为单个次要压缩选择的StoreFiles的最大数量。有效地,hbase.hstore.compaction.max的值控制单个压缩完成所需的时间长度。将其设置得更大意味着更多的StoreFiles包含在压缩中。对于大多数情况下,默认值是适当的。默认为:10

  • hbase.hstore.compaction.min.size

StoreFile(或使用ExploringCompactionPolicy时选择的StoreFiles)小于此大小将始终有资格进行轻微压缩。这个大小或更大的HFile通过hbase.hstore.compaction.ratio进行计算,以确定它们是否合格。由于此限制表示所有StoreFiles的“自动包含”限制小于此值,因此在需要刷新多个StoreFile(1-2 MB范围内的许多StoreFiles)的写入繁重环境中可能需要降低此值,因为每个StoreFile都将作为目标,对于压缩而言,所得到的StoreFile可能仍然在最小尺寸下,并且需要进一步的压缩。如果此参数降低,比率检查会更快地触发。这解决了在早期版本的HBase中看到的一些问题,但是在大多数情况下不再需要更改此参数。默认为:134217728

  • hbase.hstore.compaction.ratio

对于轻微压缩,此比率用于确定大于hbase.hstore.compaction.min.size的给定StoreFile是否适合压缩。其作用是限制大型StoreFiles的压缩。hbase.hstore.compaction.ratio的值以浮点小数表示。一个很大的比例,如10,将产生一个大型的StoreFile。相反,低值(如0.25)会产生类似于BigTable压缩算法的行为,产生四个StoreFiles。推荐使用1.0到1.4之间的中等数值。在调整此值时,您要平衡写入成本与读取成本。提高价值(如1.4)会有更多的写入成本,因为你会压缩更大的StoreFiles。然而,在读取期间,HBase将需要通过更少的StoreFiles来完成读取。如果您不能利用Bloom过滤器,请考虑使用这种方法。否则,可以将此值降低到1.0以降低写入的背景成本,并使用Bloom过滤器来控制读取期间触摸的StoreFiles的数量。对于大多数情况下,默认值是适当的。默认为:1.2F

  • hbase.hstore.compaction.ratio.offpeak

允许您设置不同(默认情况下,更积极)的比率,以确定在非高峰时段是否包含较大的StoreFiles。以与hbase.hstore.compaction.ratio相同的方式工作。仅当hbase.offpeak.start.hour和hbase.offpeak.end.hour也被启用时才适用。默认为:5.0F

  • hbase.hstore.time.to.purge.deletes

使用未来的时间戳延迟清除标记的时间。如果未设置,或设置为0,则将在下一个主要压缩过程中清除所有删除标记(包括具有未来时间戳的标记)。否则,将保留一个删除标记,直到在标记的时间戳之后发生的主要压缩加上此设置的值(以毫秒为单位)。默认为:0

  • hbase.offpeak.start.hour

非高峰时段开始,以0到23之间的整数表示,包括0和23之间的整数。设置为-1以禁用非高峰。默认为:-1

  • hbase.offpeak.end.hour

非高峰时段结束,以0到23之间的整数表示,包括0和23之间的整数。设置为-1以禁用非高峰。默认为:-1

  • hbase.regionserver.thread.compaction.throttle

有两个不同的线程池用于压缩,一个用于大型压缩,另一个用于小型压缩。这有助于保持精简表(如hbase:meta)的快速压缩。如果压缩度大于此阈值,则会进入大型压缩池。在大多数情况下,默认值是适当的。默认值:2 x hbase.hstore.compaction.max x hbase.hregion.memstore.flush.size(默认为128MB)。值字段假定hbase.hregion.memstore.flush.size的值与默认值相同。默认为:2684354560

  • hbase.regionserver.majorcompaction.pagecache.drop

指定是否通过主要压缩删除读取/写入系统页面缓存的页面。将其设置为true有助于防止重大压缩污染页面缓存,这几乎总是要求的,特别是对于具有低/中等内存与存储率的群集。默认为:true

  • hbase.regionserver.minorcompaction.pagecache.drop

指定是否通过较小的压缩删除读取/写入系统页面缓存的页面。将其设置为true有助于防止轻微压缩污染页面缓存,这对于内存与存储比率较低的群集或写入较重的群集是最有利的。当大部分读取位于最近写入的数据上时,您可能希望在中等到低写入工作负载下将其设置为false。默认为:true

  • hbase.hstore.compaction.kv.max

刷新或压缩时要读取并批量写入的KeyValues的最大数量。如果你有较大的KeyValues,并且Out Of Memory Exceptions有问题,请将它设置得更低。默认为:10

  • hbase.storescanner.parallel.seek.enable

在StoreScanner中启用StoreFileScanner并行搜索功能,该功能可以在特殊情况下减少响应延迟。默认为:false

  • hbase.storescanner.parallel.seek.threads

如果启用了并行查找功能,则默认线程池大小。默认为:10

  • hfile.block.cache.size

StoreFile使用的最大堆(-Xmx设置)分配给块缓存的百分比。默认值为0.4意味着分配40%。设置为0禁用,但不建议;您至少需要足够的缓存来保存存储文件索引。默认为:0.4

  • hfile.block.index.cacheonwrite

这允许在索引被写入时将非根多级索引块放入块高速缓存中。默认为:false

  • hfile.index.block.max.size

当多级块索引中叶级,中级或根级索引块的大小增长到这个大小时,块将被写出并启动一个新块。默认为:131072

  • hbase.bucketcache.ioengine

在哪里存储bucketcache的内容。其中之一:offheap、文件或mmap。如果有文件,则将其设置为file(s):PATH_TO_FILE。mmap意味着内容将在一个mmaped文件中。使用mmap:PATH_TO_FILE。没有默认值。

  • hbase.bucketcache.size

EITHER表示缓存的总堆内存大小的百分比(如果小于1.0),则表示BucketCache的总容量(兆字节)。默认值:0.0

  • hbase.bucketcache.bucket.sizes

用于bucketcache的存储区大小的逗号分隔列表。可以是多种尺寸。列出从最小到最大的块大小。您使用的大小取决于您的数据访问模式。必须是256的倍数,否则当你从缓存中读取时,你会遇到“java.io.IOException:Invalid HFile block magic”。如果您在此处未指定任何值,那么您可以选取代码中设置的默认bucketsizes。没有默认值。

  • hfile.format.version

用于新文件的HFile格式版本。版本3添加了对hfiles中标签的支持(请参阅http://hbase.apache.org/book.html#hbase.tags)。另请参阅配置“hbase.replication.rpc.codec”。默认为:3

  • hfile.block.bloom.cacheonwrite

为复合Bloom过滤器的内联块启用写入缓存。默认为:false

  • io.storefile.bloom.block.size

复合Bloom过滤器的单个块(“chunk”)的字节大小。这个大小是近似的,因为Bloom块只能被插入到数据块的边界处,而每个数据块的key的个数也不相同。默认为:131072

  • hbase.rs.cacheblocksonwrite

块完成后,是否应将HFile块添加到块缓存中。默认为:false

  • hbase.rpc.timeout

这是为了让RPC层定义一个远程调用超时(毫秒)HBase客户端应用程序超时。它使用ping来检查连接,但最终会抛出TimeoutException。默认为:60000

  • hbase.client.operation.timeout

操作超时是一个顶级的限制(毫秒),确保表格中的阻止操作不会被阻止超过这个限制。在每个操作中,如果rpc请求由于超时或其他原因而失败,则将重试直到成功或抛出RetriesExhaustedException。但是,如果总的阻塞时间在重试耗尽之前达到操作超时,则会提前中断并抛出SocketTimeoutException。默认为:1200000

  • hbase.cells.scanned.per.heartbeat.check

在heartbeat检查之间扫描的单元格的数量。在扫描处理过程中会发生heartbeat检查,以确定服务器是否应该停止扫描,以便将heartbeat消息发送回客户端。heartbeat消息用于在长时间运行扫描期间保持客户端 - 服务器连接的活动。较小的值意味着heartbeat检查将更频繁地发生,因此将对扫描的执行时间提供更严格的界限。数值越大意味着heartbeat检查发生的频率越低。默认为:10000

  • hbase.rpc.shortoperation.timeout

这是“hbase.rpc.timeout”的另一个版本。对于集群内的RPC操作,我们依靠此配置为短操作设置短超时限制。例如,区域服务器试图向活动主服务器报告的短rpc超时可以更快地进行主站故障转移过程。默认为:10000

  • hbase.ipc.client.tcpnodelay

在rpc套接字连接上设置没有延迟。默认为:true

  • hbase.regionserver.hostname

这个配置适用于对HBase很熟悉的人:除非你真的知道你在做什么,否则不要设定它的价值。当设置为非空值时,这表示底层服务器的(面向外部)主机名。没有默认值。

  • hbase.regionserver.hostname.disable.master.reversedns

这个配置适用于对HBase很熟练的人:除非你真的知道你在做什么,否则不要设定它的价值。当设置为true时,regionserver将使用当前节点主机名作为服务器名称,HMaster将跳过反向DNS查找并使用regionserver发送的主机名。请注意,此配置和hbase.regionserver.hostname是互斥的。默认为:false

  • hbase.master.keytab.file

用于登录配置的HMaster服务器主体的kerberos密钥表文件的完整路径。没有默认值。

  • hbase.master.kerberos.principal

“hbase/_HOST@EXAMPLE.COM”,应该用来运行HMaster进程的Kerberos主体名称。主体名称的格式应为:user/hostname @ DOMAIN。如果使用“_HOST”作为主机名部分,它将被替换为正在运行的实例的实际主机名。没有默认值。

  • hbase.regionserver.keytab.file

用于登录配置的HRegionServer服务器主体的kerberos密钥表文件的完整路径。没有默认值。

  • hbase.regionserver.kerberos.principal

“hbase/_HOST@EXAMPLE.COM”。应该用来运行HRegionServer进程的kerberos主体名称。主体名称的格式应为:user/hostname @ DOMAIN。如果使用“_HOST”作为主机名部分,它将被替换为正在运行的实例的实际主机名。此主体的条目必须存在于hbase.regionserver.keytab.file中指定的文件中,没有默认值。

  • hadoop.policy.file

RPC服务器使用策略配置文件对客户端请求进行授权决策。仅在启用HBase安全性时使用。默认为:hbase-policy.xml

  • hbase.superuser

用户或组列表(以逗号分隔),允许在整个集群中拥有完全权限(不管存储的ACL)。仅在启用HBase安全性时使用。没有默认值。

  • hbase.auth.key.update.interval

服务器中认证令牌的主密钥的更新间隔(以毫秒为单位)。仅在启用HBase安全性时使用。默认为:86400000

  • hbase.auth.token.max.lifetime

验证令牌过期的最长生存时间(以毫秒为单位)。仅在启用HBase安全性时使用。默认为:604800000

  • hbase.ipc.client.fallback-to-simple-auth-allowed

当客户端配置为尝试安全连接,但尝试连接到不安全的服务器时,该服务器可能会指示客户端切换到SASL SIMPLE(不安全)身份验证。此设置控制客户端是否接受来自服务器的此指令。如果为false(默认值),则客户端将不允许回退到SIMPLE身份验证,并会中止连接。默认为:false

  • hbase.ipc.server.fallback-to-simple-auth-allowed

当服务器配置为需要安全连接时,它将拒绝来自使用SASL SIMPLE(不安全)身份验证的客户端的连接尝试。此设置允许安全服务器在客户端请求时接受来自客户端的SASL SIMPLE连接。如果为false(默认值),服务器将不允许回退到SIMPLE身份验证,并将拒绝连接。警告:只有在将客户端转换为安全身份验证时,才应将此设置用作临时措施。必须禁止它才能进行安全操作。默认为:false

  • hbase.display.keys

当它被设置为true时,webUI等将显示所有开始/结束键作为表格细节,区域名称等的一部分。当这被设置为假时,键被隐藏。默认为:true

  • hbase.coprocessor.enabled

启用或禁用协处理器加载。如果’false’(禁用),任何其他协处理器相关的配置将被忽略。默认为:true

  • hbase.coprocessor.user.enabled

启用或禁用用户(又名表)协处理器加载。如果’false’(禁用),则表格描述符中的任何表协处理器属性将被忽略。如果“hbase.coprocessor.enabled”为“false”,则此设置无效。默认为:true

  • hbase.coprocessor.region.classes

在所有表上默认加载的区域观察者或端点协处理器的逗号分隔列表。对于任何覆盖协处理器方法,这些类将按顺序调用。在实现自己的协处理器之后,将其添加到HBase的类路径中,并在此处添加完全限定的类名称。协处理器也可以通过设置HTableDescriptor或者HBase shell来按需加载。没有默认值。

  • hbase.coprocessor.master.classes

在活动的HMaster进程中默认加载的org.apache.hadoop.hbase.coprocessor.MasterObserver协处理器的逗号分隔列表。对于任何实施的协处理器方法,列出的类将按顺序调用。在实现你自己的MasterObserver之后,把它放在HBase的类路径中,并在这里添加完全限定的类名称。没有默认值。

  • hbase.coprocessor.abortonerror- 如果协处理器加载失败,初始化失败或引发意外的Throwable对象,则设置为true将导致托管服务器(主服务器或区域服务器)中止。将其设置为false将允许服务器继续执行,但所涉及的协处理器的系统范围状态将变得不一致,因为它只能在一部分服务器中正确执行,所以这对于仅调试是非常有用的。默认为:true
    如果协处理器加载失败,初始化失败或引发意外的Throwable对象,则设置为true将导致托管服务器(主服务器或区域服务器)中止。将其设置为false将允许服务器继续执行,但所涉及的协处理器的系统范围状态将变得不一致,因为它只能在一部分服务器中正确执行,所以这对于仅调试是非常有用的。

  • hbase.rest.port- HBase REST服务器的端口。默认为:8080
    HBase REST服务器的端口。

  • hbase.rest.readonly

定义REST服务器将启动的模式。可能的值有:false:此时,所有的HTTP方法都是允许的 - GET / PUT / POST / DELETE。true:此时只允许GET方法。默认为:false

  • hbase.rest.threads.max

REST服务器线程池的最大线程数。池中的线程被重用来处理REST请求。这将控制同时处理的最大请求数。这可能有助于控制REST服务器使用的内存以避免OOM问题。如果线程池已满,则传入的请求将排队并等待一些空闲的线程。默认为:100

  • hbase.rest.threads.min

REST服务器线程池的最小线程数。线程池总是至少有这么多的线程,所以REST服务器已经准备好为传入的请求提供服务。默认为:2

  • hbase.rest.support.proxyuser

启用运行REST服务器以支持代理用户模式。默认为:false

  • hbase.defaults.for.version.skip

设置为true可以跳过“hbase.defaults.for.version”检查。将其设置为true可以在除maven生成的另一侧之外的上下文中有用;即运行在IDE中。你需要设置这个布尔值为true以避免看到RuntimeException:“hbase-default.xml文件似乎是HBase(\ $ {hbase.version})的旧版本,这个版本是XXX-SNAPSHOT”默认为:false

  • hbase.table.lock.enable

设置为true以启用锁定zookeeper中的表以进行模式更改操作。从主服务器锁定表可以防止并发的模式修改损坏表状态。默认为:true

  • hbase.table.max.rowsize

单行字节的最大大小(默认值为1 Gb),用于Get-ing或Scan’ning,不设置行内扫描标志。如果行大小超过此限制RowTooBigException被抛出到客户端。默认为:1073741824

  • hbase.thrift.minWorkerThreads

线程池的“核心大小”。在每个连接上创建新线程,直到创建了许多线程。默认为:16

  • hbase.thrift.maxWorkerThreads

线程池的最大大小。待处理的请求队列溢出时,将创建新线程,直到其号码达到此数字。之后,服务器开始丢弃连接。默认为:1000

  • hbase.thrift.maxQueuedRequests

在队列中等待的最大等待节点连接数。如果池中没有空闲线程,则服务器将请求排队。只有当队列溢出时,才会添加新的线程,直到hbase.thrift.maxQueuedRequests线程。默认为:1000

  • hbase.regionserver.thrift.framed

在服务器端使用Thrift TFramedTransport。对于thrift服务器,这是推荐的传输方式,需要在客户端进行类似的设置。将其更改为false将选择默认传输,当由于THRIFT-601发出格式错误的请求时,容易受到DoS的影响。默认为:false

  • hbase.regionserver.thrift.framed.max_frame_size_in_mb

使用成帧传输时的默认帧大小,以MB为单位。默认为:2

  • hbase.regionserver.thrift.compact

使用Thrift TCompactProtocol二进制序列化协议。默认为:false

  • hbase.rootdir.perms

安全(kerberos)安装程序中根数据子目录的FS Permissions。主服务器启动时,会使用此权限创建rootdir,如果不匹配则设置权限。默认为:700

  • hbase.wal.dir.perms

安全(kerberos)安装程序中的根WAL目录的FS Permissions。当主服务器启动时,它将使用此权限创建WAL目录,如果不匹配则设置权限。默认为:700

  • hbase.data.umask.enable

如果启用,则启用该文件权限应分配给区域服务器写入的文件默认为:false

  • hbase.data.umask

当hbase.data.umask.enable为true时,应该用来写入数据文件的文件权限默认为:000

  • hbase.snapshot.enabled

设置为true以允许taken/restored/cloned。默认为:true

  • hbase.snapshot.restore.take.failsafe.snapshot

设置为true以在还原操作之前得到快照。所得到的快照将在失败的情况下使用,以恢复以前的状态。在还原操作结束时,此快照将被删除默认为:true

  • hbase.snapshot.restore.failsafe.name

restore操作所采用的故障安全快照的名称。您可以使用{snapshot.name},{table.name}和{restore.timestamp}变量根据要恢复的内容创建一个名称。默认为:hbase-failsafe-{snapshot.name}-{restore.timestamp}

  • hbase.server.compactchecker.interval.multiplier

这个数字决定了我们扫描的频率,看是否需要压缩。通常情况下,压缩是在某些事件(如memstore flush)之后完成的,但是如果区域在一段时间内没有收到大量的写入,或者由于不同的压缩策略,则可能需要定期检查。检查之间的时间间隔是hbase.server.compactchecker.interval.multiplier乘以hbase.server.thread.wakefrequency。默认为:1000

  • hbase.lease.recovery.timeout

在放弃之前,我们等待dfs lease的总恢复时间。默认为:900000

  • hbase.lease.recovery.dfs.timeout

dfs恢复lease调用之间的时间间隔。应该大于namenode为datanode的一部分发出块恢复命令所需的时间总和;dfs.heartbeat.interval和主数据节点所花费的时间,在死数据节点上执行数据块恢复到超时;通常是dfs.client.socket-timeout。默认为:64000

  • hbase.column.max.version

新的列族描述符将使用此值作为要保留的默认版本数。默认为:1

  • dfs.client.read.shortcircuit

如果设置为true,则此配置参数启用short-circuit本地读取。默认为:false。

  • dfs.domain.socket.path

如果将dfs.client.read.shortcircuit设置为true,则这是一个UNIX域套接字的路径,该套接字将用于DataNode与本地HDFS客户端之间的通信。如果该路径中存在字符串“_PORT”,则会被DataNode的TCP端口替换。请注意托管共享域套接字的目录的权限。默认为:none

  • hbase.dfs.client.read.shortcircuit.buffer.size

如果未设置DFSClient配置dfs.client.read.shortcircuit.buffer.size,我们将使用此处配置的内容作为short-circuit读取默认直接字节缓冲区大小。DFSClient本机默认值是1MB;HBase保持HDFS文件的打开状态,所以文件块*1MB的数量很快就开始累积起来,并由于直接内存不足而威胁OOME。所以,我们从默认设置下来。使它大于在HColumnDescriptor中设置的默认hbase块大小,通常是64k。默认为:131072

  • hbase.regionserver.checksum.verify

如果设置为true(默认),HBase将验证hfile块的校验和。当HBase写出hfiles时,HBase将校验和写入数据。HDFS(在此写入时)将校验和写入单独的文件,而不是需要额外查找的数据文件。设置这个标志可以节省一些I/O。设置此标志时,HDFS的校验和验证将在hfile流内部禁用。如果hbase-checksum验证失败,我们将切换回使用HDFS校验和(所以不要禁用HDFS校验!除此功能外,还适用于hfiles,而不适用于WAL)。如果这个参数设置为false,那么hbase将不会验证任何校验和,而是取决于HDFS客户端中的校验和验证。默认为:true

  • hbase.hstore.bytes.per.checksum

新创建的校验和块中的字节数,用于hfile块中的HBase级校验和。默认为:16384

  • hbase.hstore.checksum.algorithm

用于计算校验和的算法的名称。可能的值是NULL,CRC32,CRC32C。默认为:CRC32C

  • hbase.client.scanner.max.result.size

  • 调用扫描器的下一个方法时返回的最大字节数。请注意,当单个行大于此限制时,行仍然完全返回。默认值是2MB,这对于1ge网络是有好处的。有了更快和/或更高的延迟网络,这个值应该增加。默认为:2097152
    调用扫描器的下一个方法时返回的最大字节数。请注意,当单个行大于此限制时,行仍然完全返回。默认值是2MB,这对于1ge网络是有好处的。有了更快和/或更高的延迟网络,这个值应该增加。

  • hbase.server.scanner.max.result.size

调用扫描器的下一个方法时返回的最大字节数。请注意,当单个行大于此限制时,行仍然完全返回。默认值是100MB。这是保护服务器免受OOM情况的安全设置。默认为:104857600

  • hbase.status.published

该设置激活了主控发布区域服务器的状态。当一台区域服务器死亡并开始恢复时,主服务器会将这些信息推送到客户端应用程序,让他们立即切断连接,而不是等待超时。默认为:false

  • hbase.status.publisher.class

用multicast消息实现状态发布。默认为:org.apache.hadoop.hbase.master.ClusterStatusPublisher$MulticastPublisher

  • hbase.status.listener.class

使用multicast消息实现状态监听器。默认为:org.apache.hadoop.hbase.client.ClusterStatusListener$MulticastListener

  • hbase.status.multicast.address.ip

用于multicase状态发布的multicase地址。默认为:226.1.1.3

  • hbase.status.multicast.address.port

用于multicase状态发布的multicase端口。默认为:16100

  • hbase.dynamic.jars.dir

自定义过滤器JAR的目录可以由区域服务器动态加载,而无需重新启动。但是,已加载的过滤器/协处理器类将不会被卸载。不适用于协处理器。默认为:${hbase.rootdir}/lib

  • hbase.security.authentication

控制是否为HBase启用安全身份验证。可能的值是“simple”(不认证)和“Kerberos”。默认为:simple

  • hbase.rest.filter.classes

用于REST服务的Servlet过滤器。默认为:org.apache.hadoop.hbase.rest.filter.GzipFilter

  • hbase.master.loadbalancer.class

用于在期间发生时执行区域平衡的类。它将DefaultLoadBalancer替换为默认值(因为它被重命名为SimpleLoadBalancer )。默认为:org.apache.hadoop.hbase.master.balancer.StochasticLoadBalancer

  • hbase.master.loadbalance.bytable

平衡器运行时的因子表名称。默认:false。默认为:false

  • hbase.master.normalizer.class

用于执行期间发生时的区域标准化的类。默认为:org.apache.hadoop.hbase.master.normalizer.SimpleRegionNormalizer

  • hbase.rest.csrf.enabled

设置为true以启用对跨站点请求forgery(CSRF)的保护。默认为:false

  • hbase.rest-csrf.browser-useragents-regex

通过将hbase.rest.csrf.enabled设置为true来启用为REST服务器,针对跨站点请求伪造(CSRF)的防护时,用于匹配HTTP请求的User-Agent标头的正则表达式的逗号分隔列表。如果传入的用户代理与这些正则表达式中的任何一个相匹配,则认为该请求被浏览器发送,因此CSRF预防被强制执行。如果请求的用户代理与这些正则表达式中的任何一个都不匹配,则该请求被认为是由除浏览器以外的其他东西发送的,例如脚本自动化。在这种情况下,CSRF不是一个潜在的攻击向量,所以预防没有被执行。这有助于实现与尚未更新以发送CSRF预防报头的现有自动化的向后兼容性。默认为:Mozilla.,Opera.

  • hbase.security.exec.permission.checks

如果启用此设置,并且基于ACL的访问控制处于活动状态(AccessController协处理器作为系统协处理器安装,或作为表协处理器安装在表上),则必须授予所有相关用户EXEC权限(如果需要执行协处理器端点调用。像任何其他权限一样,EXEC权限可以在全局范围内授予用户,也可以授予每个表或命名空间的用户。有关协处理器端点的更多信息,请参阅HBase联机手册的协处理器部分。有关使用AccessController授予或撤消权限的更多信息,请参阅HBase联机手册的安全性部分。默认为:false

  • hbase.procedure.regionserver.classes

在活动HRegionServer进程中默认加载的org.apache.hadoop.hbase.procedure.RegionServerProcedureManager过程管理器的逗号分隔列表。生命周期方法(init / start / stop)将由活动的HRegionServer进程调用,以执行特定的全局barriered过程。在实现你自己的RegionServerProcedureManager之后,把它放在HBase的类路径中,并在这里添加完全限定的类名称。

  • hbase.procedure.master.classes

在活动HMaster进程中默认加载的org.apache.hadoop.hbase.procedure.MasterProcedureManager过程管理器的逗号分隔列表。程序通过其签名进行标识,用户可以使用签名和即时名称来触发全局程序的执行。在实现你自己的MasterProcedureManager之后,把它放在HBase的类路径中,并在这里添加完全限定的类名称。

  • hbase.coordinated.state.manager.class

协调状态管理员的完全合格的名字。默认为:org.apache.hadoop.hbase.coordination.ZkCoordinatedStateManager

  • hbase.regionserver.storefile.refresh.period

用于刷新辅助区域的存储文件的时间段(以毫秒为单位)。0意味着此功能被禁用。辅助区域在次要区域刷新区域中的文件列表时会看到来自主要文件的新文件(来自刷新和压缩)(没有通知机制)。但是频繁刷新可能会导致额外的Namenode压力。如果文件的刷新时间不能超过HFile TTL(hbase.master.hfilecleaner.ttl),请求将被拒绝。此设置还建议将HFile TTL配置为较大的值。默认为:0

  • hbase.region.replica.replication.enabled

是否启用对辅助区域副本的异步WAL复制。如果启用了此功能,则会创建一个名为“region_replica_replication”的复制对等项,它将对日志进行尾随处理,并将突变复制到区域复制大于1的区域复制的区域复制。如果启用一次,禁用此复制也需要禁用复制对等使用shell或Admin java类。复制到辅助区域副本可以在标准群集间复制上工作。默认为:false

  • hbase.http.filter.initializers

一个以逗号分隔的类名列表。列表中的每个类都必须扩展org.apache.hadoop.hbase.http.FilterInitializer。相应的过滤器将被初始化。然后,过滤器将应用于所有面向jsp和servlet网页的用户。列表的排序定义了过滤器的排序。默认的StaticUserWebFilter添加hbase.http.staticuser.user属性定义的用户主体。默认为:org.apache.hadoop.hbase.http.lib.StaticUserWebFilter

  • hbase.security.visibility.mutations.checkauths

如果启用此属性,将检查可见性表达式中的标签是否与发出突变的用户相关联默认为:false

  • hbase.http.max.threads

HTTP服务器将在其ThreadPool中创建的最大线程数。默认为:16

  • hbase.replication.rpc.codec

启用复制时要使用的编解码器,以便标签也被复制。这与支持标签的HFileV3一起使用。如果标签未被使用或者所使用的hfile版本是HFileV2,则可以使用KeyValueCodec作为复制编解码器。请注意,在没有标签时使用KeyValueCodecWithTags进行复制不会造成任何伤害。默认为:org.apache.hadoop.hbase.codec.KeyValueCodecWithTags

  • hbase.replication.source.maxthreads

任何复制源将用于并行传送编辑到接收器的最大线程数。这也限制了每个复制批次被分解成的块的数量。较大的值可以提高主群集和从群集之间的复制吞吐量。默认值为10,很少需要改变。默认为:10

  • hbase.serial.replication.waitingMs

默认情况下,在复制中,我们不能确定slave集群中的操作顺序与master集群中的顺序相同。如果将REPLICATION_SCOPE设置为2,我们将按照写入顺序进行编辑。这个配置是设置在下一次检查之前,我们将等待多长时间(以毫秒为单位),如果日志不能被推送,因为有一些日志写在它之前还没有被推入。较大的等待将减少hbase:meta上的查询数量,但会增加复制的延迟。此功能依赖于zk-less分配,因此用户必须将hbase.assignment.usezk设置为false来支持它。默认为:10000

  • hbase.http.staticuser.user

要在呈现内容时在静态网页过滤器上过滤的用户名称。一个示例使用是HDFS Web UI(用于浏览文件的用户)。默认为:dr.stack

  • hbase.regionserver.handler.abort.on.error.percent

区域服务器RPC线程的百分比无法中止RS。-1表示禁用中止;0表示即使单个处理程序已经死亡也会中止;0.x表示只有当这个百分比的处理程序死亡时才中止;1表示只中止所有的处理程序已经死亡。默认为:0.5

  • hbase.mob.file.cache.size

要缓存的已打开文件处理程序的数量。更大的值将通过为每个移动文件缓存提供更多的文件处理程序来减少频繁的文件打开和关闭,从而有利于读取。但是,如果设置得太高,则可能导致“打开的文件处理程序太多”。默认值为1000。默认为:1000

  • hbase.mob.cache.evict.period

mob高速缓存驱逐高速缓存的mob文件之前的时间(秒)。默认值是3600秒。默认为:3600

  • hbase.mob.cache.evict.remain.ratio

当缓存的移动文件数量超过hbase.mob.file.cache.size时,触发驱逐后保留的文件的比率(介于0.0和1.0之间)会被触发。默认值是0.5f。默认为:0.5f

  • hbase.master.mob.ttl.cleaner.period

ExpiredMobFileCleanerChore运行的时间段。该单位是秒。默认值是一天。MOB文件名仅使用文件创建时间的日期部分。我们使用这个时间来决定文件的TTL到期时间。所以删除TTL过期的文件可能会被延迟。最大延迟可能是24小时。默认为:86400

  • hbase.mob.compaction.mergeable.threshold

如果一个mob文件的大小小于这个值,那么它被认为是一个小文件,需要在mob compaction中合并。默认值是1280MB。默认为:1342177280

  • hbase.mob.delfile.max.count

mob压缩中允许的最大del文件数。在mob压缩中,当现有的del文件的数量大于这个值时,它们被合并,直到del文件的数量不大于该值。默认值是3。默认为:3

  • hbase.mob.compaction.batch.size

在一批mob压缩中所允许的mob文件的最大数量。mob压缩合并小的mob文件到更大的。如果小文件的数量非常大,则可能导致合并中的“打开的文件处理程序太多”。合并必须分成批次。此值限制在一批mob压缩中选择的mob文件的数量。默认值是100。默认为:100

  • hbase.mob.compaction.chore.period

MobCompactionChore运行的时间。该单位是秒。默认值是一个星期。默认为:604800

  • hbase.mob.compactor.class

执行mob compactor,默认一个是PartitionedMobCompactor。默认为:org.apache.hadoop.hbase.mob.compactions.PartitionedMobCompactor

  • hbase.mob.compaction.threads.max

MobCompactor中使用的最大线程数。默认为:1

  • hbase.snapshot.master.timeout.millis

主快照程序执行的超时。默认为:300000

  • hbase.snapshot.region.timeout

区域服务器将线程保持在快照请求池中等待超时。默认为:300000

  • hbase.rpc.rows.warning.threshold

批处理操作中的行数,超过该值将记录警告。默认为:5000。

  • hbase.master.wait.on.service.seconds

    默认是5分钟。做30秒的测试。有关上下文,请参见HBASE-19794。默认为:30

hbase-env.sh

hbase-env.sh文件用来设置HBase环境变量。比如包括在启动HBase守护程序(如堆大小和垃圾回收器配置)时传递JVM的选项。您还可以设置HBase配置、日志目录、niceness、ssh选项,定位进程pid文件的位置等的配置。打开conf/hbase-env.sh文件并仔细阅读其内容。每个选项都有相当好的记录。如果希望在启动时由HBase守护进程读取,请在此处添加您自己的环境变量。

此处的更改将需要重启HBase才能注意到更改。

log4j.properties

编辑文件以更改HBase文件的滚动速度,并更改HBase记录消息的级别。

此处的更改将需要重新启动集群以注意到更改,尽管可以通过HBase UI为特定的守护程序更改日志级别。

客户端配置和依赖关系连接到HBase集群

如果您在独立模式下运行HBase,则不必为您的客户端配置任何内容,只要保证它们在同一台计算机上即可。

由于HBase Master可以移动,客户可以通过向ZooKeeper寻找当前的关键位置来进行引导。ZooKeeper是保存所有这些值的地方。因此客户需要ZooKeeper集合的位置才能做其他事情。通常这个集合位置被保存在hbase-site.xml中,并由客户端从CLASSPATH中提取。

如果你正在配置一个IDE来运行一个HBase客户端,你应该在你的类路径中包含conf/目录,这样可以找到hbase-site.xml设置(或者添加src/test/resources来获取使用的hbase-site.xml文件通过测试)。

最小的情况是,当连接到集群时,HBase客户机需要依赖关系中的hbase-client模块:

<dependency>
   <groupId>org.apache.hbase</groupId>   
   <artifactId>hbase-client</artifactId>   
   <version>1.2.4</version> 
</dependency>

一个基本的客户端的hbase-site.xml的使用示例可能如下所示:

<?xml version="1.0"?> 
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?> 
<configuration>
   <property>
        <name>hbase.zookeeper.quorum</name>
        <value>example1,example2,example3</value>     
        <description>The directory shared by region servers.     
        </description>   
    </property> 
</configuration>

Java客户端配置

Java客户端使用的配置保存在HBaseConfiguration实例中。

HBaseConfiguration的工厂方法,HBaseConfiguration.create();,在调用时会读取客户端上的第一个hbase-site.xml的内容(CLASSPATH如果存在的话)(调用也将包含在任何发现的hbase-default.xml中;hbase-default.xml在hbase.X.X.X.jar里面)。也可以直接指定配置,而无需从hbase-site.xml中读取数据。例如,要以编程方式设置集群的ZooKeeper集成,请执行以下操作:

Configuration config = HBaseConfiguration.create(); 
config.set("hbase.zookeeper.quorum", "localhost");  // Here we are running zookeeper locally

如果多个ZooKeeper实例组成ZooKeeper集合,则可以在逗号分隔列表中指定它们(就像在hbase-site.xml文件中一样)。这个填充的Configuration实例然后可以传递给一个表,依此类推。


HBase 配置示例

基本分布式HBase安装

在下文内容中是一个分布式10节点的群集的基本配置示例:其中,节点被命名为example0,example1…一直到example9,在这个例子中;HBase Master和HDFS NameNode正在节点example0上运行;RegionServers在节点example1- example9上运行;一个3节点ZooKeeper集合运行在example1、example2,以及example3的默认端口上;ZooKeeper的数据被保存到:directory/export/zookeeper。

下面我们显示在HBase conf目录中找到的主要配置文件  -hbase-site.xml,regionservers和hbase-env.sh。

HBase-site.xml

<?xml version="1.0"?> 
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?> 
<configuration>
   <property>
        <name>hbase.zookeeper.quorum</name>     
        <value>example1,example2,example3</value>     
        <description>The directory shared by RegionServers.     
        </description>   
    </property>   
    <property>
         <name>hbase.zookeeper.property.dataDir</name>     
         <value>/export/zookeeper</value>     
         <description>Property from ZooKeeper config zoo.cfg.     
         The directory where the snapshot is stored.     
         </description>   
     </property>   
     <property>
          <name>hbase.rootdir</name>     
          <value>hdfs://example0:8020/hbase</value>     
          <description>The directory shared by RegionServers.     
          </description>   
      </property>   
      <property>
           <name>hbase.cluster.distributed</name>     
           <value>true</value>     
           <description>The mode the cluster will be in. Possible values are       
           false: standalone and pseudo-distributed setups with managed ZooKeeper       
           true: fully-distributed with unmanaged ZooKeeper Quorum (see hbase-env.sh)     
           </description>   
       </property> 
</configuration>

regionservers

在此文件中列出将运行RegionServers的节点。在我们的例子中,这些节点是example1- example9。

example1 
example2 
example3 
example4 
example5 
example6 
example7 
example8 
example9

hbase-env.sh文件中的以下行显示了如何设置JAVA_HOME环境变量(HBase需要的)并将堆设置为4 GB(而不是默认值1 GB)。如果您复制并粘贴此示例,请务必调整JAVA_HOME以适合您的环境。

# The java implementation to use. 
export JAVA_HOME=/usr/java/jdk1.8.0/ 
 
# The maximum amount of heap to use. Default is left to JVM default. 
export HBASE_HEAPSIZE=4

Base 重要配置

下面我们列出一些重要的配置。我们已经将这部分分为必需的配置和值得推荐的配置。

HBase所需的配置

请你参考本教程中HBase基础条件中的操作系统和Hadoop部分的内容!

大型群集配置

如果您拥有一个包含大量区域的群集,那么在主服务器启动后,Regionserver可能会暂时地进行检查,而所有剩余的RegionServers落后。要签入的第一台服务器将被分配到所有不是最优的区域。为防止出现上述情况,请将其hbase.master.wait.on.regionservers.mintostart属性从其默认值1中调高。

HBase推荐的配置

ZooKeeper 配置:zookeeper.session.timeout

默认的超时时间是三分钟(以毫秒为单位)。这意味着,如果服务器崩溃,则在主服务器在三分钟前发现崩溃并开始恢复。您可能需要将超时调整到一分钟甚至更短的时间,以便主服务器尽快通知故障。在更改此值之前,请确保您的JVM垃圾收集配置处于受控状态,否则,长时间的垃圾回收会超出ZooKeeper会话超时时间,将取出您的RegionServer。(如果一个RegionServer长时间处于GC状态,你可能需要在服务器上启动恢复)。

要更改此配置,请编辑hbase-site.xml,将更改的文件复制到群集中并重新启动。

我们将这个值设置得很高,以避免不必要的麻烦。如果出现类似“为什么我在执行一个大规模数据导入的时候Region Server死掉啦”这样的问题,可以解释的原因是:他们的JVM未被解析,并且正在运行长时间的GC操作。

ZooKeeper 实例的数量

HDFS 配置

dfs.datanode.failed.volumes.tolerated

这是“DataNode 停止提供服务之前允许失败的卷数。默认情况下,任何卷失败都会导致 datanode 关闭”从HDFS-default.xml中的描述。您可能希望将其设置为可用磁盘数量的一半左右。

hbase.regionserver.handler.count

此设置定义了为应答传入的用户表请求而保持打开的线程数。经验法则是,当每个请求的有效载荷接近MB(大容量、扫描使用大缓存)时保持低数字,并且当有效负载小(获取,小投入,ICV,删除)时保持此数字为高。正在进行的查询的总大小受设置hbase.ipc.server.max.callqueue.size的限制。

如果这个数字的有效载荷很小,那么将这个数字设置为最大传入客户端数量是安全的,典型的例子是一个服务于网站的集群,因为put通常不被缓冲,大部分操作都是获取的。

保持此设置的高风险的原因是,当前在区域服务器中发生的所有投入的总大小可能对其内存造成太大的压力,甚至会触发OutOfMemoryError。在低内存上运行的RegionServer将触发其JVM的垃圾收集器,以更频繁的方式运行,直到GC暂停变得明显(原因是用于保留所有请求的有效载荷的所有内存不能被丢弃,即便垃圾收集器正在进行尝试)。一段时间之后,整个群集吞吐量都会受到影响,因为每个碰到该RegionServer的请求都将花费更长的时间,这更加剧了问题的严重性。

您可以通过rpc.logging查看某个RegionServer上是否有太多或太多的处理程序,然后跟踪其日志(排队请求消耗内存)。

大型内存机器的配置

HBase提供了一个合理的,保守的配置,可以在几乎所有人们可能想要测试的机器类型上运行。如果你有更大的机器 - HBase有8G或更大的堆 - 你可能会发现下面的配置选项很有帮助。

压缩(Compression)

您应该考虑启用ColumnFamily压缩。有几个选项可以在大多数情况下都是通过减小StoreFiles的大小来提高性能,从而减少I / O。

请参阅“HBase压缩”了解更多信息。

配置WAL文件的大小和数量

在发生RS故障的情况下,HBase使用wal恢复尚未刷新到磁盘的memstore数据。这些WAL文件应该配置为略小于HDFS块(默认情况下,HDFS块为64Mb,WAL文件为〜60Mb)。

HBase也对WAL文件的数量有限制,旨在确保在恢复过程中不会有太多的数据需要重放。这个限制需要根据memstore配置进行设置,以便所有必要的数据都可以适用。建议分配足够多的WAL文件来存储至少那么多的数据(当所有的存储都接近完整时)。例如,对于16Gb RS堆,默认的memstore设置(0.4)和默认的WAL文件大小(〜60Mb),16Gb * 0.4 / 60,WAL文件数的起点为〜109。但是,由于所有的memstores不会一直占满,所以可以分配更少的WAL文件。

管理分割(Splitting)

HBase通常会根据您的hbase-default.xml和hbase-site.xml 配置文件中的设置来处理您所在区域的分割。重要的设置包括:hbase.regionserver.region.split.policy,hbase.hregion.max.filesize,hbase.regionserver.regionSplitLimit。分割的一个简单的观点是,当一个区域发展到hbase.hregion.max.filesize时,它被分割。对于大多数使用模式,您应该使用自动分割。有关手动区域分割的更多信息,请参阅手动区域分割决策。

不要让HBase自动分割你的区域,你可以选择自己管理分割。HBase 0.90.0增加了这个功能。如果你知道你的密钥空间,手动管理分割就行,否则让HBase为你分割。手动分割可以减轻在负载下的区域创建和移动。这也使得区域边界是已知的和不变的(如果你禁用区域分割)。如果使用手动分割,则可以更轻松地进行交错式的基于时间的主要压缩来分散网络IO负载。

禁用自动分割:要禁用自动拆分,可以在集群配置或表配置中设置区域拆分策略:org.apache.hadoop.hbase.regionserver.DisabledRegionSplitPolicy

自动分割建议:如果禁用自动分割来诊断问题或在数据快速增长期间,建议在您的情况变得更加稳定时重新启用它们。

确定预分割区域的最佳数目:

预分割区域的最佳数量取决于您的应用程序和环境。一个好的经验法则是从每个服务器的10个预分割区域开始,随着时间的推移数据不断增长。尽量在区域太少的地方犯错,稍后进行滚动分割更好。区域的最佳数量取决于您所在区域中最大的StoreFile。如果数据量增加,最大的StoreFile的大小将随着时间增加。目标是使最大的区域足够大,压实选择算法仅在定时的主要压实期间将其压缩。否则,该集群可能会同时出现大量压实区域的压实风暴。数据增长导致压缩风暴,而不是人工分割决策,这一点很重要。

如果区域被分割成太多的区域,可以通过配置HConstants.MAJOR_COMPACTION_PERIOD来增加主要的压缩间隔。HBase 0.90引入了org.apache.hadoop.hbase.util.RegionSplitter,它提供所有区域的网络IO安全滚动分割。

管理压缩(Compactions)

默认情况下,主要的压缩计划在7天内运行一次。在HBase 0.96.x之前,默认情况下主要的压缩计划是每天发生一次。

如果您需要精确控制主要压缩的运行时间和频率,可以禁用托管的主要压缩。请参阅“compaction.parameters表中的hbase.hregion.majorcompaction条目”的详细信息。

不禁用主要压缩:对于StoreFile清理来说,重要的压缩是绝对必要的。不要完全禁用它们。您可以通过HBase shell或Admin API手动运行主要压缩。

预测执行(Speculative Execution)

预测执行MapReduce任务是默认开启的,对于HBase集群,通常建议关闭系统级的推测执行,除非您需要在特定情况下可以配置每个作业。将属性 mapreduce.map.speculative 和 mapreduce.reduce.speculative 设置为 false。

其他配置

平衡器(Balancer)

平衡器(Balancer)是在主服务器上运行的一个周期性操作,用于重新分配集群上的区域。它通过hbase.balancer.period配置,默认为300000(5分钟)。

有关LoadBalancer的更多信息,请参阅master.processes.loadbalancer。

禁用Blockcache

不要关闭块缓存(你可以通过设置hfile.block.cache.size为零来实现)。这样做没有好处,因为RegionServer将花费所有的时间一次又一次地加载HFile索引。如果你的工作集是这样配置块缓存,那么没有益处,最少应保证hfile指数保存在块缓存内的大小(你可以通过调查RegionServer UI粗略地了解你需要的大小;请参阅占网页顶部附近的索引块大小)。

Nagle’s或小包装的问题

如果在对HBase的操作中出现大约40ms左右的延迟,请尝试Nagles的设置。例如,请参阅用户邮件列表线程,将缓存设置为1的不一致扫描性能以及其中所引用的设置tcpNoDelay来提高扫描速度的问题。您也可以查看该文档的尾部图表:HBASE-7008 Set扫描缓存到一个更好的默认位置,我们的Lars Hofhansl会尝试使用Nagle打开和关闭测量效果的各种数据大小。

更好的平均恢复时间(MTTR)

这部分是关于在服务器出现故障后会使服务器恢复更快的配置。请参阅Deveraj Das和Nicolas Liochon博客文章:简介HBase平均恢复时间(MTTR)

HBASE-8354强制Namenode使用lease恢复请求循环的问题是混乱的,但在低超时以及如何引起更快的恢复,包括引用添加到HDFS的修复程序方面,有很多好的讨论。下面建议的配置是Varun的建议的提炼和测试,确保你在HDFS版本上运行,所以你有他所提到的修补程序,并且他自己添加到HDFS,帮助HBase MTTR(例如HDFS-3703,HDFS-3712和HDFS-4791 -Hadoop 2确保有他们并且后期Hadoop 1有一些)。在RegionServer中设置以下内容:

<property>
   <name>hbase.lease.recovery.dfs.timeout</name>   
   <value>23000</value>   
   <description>How much time we allow elapse between calls to recover lease.   
   Should be larger than the dfs timeout.</description> 
</property> 
<property>
   <name>dfs.client.socket-timeout</name>   
   <value>10000</value>   
   <description>Down the DFS timeout from 60 to 10 seconds.</description> 
</property>

在NameNode/DataNode端,设置以下内容来启用HDFS-3703,HDFS-3912中引入的“staleness”:

<property>
   <name>dfs.client.socket-timeout</name>   
   <value>10000</value>   
   <description>Down the DFS timeout from 60 to 10 seconds.</description> 
</property> 
<property>
   <name>dfs.datanode.socket.write.timeout</name>   
   <value>10000</value>   
   <description>Down the DFS timeout from 8 * 60 to 10 seconds.</description> 
</property> 
<property>
   <name>ipc.client.connect.timeout</name>   
   <value>3000</value>   
   <description>Down from 60 seconds to 3.</description> 
</property> 
<property>
   <name>ipc.client.connect.max.retries.on.timeouts</name>   
   <value>2</value>   
   <description>Down from 45 seconds to 3 (2 == 3 retries).</description> 
</property> 
<property>
   <name>dfs.namenode.avoid.read.stale.datanode</name>   
   <value>true</value>   
   <description>Enable stale state in hdfs</description> 
</property> 
<property>
   <name>dfs.namenode.stale.datanode.interval</name>   
   <value>20000</value>   
   <description>Down from default 30 seconds</description> 
   </property> 
<property>
   <name>dfs.namenode.avoid.write.stale.datanode</name>   
   <value>true</value>   
   <description>Enable stale state in hdfs</description> 
</property>

JMX

JMX(Java Management Extensions,Java管理扩展)提供了内置的工具,使您能够监视和管理Java VM。要启用远程系统的监视和管理,在启动 Java VM 时,您需要设置系统属性com.sun.management.jmxremote.port(要启用JMX RMI连接的端口号)。从历史上看,除了上面提到的端口之外,JMX还会打开两个附加的随机TCP侦听端口,这可能会导致端口冲突问题。

作为一种替代方法,您可以使用HBase提供的基于协处理器的JMX实现。要在0.99或更高版本中启用它,请在hbase-site.xml中添加以下属性:

<property>
   <name>hbase.coprocessor.regionserver.classes</name>   
   <value>org.apache.hadoop.hbase.JMXListener</value> 
</property>

不要同时为Java VM 设置com.sun.management.jmxremote.port

目前它支持Master和RegionServer Java VM。默认情况下,JMX侦听TCP端口10102,您可以使用以下属性进一步配置端口:

<property>
   <name>regionserver.rmi.registry.port</name>   
   <value>61130</value> 
</property> 
<property>
   <name>regionserver.rmi.connector.port</name>   
   <value>61140</value> 
</property>

在大多数情况下,注册表端口可以与连接器端口共享,所以只需要配置regionserver.rmi.registry.port。但是,如果要使用SSL通信,则必须将2个端口配置为不同的值。

默认情况下,密码认证和SSL通信被禁用。要启用密码验证,您需要像下面那样更新hbase-env.sh:

请参阅$ JRE_HOME/lib/management下面的示例password/access文件。

要使用密码验证启用SSL通信,请按照以下步骤操作:

#1. generate a key pair, stored in myKeyStore 
keytool -genkey -alias jconsole -keystore myKeyStore 
 
#2. export it to file jconsole.cert 
keytool -export -alias jconsole -keystore myKeyStore -file jconsole.cert 
 
#3. copy jconsole.cert to jconsole client machine, import it to jconsole
KeyStore keytool -import -alias jconsole -keystore jconsoleKeyStore -file jconsole.cert

然后像下面这样更新hbase-env.sh:

export HBASE_JMX_BASE="-Dcom.sun.management.jmxremote.ssl=true                         \ 
               -Djavax.net.ssl.keyStore=/home/tianq/myKeyStore                 \                        
               -Djavax.net.ssl.keyStorePassword=your_password_in_step_1       \                        
               -Dcom.sun.management.jmxremote.authenticate=true                \                        
               -Dcom.sun.management.jmxremote.password.file=your_password file \                        
               -Dcom.sun.management.jmxremote.access.file=your_access_file" 
                
export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS $HBASE_JMX_BASE " 
export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS $HBASE_JMX_BASE "

最后,使用密钥存储在客户端上启动 jconsole:

jconsole -J-Djavax.net.ssl.trustStore=/home/tianq/jconsoleKeyStore

要在主服务器上启用HBase JMX实现,还需要在hbase-site.xml中添加以下属性:

<property>
   <name>hbase.coprocessor.master.classes</name>   
   <value>org.apache.hadoop.hbase.JMXListener</value> 
</property>

端口配置的相应属性为:master.rmi.registry.port(默认为10101)和master.rmi.connector.port(默认情况下与registry.port相同)。


HBase 动态配置

从 HBase 1.0.0 版本开始,你可以在不重新启动服务器的情况下更改配置的子集。在 HBase shell 中,有新的操作符,update_config 以及 update_all_config,它们会提示服务器或所有服务器重新加载配置。

当前正在运行的服务器中,只能更改所有配置的子集。以下是这些支持动态更改的配置:

Key
hbase.ipc.server.fallback-to-simple-auth-allowed
hbase.cleaner.scan.dir.concurrent.size
hbase.regionserver.thread.compaction.large
hbase.regionserver.thread.compaction.small
hbase.regionserver.thread.split
hbase.regionserver.throughput.controller
hbase.regionserver.thread.hfilecleaner.throttle
hbase.regionserver.hfilecleaner.large.queue.size
hbase.regionserver.hfilecleaner.small.queue.size
hbase.regionserver.hfilecleaner.large.thread.count
hbase.regionserver.hfilecleaner.small.thread.count
hbase.regionserver.flush.throughput.controller
hbase.hstore.compaction.max.size
hbase.hstore.compaction.max.size.offpeak
hbase.hstore.compaction.min.size
hbase.hstore.compaction.min
hbase.hstore.compaction.max
hbase.hstore.compaction.ratio
hbase.hstore.compaction.ratio.offpeak
hbase.regionserver.thread.compaction.throttle
hbase.hregion.majorcompaction
hbase.hregion.majorcompaction.jitter
hbase.hstore.min.locality.to.skip.major.compact
hbase.hstore.compaction.date.tiered.max.storefile.age.millis
hbase.hstore.compaction.date.tiered.incoming.window.min
hbase.hstore.compaction.date.tiered.window.policy.class
hbase.hstore.compaction.date.tiered.single.output.for.minor.compaction
hbase.hstore.compaction.date.tiered.window.factory.class
hbase.offpeak.start.hour
hbase.offpeak.end.hour
hbase.oldwals.cleaner.thread.size
hbase.procedure.worker.keep.alive.time.msec
hbase.procedure.worker.add.stuck.percentage
hbase.procedure.worker.monitor.interval.msec
hbase.procedure.worker.stuck.threshold.msec
hbase.regions.slop
hbase.regions.overallSlop
hbase.balancer.tablesOnMaster
hbase.balancer.tablesOnMaster.systemTablesOnly
hbase.util.ip.to.rack.determiner
hbase.ipc.server.max.callqueue.length
hbase.ipc.server.priority.max.callqueue.length
hbase.ipc.server.callqueue.type
hbase.ipc.server.callqueue.codel.target.delay
hbase.ipc.server.callqueue.codel.interval
hbase.ipc.server.callqueue.codel.lifo.threshold
hbase.master.balancer.stochastic.maxSteps
hbase.master.balancer.stochastic.stepsPerRegion
hbase.master.balancer.stochastic.maxRunningTime
hbase.master.balancer.stochastic.runMaxSteps
hbase.master.balancer.stochastic.numRegionLoadsToRemember
hbase.master.loadbalance.bytable
hbase.master.balancer.stochastic.minCostNeedBalance
hbase.master.balancer.stochastic.localityCost
hbase.master.balancer.stochastic.rackLocalityCost
hbase.master.balancer.stochastic.readRequestCost
hbase.master.balancer.stochastic.writeRequestCost
hbase.master.balancer.stochastic.memstoreSizeCost
hbase.master.balancer.stochastic.storefileSizeCost
hbase.master.balancer.stochastic.regionReplicaHostCostKey
hbase.master.balancer.stochastic.regionReplicaRackCostKey
hbase.master.balancer.stochastic.regionCountCost
hbase.master.balancer.stochastic.primaryRegionCountCost
hbase.master.balancer.stochastic.moveCost
hbase.master.balancer.stochastic.maxMovePercent
hbase.master.balancer.stochastic.tableSkewCost

HBase 版本号和兼容性

HBase 有两种版本控制方案,分别是:pre-1.0 和 post-1.0。在本节内容中将作出详细的说明。

HBase post-1.0

从 1.0.0 版本开始,HBase 正在致力于 Semantic Versioning 的发布版本。综上所述:

对于给定的版本号 MAJOR.MINOR.PATCH,增加如下内容:

  • MAJOR 版本,当你进行不兼容的 API 更改时
  • MINOR 版本,当您以向后兼容的方式添加功能时
  • PATCH 版本,当您进行向后兼容的错误修复时
  • 预发布和构建元数据的其他标签可作为MAJOR.MINOR.PATCH格式的扩展。

兼容性维度:

除了通常的 API 版本考虑之外,HBase 还有其他需要考虑的兼容性维度。

Client-Server 线协议兼容性:

  • 允许不同步更新客户端和服务器。
  • 我们只能允许先升级服务器。也就是说,服务器将向后兼容旧客户端,这样新的 API 就可以使用。
  • 示例:用户应该能够使用旧客户端连接到升级的群集。

Server-Server 协议兼容性:

  • 不同版本的服务器可以共存于同一个群集中。
  • 服务器之间的有线协议是兼容的。
  • 分布式任务的工作人员(如复制和日志拆分)可以共存于同一个群集中。
  • 相关协议(如使用ZK进行协调)也不会改变。
  • 示例:用户可以执行滚动升级。

文件格式兼容性:

  • 支持文件格式向前和向后兼容
  • 示例:文件、ZK 编码、目录布局自动升级为 HBase 升级的一部分。用户可以降级到旧版本,并且一切都将继续工作。

客户端 API 兼容性:

  • 允许更改或删除现有的客户端 API。
  • 在我们更改/删除主要版本之前,API 需要被弃用。
  • 修补程序(patch)版本中提供的 API 将在所有后续修补程序版本中提供。但是,可能会添加新的 API,这些 API 在以前的修补程序版本中将不可用。
  • 修补程序版本中引入的新 API 只能以源代码兼容的方式添加:即实现公共 API 的代码将继续编译。示例:使用新废用的 API 的用户不需要使用 HBase API 调用修改应用程序代码,直到下一个主要版本。

客户端二进制兼容性:

  • 写入给定修补程序版本中提供的 API 的客户端代码可以运行不变(不需要重新编译),以抵补新的 jar 后续补丁版本。

  • 写入给定修补程序版本中提供的 API 的客户端代码可能无法针对早期修补程序版本中的旧 jar 运行。示例:旧编译的客户端代码将在 jar 中保持不变。

  • 如果客户端实现 HBase 接口,则可能需要重新编译升级到较新的次要(minor)版本。服务器端有限的 API 兼容性(取自 Hadoop):

  • 内部API被标记为“稳定(Stable)”,“正在发展(Evolving)”或“不稳定(Unstable)”。

  • 这意味着协处理器和插件(可插入类,包括复制)的二进制兼容性,只要这些只使用标记的接口/类。

  • 例如:旧编译的协处理器,过滤器或插件代码将在新 jar 中保持不变。

相关性兼容性:

  • HBase 的升级不需要依赖项目的兼容升级,包括运行 Java 时。
  • 示例:Hadoop 的升级不会使我们所做的任何兼容性保证失效。

操作兼容性:

  • 度量标准的更改
  • 服务的行为变化
  • 通过 /jmx/ 端点公开的 JMX API

概要

  • 修补程序(patch)升级是一种直接替代方案。任何不是 Java 二进制和源代码兼容的更改都将不被允许。在修补程序版本中降级版本可能不兼容。
  • 次要(minor)升级不需要修改应用程序/客户端代码。理想情况下,这将是一个直接替换,但如果使用新的 jar,则客户端代码,协处理器,过滤器等可能必须重新编译。
  • 主要(major)升级允许 HBase 做出重大改变。

以下是兼容性矩阵列表:

企业微信截图_69fa3ca1-792f-4d29-8eac-19570f059ff5

HBase 有很多 API 要点,但对于上面的兼容性矩阵,我们区分了Client API(客户端 API),Limited Private API(有限的私有 API)和 Private API(私有 API)。

  • InterfaceAudience(javadocs):捕捉预期的受众,可能的值包括:
    • Public:对于最终用户和外部项目是安全的;
    • LimitedPrivate:用于我们期望可插入的内部组件,如协处理器;
    • Private:严格用于 HBase 自身内部定义为 IA 的类中,Private 可以用作声明 IA.LimitedPrivate 接口的参数或返回值。将IA.Private对象视为不透明;不要尝试直接访问其方法或字段。
  • InterfaceStability(javadocs):描述允许接口更改的类型。可能的值包括:
    • Stable:接口是固定的,预计不会改变;
    • Evolving:界面可能会在未来的minor 版本中改变;
    • Unstable:界面可能随时更改

请记住 HBase 项目中 InterfaceAudience 注释和 InterfaceStability 注释之间的以下相互作用:

  • IA.Public 类本质上是稳定的,并坚持我们有关升级类型(主要,次要或修补程序)的稳定性保证。
  • IA.LimitedPrivate 类应始终使用给定的 InterfaceStability 值的其中一个进行注释。如果他们不是,你应该假定他们是 IS.Unstable。
  • IA.Private 类应该被认为是隐含不稳定的,不能保证发布之间的稳定性。

HBase 客户端 API

HBase 客户端 API 由所有标记有 InterfaceAudience.Public 接口的类或方法组成。hbase-client 和依赖模块中的所有主类都有InterfaceAudience.Public,InterfaceAudience.LimitedPrivate或InterfaceAudience.Private标记。并非所有其他模块(hbase-server等)中的类都有标记。如果一个类没有使用上述中的一个注释,则它被认为是一个InterfaceAudience.Private类。

HBase Limited Private API

LimitedPrivate 注释为接口附带了一组目标使用者。这些使用者是协处理器,phoenix,复制端点实现等。此时,HBase 只能保证修补程序版本之间的这些接口的源和二进制兼容性。

HBase Private API

所有使用InterfaceAudience.Private注释的类或没有注释的所有类仅在HBase内部使用。接口和方法签名可以随时改变。如果您依赖于标记为Private的特定界面,则应打开jira以建议将界面更改为Public或LimitedPrivate,或者为此目的公开的接口。

HBase Pre 1.0

HBase Pre-1.0 版本都是 EOM:对于新的安装,请勿部署:0.94.y、0.96.y 或 0.98.y,应该部署稳定的版本。 

在语义版本化方案 pre-1.0 之前,HBase 追随 Hadoop 的 0.2x 或 0.9x 版本。 

二进制兼容性:

当我们说两个 HBase 版本是兼容的时,我们的意思是这些版本是线(wire)和二进制兼容的。兼容的HBase版本意味着客户可以与兼容但不同版本的服务器通话。这也意味着你可以换出一个版本的 jar,并用另一个兼容版本的 jar 替换它们,所有的 jar 都可以工作。除非另有说明,否则 HBase 主要的版本都是二进制兼容的。您可以安全地在二进制兼容版本之间进行滚动升级。

滚动升级

滚动升级是您一次更新服务器群集中的服务器的过程。如果它们是二进制或线路兼容的,则可以跨 HBase 版本进行滚动升级。粗略地说,滚动升级是正常地停止每台服务器,更新软件,然后重新启动。您可以为集群中的每个服务器执行此操作。通常先升级 Master,然后再升级 RegionServers。 

例如,下面的 HBase 是 symlinked 实际的 HBase 安装。在升级之前,在群集上运行滚动重启之前,我们将 symlink 更改为指向新的 HBase 软件版本,然后运行:

$ HADOOP_HOME=~/hadoop-2.6.0-CRC-SNAPSHOT ~/hbase/bin/rolling-restart.sh --config ~/conf_hbase

滚动重新启动脚本将首先正常停止并重新启动主服务器,然后依次重新启动每个 RegionServer。由于 symlink 被更改,所以重新启动时,服务器将使用新的HBase 版本。随着滚动升级的进行,检查日志中是否有错误。 

在兼容二进制/Wire的版本之间进行滚动升级:

除非另有说明,否则 HBase 指向的版本是二进制兼容的。您可以在 HBase 主要版本之间进行滚动升级。例如,您可以通过在集群中进行滚动升级,使用0.94.6二进制文件替换0.94.5二进制文件,从而从 0.94.5 转到 0.94.6。

在次要(minor)版本中,我们调用的版本是有线/协议兼容的,在这种情况下,也可以执行滚动升级。例如,在从 0.98.x 升级到 HBase 1.0.0 时,我们声明可以在 hbase-0.98.x 和 hbase-1.0.0 之间进行滚动升级。


HBase 回滚:版本恢复

HBase回滚

当你在试着升级 HBase 的时候,你可能会遇到升级失败的问题,并且想要将其恢复成之前的版本。本节就介绍如何执行回滚以将 HBase 恢复为到较早的版本。请注意,这应该只在主要版本和一些次要版本之间需要。您应该始终能够在相同次要版本的 HBase Patch 版本之间进行降级。这些说明可能要求您在开始升级过程之前注意相关的事项,因此请务必事先阅读本节。 

HBase回滚注意事项

回滚与降级:

本节介绍如何对 HBase 次要版本和主要版本之间的升级执行回滚。在本文档中,回滚指的是采取升级后的集群并将其恢复到旧版本的过程,同时丢失升级后发生的所有更改。相比之下,群集降级会将升级后的群集恢复到旧版本,同时保留升级后写入的任何数据。我们目前仅提供回滚 HBase 集群的说明。此外,只有在执行升级之前遵循这些说明,回滚才有效。 

当这些指令谈论回滚与降级的先决条件群集服务(即HDFS)时,您应该将服务版本与退化的降级案例视为相同。

复制:

除非您正在执行全部服务回滚,否则 HBase 群集将会丢失任何配置的对等 HBase 复制。如果您的集群配置为 HBase 复制,那么在按照这些说明进行操作之前,您应该记录所有复制节点。执行回滚之后,您应该将每个记录的对等点添加回群集。另外要注意,自升级后写入群集的数据可能已经或可能未被复制到任何对等方。 

数据地点:

除非您正在执行全部服务回滚,否则通过回滚过程可能会破坏Region Server的所有局部位置。在群集有时间通过紧凑排列恢复数据位置之前,您应该期望性能的降级。或者,您可以强制压缩来加速此过程,但要以生成群集负载为代价。

可配置的位置:

以下说明假设 HBase 数据目录和 HBase znode 的默认位置。这两个位置都是可配置的,您应该在继续操作之前验证群集中使用的值。如果您有不同的值,只需将默认值替换为在配置中找到的 HBase 数据目录,它是通过密钥 “HBase” (rootdir) 配置的,并且具有默认的 “/HBase”。* HBase znode通过密钥’zookeeper.znode.parent’进行配置,默认值为’/ hbase’。 

所有服务回滚

如果您要执行 HDFS 和 ZooKeeper 服务的回滚,那么 HBase 的数据将在此过程中回滚。

要求

能够回滚 HDFS 和 ZooKeeper

升级前

在升级前不需要额外的步骤。作为一项额外的预防措施,您可能希望使用 distcp 将 HBase 数据备份到要升级的群集之外。为此,请本节内容中的按照“HDFS降级后回滚”的“升级前”部分中的步骤操作,但它是复制到另一个 HDFS 实例,而不是在同一实例中。

执行回滚

  1. 停止 HBase
  2. 执行 HDFS 和 ZooKeeper 的回滚(HBase 应该保持停止状态)
  3. 将安装的 HBase 版本更改为以前的版本
  4. 启动 HBase
  5. 验证 HBase 内容 - 使用 HBase shell 列出表格并扫描一些已知值。

HDFS 回滚和 ZooKeeper 降级后回滚

如果您将回滚 HDFS,但通过 ZooKeeper 降级,那么 HBase 将处于不一致的状态。在完成此过程之前,您必须确保集群未启动。

要求

能够回滚 HDFS

能够降级 ZooKeeper

升级前

在升级前不需要额外的步骤。作为一种额外的预防措施,您可能希望使用 distcp 将 HBase 数据备份到要升级的群集之外。为此,请本节内容中的按照“HDFS降级后回滚”的“升级前”部分中的步骤操作,但它将复制到另一个HDFS实例,而不是在同一实例中。

执行回滚

1.停止 HBase

2.执行 HDFS 回滚和 ZooKeeper 降级(HBase 应该保持停止状态)

3.将安装的 HBase 版本更改为以前的版本

4.清除与 HBase 相关的 ZooKeeper 信息。警告:此步骤将永久销毁所有复制对等点。清理 ZooKeeper 中的 HBase 信息:

[hpnewton@gateway_node.example.com ~]$ zookeeper-client -server 
zookeeper1.example.com:2181,zookeeper2.example.com:2181,zookeeper3.example.com:2181 
Welcome to ZooKeeper! 
JLine support is disabled 
rmr /hbase 
quit 
Quitting...

5.启动 HBase

6.验证 HBase 内容 - 使用 HBase shell 列出表格并扫描一些已知值。

HDFS 降级后回滚

如果您要执行 HDFS 降级,则无论ZooKeeper是否通过回滚、降级或重新安装,您都需要遵循这些指示信息。 

要求

可以降级 HDFS

升级前群集必须能够运行 MapReduce 作业

HDFS 超级用户访问

在 HDFS 中至少有两个 HBase 数据目录的副本空间

升级前

在开始升级过程之前,您必须对 HBase 的支持数据进行完整备份。以下说明介绍了在当前HDFS实例中备份数据的过程。或者,您可以使用 distcp 命令将数据复制到另一个 HDFS 群集。 

1.停止 HBase 群集

2.将 HBase 数据目录复制到备份位置, 方法是使用 distcp 命令作为 HDFS 超级用户 (下面显示在启用安全的群集上);
使用distcp备份HBase数据目录:

[hpnewton@gateway_node.example.com ~]$ kinit -k -t hdfs.keytab hdfs@EXAMPLE.COM 
[hpnewton@gateway_node.example.com ~]$ hadoop distcp /hbase /hbase-pre-upgrade-backup

3.Distcp 将启动一个 mapreduce 作业来处理以分布式方式复制文件。检查 distcp 命令的输出,以确保此作业成功完成。

执行回滚

1.停止 HBase

2.执行 HDFS 的降级和 ZooKeeper 的降级/回滚(HBase 应该保持停止状态)

3.将安装的 HBase 版本更改为以前的版本

4.将 HBase 数据目录从升级前恢复为 HDFS 超级用户 (如下所示在启用安全的群集上)。如果您将数据备份到另一个 HDFS 群集而不是本地,则需要使用distcp 命令将其复制回当前的 HDFS 群集。
恢复 HBase 数据目录:

[hpnewton@gateway_node.example.com ~]$ kinit -k -t hdfs.keytab hdfs@EXAMPLE.COM 
[hpnewton@gateway_node.example.com ~]$ hdfs dfs -mv /hbase /hbase-upgrade-rollback 
[hpnewton@gateway_node.example.com ~]$ hdfs dfs -mv /hbase-pre-upgrade-backup /hbase

5.清除与 HBase 相关的 ZooKeeper 信息。警告:此步骤将永久销毁所有复制对等点。
清理 ZooKeeper 中的 HBase 信息:

[hpnewton@gateway_node.example.com ~]$ zookeeper-client -server 
zookeeper1.example.com:2181,zookeeper2.example.com:2181,zookeeper3.example.com:2181 
Welcome to ZooKeeper! 
JLine support is disabled 
rmr /hbase 
quit 
Quitting...

6.启动 HBase

7.验证 HBase 内容 - 使用 HBase shell 列出表格并扫描一些已知值。


HBase 升级路径

HBase:从 0.98.x 升级到 1.x

在本节中,首先,你需要注意 1.0.0 版本以上的 HBase 做出了重大的更改,所以在继续升级过程前,你应该仔细阅读这些重要的更改部分,以免发生意外。

HBase 1.0.0+ 重要更改部分:

在这里,我们列出了自 0.98.x 版本之后的 1.0.0 以上版本的重要更改,您应该知道这些更改会在升级后生效。

  • HBase 1.0.0+ 中 ZooKeeper 3.4 是必需的。
  • HBase 默认端口已更改:HBase使用的端口已更改。他们曾经是在600XX范围内。在HBase 1.0.0中,它们已经从临时端口范围中移出,并且是160XX(主 Web UI 为 60010,现在为16010; RegionServer Web UI 为 60030,现在为16030等)。如果要保留旧的端口位置,请将hbase-default.xml中的端口设置配置复制到hbase-site.xml中,将它们更改回 HBase 0.98.x 版本的旧值,并确保在重新启动之前已分发了配置。 
  • HBase 主端口绑定更改:在 HBase 1.0.x 中,HBase Master绑定RegionServer端口以及主端口。此行为从1.0之前的 HBase 版本更改。在 HBase 1.1 和 2.0 分支中,此行为将恢复为 HBase 主服务器未绑定RegionServer端口的 1.0 行为。 
  • hbase.bucketcache.percentage.in.combinedcache 配置已被删除:
    如果您正在使用BucketCache,则可能已使用此配置。如果不使用 BucketCache,则此更改不会影响您。它的移除意味着您的 L1 LruBlockCache 现在使用 hfile.block.cache.size 来调整大小,即,如果您不在执行 BucketCache,您可以调整堆上 L1 LruBlockCache 的大小 - 并且 BucketCache 大小不适用于该 hbase.bucketcache.size 设置。您可能需要调整 configs 以将 LruBlockCache 和 BucketCache 大小设置为 0.98.x 和之前的大小。如果你没有设置这个配置,它的默认值是 0.9。如果你什么都不做,你的 BucketCache 将会增加10%。您的 L1 LruBlockCache 将成为 java 堆大小的 hfile.block.cache.size 倍(hfile.block.cache.size 是 0.0 到 1.0 之间的浮点数)。

HBase:从 0.96.x 升级到 0.98.x

HBase 从 0.96.x 到 0.98.x 的滚动升级工作。这两个版本不是二进制兼容的。 

需要执行其他步骤才能利用 0.98.x 的一些新功能,包括单元可见性标签,单元 ACL 和透明服务器端加密。有关更多信息,请参阅保护 Apache HBase。显着的性能改进包括对提前写日志线程模型的更改,它在高负载、反向扫描仪、MapReduce 快照文件和带区压缩的情况下提供更高的事务吞吐量。

客户端和服务器可以运行 0.98.x 和 0.96.x 版本。但是,由于 Java API 中的更改,应用程序可能需要重新编译。

HBase:从 0.94.x 升级到 0.98.x

HBase 从 0.94.x 直接到 0.98.x 的滚动升级不起作用。升级路径遵循与从 0.94.x 升级到 0.96.x 相同的过程。需要额外的步骤才能使用 0.98.x 的一些新功能。 

HBase:从 0.94.x 升级到 0.96.x

Singularity

您必须完全停止旧版本的 0.94.x 群集才能进行升级。如果您正在群集之间进行复制,则两个群集都必须进行升级。请确保它完全处于关机状态。WAL 文件越少,升级运行的速度就越快(升级将在文件系统中找到的所有日志文件都分解为升级过程的一部分)。所有客户端也必须升级到 0.96。

API 已经改变。您需要重新编译 0.96 的代码,您可能需要调整应用程序以适应新的 API(TODO:更改列表)。

执行 0.96 升级

在升级过程中,HDFS 和 ZooKeeper 必须启动并运行!

HBase 0.96.0 附带升级脚本,请运行:

$ bin/hbase upgrade

以查看其用法。该升级脚本有两种主要模式:check 和 execute。 

**check **

检查(check)步骤针对正在运行的 0.94 群集运行。从下载的 0.96.x 二进制文件运行它。检查步骤正在寻找 HFile v1 文件的存在。这些在 HBase 0.96.0 中不受支持。要让它们重写为 HFile v2,您必须运行压缩。

检查步骤在其运行结束时打印统计数据(在日志中 grep 用于 “Result:”),打印其扫描的表的绝对路径、找到的任何 HFile v1 文件、包含所述文件的区域(这些区域将需要大的压缩)以及任何如果找到损坏的文件。一个损坏的文件是不可读的,所以未定义(HFile v1 和 HFile v2 都没有)。

要运行检查步骤,请运行:

$ bin/hbase upgrade -check

这里是示例输出:

Tables Processed: 
hdfs://localhost:41020/myHBase/.META. 
hdfs://localhost:41020/myHBase/usertable 
hdfs://localhost:41020/myHBase/TestTable 
hdfs://localhost:41020/myHBase/t 
 
Count of HFileV1: 2 
HFileV1: 
hdfs://localhost:41020/myHBase/usertable    
/fa02dac1f38d03577bd0f7e666f12812/family/249450144068442524 
hdfs://localhost:41020/myHBase/usertable    
/ecdd3eaee2d2fcf8184ac025555bb2af/family/249450144068442512 
 
Count of corrupted files: 1 
Corrupted Files: 
hdfs://localhost:41020/myHBase/usertable/fa02dac1f38d03577bd0f7e666f12812/family/1 
Count of Regions with HFileV1: 2 
Regions to Major Compact: 
hdfs://localhost:41020/myHBase/usertable/fa02dac1f38d03577bd0f7e666f12812 
hdfs://localhost:41020/myHBase/usertable/ecdd3eaee2d2fcf8184ac025555bb2af 
 
There are some HFileV1, or corrupt files (files with incorrect major version)

在上面的示例输出中,两个区域中有两个 HFile v1 文件和一个损坏的文件,应该删除损坏的文件。具有 HFile v1 的地区需要进行大规模压缩。为了紧凑,请启动hbase shell 并查看如何压缩单个区域。完成主要压缩后,重新运行检查步骤,并且 HFile v1 文件应该消失,替换为 HFile v2 实例。 

默认情况下,检查步骤将扫描 HBase 根目录(在配置中定义为 hbase.rootdir)。要仅扫描特定目录,请传递 dir 选项。

$ bin/hbase upgrade -check -dir /myHBase/testTable

上述命令将检测 /myHBase/testTable 目录中的 HFile v1 文件。

一旦检查步骤报告所有 HFile v1 文件已被重写,则继续进行升级是安全的。

**execute **

在检查步骤显示群集没有 HFile v1 后,继续升级是安全的。接下来是执行(execute)步骤。在执行 execute 步骤之前,您必须关闭您的 0.94.x CLUSTER。如果检测到正在运行的 HBase 主服务器或 RegionServer,则 execute 步骤将不会运行。 

在升级过程中,HDFS 和 ZooKeeper 应该启动并运行。如果 zookeeper 由 HBase 管理,那么您可以启动 zookeeper,以便通过运行升级:

执行升级步骤由三个子步骤组成。 

  • 命名空间:HBase 0.96.0 支持命名空间。升级需要重新排序文件系统中的目录以使命名空间正常工作。- ZNodes:清除所有 znode,以便可以使用新的 protobuf’ed 格式将新的 znode 写入其位置,并且可以将一些 znode 迁移到适当位置:例如复制和表状态znodes- WAL 日志分割:如果 0.94.x 集群没有完全关闭,我们将在0.96.0 启动之前将 WAL 日志分割为迁移的一部分。这个 WAL 分割比本地分布式 WAL 分割运行速度慢,因为它全部在单个升级过程中。
    ZNodes:清除所有 znode,以便可以使用新的 protobuf’ed 格式将新的 znode 写入其位置,并且可以将一些 znode 迁移到适当位置:例如复制和表状态znodes

要运行执行步骤,请确保首先在服务器和客户端的各处复制了 HBase 0.96.0 二进制文件。确保 0.94.0 群集已关闭。然后执行如下操作:

以下是一些示例输出:

如果执行步骤的输出看起来不错,请停止开始执行升级的zookeeper实例:

然后就可以启动 hbase-0.96.0。

故障排除

旧客户端连接到0.96群集

出现如下的异常,升级过程将会失败:

升级 META 以使用 Protocol Buffers(Protobuf)

HBase 从 0.96 之前的版本升级时,META 需要转换为使用协议缓冲区(Protobuf)。这是由配置选项 hbase.MetaMigrationConvertingToPB 控制,它在默认情况下被设置为 true。因此,默认情况下,您不需要采取任何措施。 

迁移是一次性事件。但是,每次启动群集时,META 都会进行扫描以确保不需要转换。如果您的区域数量非常多,则此扫描可能需要很长时间。在 0.98.5 开始,您可以在 HBase的-site.xml 中设置 hbase.MetaMigrationConvertingToPB 为 false ,以禁用此启动扫描。

HBase:从 0.92.x 升级到 0.94.x

我们曾经认为 HBase 的 0.92 版本和 0.94 版本是接口兼容的,您可以在这些版本之间进行滚动升级,但是后来我们发现 HColumnDescriptor 中的HBASE-5357 Use builder 模式更改了方法签名,不是返回 void,而是返回 HColumnDescriptor。这将抛出 java.lang.NoSuchMethodError: org.apache.hadoop.hbase.HColumnDescriptor.setMaxVersions(I)V,因此 0.92 和 0.94 不兼容,你不能在它们之间进行滚动升级。 

HBase:从 0.90.x 升级到 0.92.x

升级指南

您会发现 0.92.0 与 0.90.x 版本稍有不同,这里有一些需要注意的事项。

这些是升级前需要了解的重要内容: 

  • 默认情况下 MSLAB 处于开启状态。如果您有很多区域,请观看该堆的使用情况。 
    - 默认情况下,分布式日志分割处于开启状态。它应该使 RegionServer 故障转移更快。 
    - 有一个单独的包安全。 
    - 如果 -XX: MaxDirectMemorySize 是设置在您的 hbase. sh,它将启用实验性的离堆缓存 (您可能不希望这样)。
    默认情况下,分布式日志分割处于开启状态。它应该使 RegionServer 故障转移更快。 

如果 -XX: MaxDirectMemorySize 是设置在您的 hbase. sh,它将启用实验性的离堆缓存 (您可能不希望这样)。

不可回退:

要移动到 0.92.0,你只需关闭群集,将 HBase 0.90.x 替换为 HBase 0.92.0 二进制文件(确保清除所有 0.90.x 实例)并重新启动(不能从 0.90.x 到 0.92.x 重新启动,必须重新启动)。在启动时,.META. 表格内容被重写,从 info:regioninfo 列中移除表格模式。此外,首次启动后完成的任何刷新都将以新的0.92.0 文件格式(带有内嵌块(版本2)的 HBase 文件格式)写入数据。这意味着一旦您在 HBase 数据目录中启动了 HBase 0.92.0,您就无法回到 0.90.x。

**MSLAB 默认为开启: **

在 0.92.0 中,该 hbase.hregion.memstore.mslab.enabled 标志被设置为 true。在 0.90.x 中是 false。启用它时,即使内存存储为零或仅包含一些小元素,memstores 也会逐步为 MSLAB 2MB 块分配内存。这通常很好,但是如果您在 0.90.x 群集中每个 RegionServer 有很多区域(并且 MSLAB 已关闭),则可能会发现自己升级时出现 OOME,因为 thousands of regions * number of column families * 2MB MSLAB(至少)将堆放在顶部。设置hbase.hregion.memstore.mslab.enabled 为 false 或将 hbase.hregion.memstore.mslab.chunksize 设置为小于2MB 的 MSLAB 大小。

分布式日志分割处于默认状态:

此前,WAL 日志崩溃是由 Master 单独分割的。在 0.92.0 中,日志分割由群集完成。这应该大大减少分割日志和使区域重新联机所需的时间。 

内存计算改变:

在 0.92.0 中,包含嵌入块(版本2)索引和 bloom 过滤器的 HBase 文件格式占用了来自文件系统的相同 LRU 使用的高速缓存块。在 0.90.x 版本中,HFile v1 指数位于 LRU 之外,因此即使索引位于没有被使用的文件中,也会占用空间。利用 LRU 中的索引,你可能会发现块缓存的空间较少。相应地调整块缓存。块大小的默认大小已经从0.22.0(堆的20%)改变为0.25。 

可用的 Hadoop 版本:

在 Hadoop 1.0.x(或 CDH3u3)上运行 0.92.0。性能优势值得推动。否则,我们的 Hadoop 处方就像以前一样;您需要一个支持工作同步的 Hadoop。 

如果在 Hadoop 1.0.x(或 CDH3u3)上运行,请启用本地读取。

HBase 0.92.0 附带 ZooKeeper 3.4.2:

如果可以的话,升级你的 ZooKeeper。如果你不能,3.4.2 客户端应该与 3.3.X 集成(HBase 使用 3.4.2 API)进行工作。

联机更改默认为关闭状态:

在 0.92.0 中,我们添加了一个实验性在线模式更改设施。它在默认情况下是关闭的。您自担风险启用它。联机修改和分割表格不能很好地协同工作,所以请确保您的群集静态使用此功能(现在)。 

WebUI:

网络用户界面(web UI)在 0.92.0 中添加了一些附加功能。它显示当前正在转换的区域的列表,最近的压缩/刷新和正在运行的进程的进程列表(如果一切正常并且请求正在及时处理,通常是空的)。其他添加内容包括按区域请求、调试 servlet 转储等。 

安全 tarball:

我们现在运送两个 tarballs:安全和不安全的 HBase。

HBase复制的变化:

0.92.0 增加了两个新功能:multi-slave 复制和 multi-master 复制。启用它的方式与添加新的对等方式相同,因此为了拥有 multi-master,您只需运行 add_peer,就可以为每个群集充当其他从属群集的主节点。冲突是在时间戳级别处理的,这可能是也可能不是您想要的,因此需要在每个用例基础上对其进行评估。复制在 0.92 仍然是实验性的,默认情况下是禁用的,运行需要您自担风险。 

如果 OOME,RegionServer 现在会中止:

如果一个 OOME,我们现在有 JVM kill RegionServer 进程,所以它快速下降。之前,RegionServer 可能会在受伤的状态下徘徊一段时间后停滞。要禁用此功能,并建议您将其保留原位,则需要编辑 bin/hbase 文件。 

HFile v2 和“更大,更少”的趋势:

0.92.0 以新格式存储数据,HBase 文件格式包含内嵌块(版本2)。随着 HBase 的运行,它会将您的所有数据从 HFile v1 移至 HFile v2 格式。此自动迁移将在刷新和紧凑排列运行时在后台运行。HFile v2 允许 HBase 运行更大的区域/文件。事实上,我们鼓励所有前进的 HBase 都倾向于 Facebook axiom #1,运行时区域更大,区域更少。如果你现在有很多区域 - 每个主机超过100个 - 你应该考虑在你移动到 0.92.0(在 0.92.0,默认大小现在是 1G,从 256M 开始)之后设置你的区域大小,然后运行在线合并工具。 

HBase:从 0.20.x 或 0.89.x 升级到 HBase 0.90.x

此版本的 0.90.x HBase 可以在 HBase 0.20.x 或 HBase 0.89.x 写入的数据上启动。不需要迁移步骤。HBase 0.89.x 和 0.90.x 以不同的方式地写出了区域目录的名称,它们用区域名称的 md5 哈希来命名,而不是 jenkins 哈希,所以这意味着一旦启动,就不会返回到 HBase 0.20 。X。 

确保在升级时从 conf 目录中删除 hbase-default.xml。此文件的 0.20.x 版本将具有用于 0.90.x HBase 的子优化配置。在 HBase 的 -default.xml 文件中现在被捆绑到 HBase jar 上进行读取。如果您想查看此文件的内容,请在:src/main/resources/hbase-default.xml 的 src 树中查看它,或者参阅 HBase 默认配置。

最后,如果从 0.20.x 升级,请检查您的 shell 中的 .META 模式。在过去,我们会建议用户使用 16kb 的 MEMSTORE_FLUSHSIZE,在 shell 中运行:

这将输出当前 .META. 模式。检查 MEMSTORE_FLUSHSIZE 大小。它是 16kb(16384)吗?如果是的话,你需要修改它(默认的值是 64MB (67108864)) 运行脚本bin/set_meta_memstore_size.rb,这个脚本会修改.META.schema。如果不运行的话,集群会比较慢。



使用Apache HBase Shell

Apache HBase Shell 是在(J)Ruby 的 IRB 的基础上增加了一些 HBase 特定的命令。你可以在 IRB 中做的任何事情,都可以在 HBase Shell 中完成。

Apache HBase Shell 是在(J)Ruby 的 IRB 的基础上增加了一些 HBase 特定的命令。你可以在 IRB 中做的任何事情,都可以在 HBase Shell 中完成。

要运行 HBase shell,请执行如下操作:

用Ruby编写脚本

有关脚本编写 Apache HBase 的示例,请查看 HBase bin 目录;查看以* .rb结尾的文件,要运行这些文件之一,请执行如下操作:

HBase Shell(HBASE-11658)添加了一种新的非交互模式。非交互模式捕获 HBase Shell 命令的退出状态(成功或失败),并将该状态返回给命令解释器。如果您使用正常的交互模式,HBase Shell 将只会返回自己的退出状态,这几乎总是会0成功的。

要调用非交互模式,请将 -n 或 --non-interactive 选项传递给 HBase Shell。

OS脚本中的HBase Shell

您可以在操作系统脚本解释器中使用 HBase shell,例如 Bash shell,它是大多数 Linux 和 UNIX 发行版的默认命令解释程序。以下准则使用 Bash 语法,但可以调整为使用 C 样式的 shell(例如 csh 或 tcsh),并且可能会修改为使用 Microsoft Windows 脚本解释器一起使用。

注意:以这种方式生成 HBase Shell 命令的速度很慢,所以在决定何时将 HBase 操作与操作系统命令行相结合时,请记住这一点。

示例——将命令传递给 HBase Shell

您可以使用 echo 命令和 |(管道)操作,以非交互模式将命令传递到 HBase Shell。一定要转义 HBase 命令中的字符,否则 shell 将会解释这些字符。一些调试级别的输出已从下面的示例中截断。

若要取消所有输出,请将其回显到 /dev/null:

示例8——检查脚本命令的结果

由于脚本不是设计为交互式运行的,因此您需要一种方法来检查命令是失败还是成功。HBase shell 使用为成功的命令返回值0的标准约定,并为失败的命令返回一些非零值。Bash 将命令的返回值存储在一个名为 $? 的特殊环境变量中。因为每次 shell 运行任何命令时都会覆盖该变量,所以应该将结果存储在另一个脚本定义的变量中。

下面的这个脚本展示了一种方法来存储返回值并根据它做出决定:

在脚本中检查成功或失败

获取退出代码0意味着您脚本编写的命令确实成功了。但是,获取非零退出代码并不一定意味着命令失败。该命令可能已成功,但客户端失去连接,或者其他事件阻碍了其成功。这是因为 RPC 命令是无状态的。确保操作状态的唯一方法是检查。例如,如果你的脚本创建一个表,但返回一个非零的退出值,你应该检查表是否实际创建,然后再试图创建它。

从命令文件读取HBase Shell命令

您可以将 HBase Shell 命令输入到文本文件中,每行一个命令,并将该文件传递给HBase Shell。

示例9——命令文件示例

将命令文件的路径作为 hbase shell 命令的唯一参数传递。每个命令都会执行并显示其输出。如果您未在脚本中包含该 exit 命令,则会返回到 HBase shell 提示符。没有办法以编程方式检查每个单独的命令是否成功或失败。此外,尽管您看到每个命令的输出,但命令本身并未回显到屏幕,因此可能难以将命令与其输出对齐。

将VM选项传递给Shell

您可以使用 HBASE_SHELL_OPTS 环境变量将 VM 选项传递到 HBase Shell 。您可以在您的环境中进行设置,例如通过编辑 〜/ .bashrc,或将其设置为启动HBase Shell 的命令的一部分。以下的示例设置了几个与垃圾回收相关的变量,仅用于运行 HBase Shell 的 VM 的生命周期。为了可读性,该命令应该在单行中全部运行,但是会被 \ 字符打断。



HBase shell 技巧

表变量

HBase 0.95 版本增加了为表提供 jruby 风格的面向对象引用的 shell 命令。以前,作用于表的所有 shell 命令都具有程序风格,该风格始终将表的名称作为参数。HBase 0.95 引入了将表分配给 jruby 变量的功能。表引用可以用来执行数据读写操作,比如放入、扫描、以及管理功能(如禁用,删除,描述表等)。

例如,以前你总是会指定一个表名:

现在,您可以将该表分配给一个变量,并在 jruby shell 代码中使用结果。

如果该表已被创建,则可以使用 get_table 方法将一个表分配给一个变量:

列表功能也已被扩展,以便它返回一个表名称作为字符串的列表。然后,您可以使用 jruby 根据这些名称对表操作进行脚本编写。list_snapshots 命令的作用也相似。

irbrc

在您的主目录中为自己创建一个 .irbrc 文件,添加自定义项。一个有用的是历史记录命令,因此命令可以跨 Shell 调用进行保存:

请参阅 .irbrc 的 ruby 文档以了解其他可能的配置。

将数据记录到时间戳

要将日期“08/08/16 20:56:29”从 hbase 日志转换为时间戳,请执行以下操作:

从走另一个方向:

以与 HBase 日志格式完全相同的格式输出将会对 SimpleDateFormat 产生一些影响。

查询 Shell 配置

在 shell 中设置一个配置:

使用 HBase Shell 预分割表

在通过 HBase Shell 的 create 命令创建表时,您可以使用各种选项预先拆分表。

最简单的方法是在创建表格时指定一个分割点数组。请注意,当将字符串文字指定为分割点时,这些将根据字符串的基础字节表示创建分割点。所以当指定分割点“10”时,我们实际上是指定了字节分割点“\x31\30”。

分割点将定义 n+1 区域,其中 n 是分割点的数量。最低的区域将包含从最低可能的键直到但不包括第一分割点密钥的所有密钥。下一个区域将包含从第一个分割点开始的密钥,但不包括下一个分割点密钥键。这将持续到最后的所有分界点。最后一个区域将从最后一个拆分点定义为最大可能的密钥。

在上面的例子中,将使用列族 “f” 创建表 “t1”,预先拆分到四个区域。请注意,第一个区域将包含从“\x00”到“\x30”(因为“\x31”是“1”的 ASCII 码)的所有密钥。

您可以使用以下变化将分割点传递到文件中。在这个例子中,分割是从对应于本地文件系统上的本地路径的文件中读取的。文件中的每一行都指定一个分割点密钥。

其他选项是根据所需的区域数量和分割算法自动计算分割。HBase 提供基于统一拆分或基于十六进制密钥分割密钥范围的算法,但您可以提供自己的拆分算法来细分密钥范围。

由于 HBase Shell 实际上是一个 Ruby 环境,因此您可以使用简单的 Ruby 脚本以算法方式计算分割。

请注意,HBase Shell 命令 truncate 有效地删除并重新创建具有默认选项的表格,这将丢弃任何预分割。如果您需要截断预分割表,则必须显式删除并重新创建表以重新指定自定义分割选项。

调试

shell 调试开关

您可以在 shell 中设置一个调试开关,以查看更多输出 - 例如,运行命令时出现更多的异常堆栈跟踪:

DEBUG 日志级别

要在 shell 中启用 DEBUG 级日志记录,请使用该 -d 选项启动它:

Count 命令

Count 命令返回表中的行数。配置正确的 CACHE 时速度非常快:

上述计数一次取 1000 行。如果行很大,请将 CACHE 设置得较低。默认是每次读取一行。



HBase 数据模型

在 HBase 中,数据模型同样是由表组成的,各个表中又包含数据行和列,在这些表中存储了 HBase 数据。在本节中,我们将介绍 HBase 数据模型中的一些术语。

HBase数据模型术语

表(Table)

HBase 会将数据组织进一张张的表里面,一个 HBase 表由多行组成。

行(Row)

HBase 中的一行包含一个行键和一个或多个与其相关的值的列。在存储行时,行按字母顺序排序。出于这个原因,行键的设计非常重要。目标是以相关行相互靠近的方式存储数据。常用的行键模式是网站域。如果你的行键是域名,则你可能应该将它们存储在相反的位置(org.apache.www,org.apache.mail,org.apache.jira)。这样,表中的所有 Apache 域都彼此靠近,而不是根据子域的第一个字母分布。

列(Column)

HBase 中的列由一个列族和一个列限定符组成,它们由:(冒号)字符分隔。

列族(Column Family)

出于性能原因,列族在物理上共同存在一组列和它们的值。在 HBase 中每个列族都有一组存储属性,例如其值是否应缓存在内存中,数据如何压缩或其行编码是如何编码的等等。表中的每一行都有相同的列族,但给定的行可能不会在给定的列族中存储任何内容。

列族一旦确定后,就不能轻易修改,因为它会影响到 HBase 真实的物理存储结构,但是列族中的列标识(Column Qualifier)以及其对应的值可以动态增删。

列限定符(Column Qualifier)

列限定符被添加到列族中,以提供给定数据段的索引。鉴于列族的content,列限定符可能是content:html,而另一个可能是content:pdf。虽然列族在创建表时是固定的,但列限定符是可变的,并且在行之间可能差别很大。

单元格(Cell)

单元格是行、列族和列限定符的组合,并且包含值和时间戳,它表示值的版本。

时间戳(Timestamp)

时间戳与每个值一起编写,并且是给定版本的值的标识符。默认情况下,时间戳表示写入数据时 RegionServer 上的时间,但可以在将数据放入单元格时指定不同的时间戳值。



HBase 概念视图

本节介绍 HBase 的概念视图。

本节的示例是根据  BigTable 论文进行稍微修改后的示例。在本节的示例中有一个名为表 webtable,其中包含两行(com.cnn.www 和 com.example.www)以及名为 contents、anchor 和 people 的三个列族。在本例中,对于第一行(com.cnn.www), anchor 包含两列(anchor:cssnsi.com,anchor:my.look.ca),并且 contents 包含一列(contents:html)。本示例包含具有行键 com.cnn.www 的行的5个版本,以及具有行键 com.example.www 的行的一个版本。contents:html 列限定符包含给定网站的整个 HTML。锚(anchor)列族的限定符每个包含与该行所表示的站点链接的外部站点以及它在其链接的锚点(anchor)中使用的文本。people 列族代表与该网站相关的人员。

列名称:按照约定,列名由其列族前缀和限定符组成。例如,列内容: html 由列族contents和html限定符组成。冒号字符(:)从列族限定符分隔列族。

webtable 表如下所示:

行键(Row Key)
时间戳(Time Stamp)
ColumnFamily`contents`ColumnFamily`anchor`ColumnFamily `people`|------

“com.cnn.www”

T9

anchor:cnnsi.com =“CNN”

“com.cnn.www”

T8

anchor:my.look.ca =“CNN.com”

“com.cnn.www”

T6

内容:html =“<html> …”

“com.cnn.www”

T5

内容:html =“<html> …”

“com.cnn.www”

T3

内容:html =“<html> …”

“com.example.www”

T5

内容:html =“<html> …”

people:author = “John Doe”

此表中显示为空的单元格在 HBase 中不占用空间或实际上存在。这正是使 HBase “稀疏”的原因。表格视图并不是查看 HBase 数据的唯一可能的方法,甚至是最准确的。以下代表与多维地图相同的信息。这只是用于说明目的的模拟,可能并不严格准确。



HBase 物理视图

本节介绍 HBase 物理视图。

尽管在 HBase 概念视图中,表格被视为一组稀疏的行的集合,但它们是按列族进行物理存储的。可以随时将新的列限定符(column_family:column_qualifier)添加到现有的列族。

ColumnFamily anchor 表:

行键(Row Key)
时间戳(Time Stamp)
ColumnFamily anchor|------

“com.cnn.www”

T9

anchor:cnnsi.com = “CNN”

“com.cnn.www”

T8

anchor:my.look.ca = “CNN.com”

ColumnFamily contents表:

行键(Row Key)时间戳(Time Stamp)ColumnFamily `contents:`|------

“com.cnn.www”

T6

contents:html = “<html>…”

“com.cnn.www”

T5

contents:html = “<html>…”

“com.cnn.www”

T3

contents:html = “<html>…”

HBase 概念视图中显示的空单元根本不存储。因此,对时间戳为 t8 的 contents:html 列值的请求将不返回任何值。同样,在时间戳为 t9 中一个anchor:my.look.ca 值的请求也不会返回任何值。但是,如果未提供时间戳,则会返回特定列的最新值。给定多个版本,最近的也是第一个找到的,因为时间戳按降序存储。因此,如果没有指定时间戳,则对行 com.cnn.www 中所有列的值的请求将是: 时间戳 t6 中的 contents:html,时间戳 t9 中 anchor:cnnsi.com 的值,时间戳 t8 中 anchor:my.look.ca 的值。



HBase 命名空间

HBase命名空间 namespace 是与关系数据库系统中的数据库类似的表的逻辑分组。这种抽象为即将出现的多租户相关功能奠定了基础:

  • 配额管理(Quota Management)(HBASE-8410) - 限制命名空间可占用的资源量(即区域,表)。- 命名空间安全管理(Namespace Security Administration)(HBASE-9206) - 为租户提供另一级别的安全管理。- 区域服务器组(Region server groups)(HBASE-6721) - 命名空间/表可以固定在 RegionServers 的子集上,从而保证粗略的隔离级别。
    命名空间安全管理(Namespace Security Administration)(HBASE-9206) - 为租户提供另一级别的安全管理。

命名空间管理

你可以创建、删除或更改命名空间。通过指定表单的完全限定表名,在创建表时确定命名空间成员权限:

示例:

HBase预定义的命名空间

在 HBase 中有两个预定义的特殊命名空间:

  • hbase:系统命名空间,用于包含 HBase 内部表- default:没有显式指定命名空间的表将自动落入此命名空间
    default:没有显式指定命名空间的表将自动落入此命名空间

示例:



HBase 表、行与列族

HBase表

HBase 中表是在 schema 定义时被预先声明的。

可以使用以下的命令来创建一个表,在这里必须指定表名和列族名。在 HBase shell 中创建表的语法如下所示:

HBase行

HBase中的行是逻辑上的行,物理上模型上行是按列族(colomn family)分别存取的。

行键是未解释的字节,行是按字母顺序排序的,最低顺序首先出现在表中。空字节数组用于表示表命名空间的开始和结束。

HBase列族

Apache HBase 中的列被分组为列族。列族的所有列成员具有相同的前缀。例如,courses:history 和 courses:math 都是 courses 列族的成员。冒号字符(:)从列族限定符中分隔列族。列族前缀必须由可打印字符组成。限定尾部,列族限定符可以由任意字节组成。必须在 schema 定义时提前声明列族,而列不需要在 schema 时定义,但可以在表启动并运行时动态地变为列。

在物理上,所有列族成员一起存储在文件系统上。由于调音(tunings)和存储(storage)规范是在列族级完成的,因此建议所有列族成员具有相同的一般访问模式和大小特征。

HBase Cell

由{row key, column( =<family> + <label>), version} 唯一确定的单元。cell 中的数据是没有类型的,全部是字节码形式存储。



HBase 数据模型操作

在 HBase 中有四个主要的数据模型操作,分别是:Get、Put、Scan 和 Delete。

Get(读取)

Get 指定行的返回属性。读取通过 Table.get 执行。

Get 操作的语法如下所示:

在以下的 get 命令示例中,我们扫描了 emp 表的第一行:

读取指定列

下面给出的是使用 get 操作读取指定列语法:

在下面给出的示例表示用于读取 HBase 表中的特定列:

Put(写)

Put 可以将新行添加到表中(如果该项是新的)或者可以更新现有行(如果该项已经存在)。Put 操作通过 Table.put(non-writeBuffer)或 Table.batch(non-writeBuffer)执行。

Put 操作的命令如下所示,在该语法中,你需要注明新值:

新给定的值将替换现有的值,并更新该行。

**Put操作示例 **

假设 HBase 中有一个表 EMP 拥有下列数据:

以下命令将员工名为“raju”的城市值更新为“Delhi”:

更新后的表如下所示:

Scan(扫描)

Scan 允许在多个行上对指定属性进行迭代。

Scan 操作的语法如下:

以下是扫描表格实例的示例。假定表中有带有键  "row1 "、 "row2 "、 "row3 " 的行,然后是具有键“abc1”,“abc2”和“abc3”的另一组行。以下示例显示如何设置Scan实例以返回以“row”开头的行。

请注意,通常,指定扫描的特定停止点的最简单方法是使用 InclusiveStopFilter 类。

Delete(删除)

Delete 操作用于从表中删除一行。Delete 通过 Table.delete 执行。

HBase 不会修改数据,因此通过创建名为 tombstones 的新标记来处理 Delete 操作。这些  tombstones,以及没用的价值,都在重大的压实中清理干净。

使用 Delete 命令的语法如下:

下面是一个删除特定单元格的例子:

删除表的所有单元格

使用 “deleteall” 命令,可以删除一行中所有单元格。下面给出是 deleteall 命令的语法:

这里是使用“deleteall”命令删除 emp 表 row1 的所有单元的一个例子。

使用 Scan 命令验证表。表被删除后的快照如下:



HBase 版本

在 HBase 中,一个{row,column,version}元组精确指定了一个 cell。可能有无限数量的单元格,其中行和列是相同的,但单元格地址仅在其版本维度上有所不同。 

虽然行和列键以字节表示,但版本是使用长整数指定的。通常,这个long包含时间实例,如由java.util.Date.getTime() 或者 System.currentTimeMillis() 返回的时间实例,即:1970年1月1日UTC的当前时间和午夜之间的差值(以毫秒为单位)。

HBase 版本维度按递减顺序存储,因此从存储文件读取时,会先查找最新的值。

在 HBase 中,cell 版本的语义有很多混淆。尤其是:

  • 如果对一个单元的多次写入具有相同的版本,则只有最后一次写入是可以读取的。- 以非递增版本顺序编写单元格是可以的。
    以非递增版本顺序编写单元格是可以的。

下面我们描述 HBase 当前的版本维度是如何工作的。HBase 中的弯曲时间使得 HBase 中的版本或时间维度得到很好的阅读。它在版本控制方面的细节比这里提供的更多。

在撰写本文时,文章中提到的限制覆盖现有时间戳的值不再适用于HBase。本节基本上是 Bruno Dumon 撰写的文章的简介。

指定要存储的HBase版本数量

为给定列存储的最大版本数是列架构的一部分,并在创建表时通过 alter 命令 HColumnDescriptor.DEFAULT_VERSIONS 指定 。在 HBase 0.96 之前,保留的版本的默认数量是3,但在 0.96 以及新版本中已更改为1。

示例 - 修改一个列族的最大版本数量

本示例使用HBase Shell来保留列族中所有列的最多5个版本f1。你也可以使用HColumnDescriptor。

示例 - 修改列族的最小版本数

您还可以指定每列家族存储的最低版本数。默认情况下,它被设置为0,这意味着该功能被禁用。下面的示例通过 HBase Shell 将在列族 f1 中的所有列的最小版本数设置为2。你也可以使用 HColumnDescriptor。

从 HBase 0.98.2 开始,您可以通过在 hbase-site.xml 中设置 hbase.column.max.version 为所有新创建列保留的最大版本数指定一个全局默认值。

版本和 HBase 操作

在下面的内容中,我们将了解每个核心 HBase 操作的版本维度的行为。 

获取/扫描(Get/Scan)

获取在 Scans 之上实现。以下关于 Get 的讨论同样适用于 Scans。

默认情况下,即如果你没有指定明确的版本,则在执行“get”操作时,会返回其版本值最大的单元格(可能是也可能不是最新版本,请参阅后面的内容)。默认行为可以通过以下方式进行修改:

  • 要返回多个版本,请参阅 Get.setMaxVersions()- 要返回除最新版本以外的其他版本,请参阅 Get.setTimeRange(),要检索小于或等于给定值的最新版本,从而在某个时间点给出记录的“最新”状态,只需使用从0到所需版本的范围,并将最大版本设置为1 。
    要返回除最新版本以外的其他版本,请参阅 Get.setTimeRange(),要检索小于或等于给定值的最新版本,从而在某个时间点给出记录的“最新”状态,只需使用从0到所需版本的范围,并将最大版本设置为1 。

默认获取示例

以下获取将只检索行的当前版本:

版本化获取示例

以下 Get 将返回该行的最后3个版本。

Put(写)

在某个时间戳处进行Put(写)操作总是会创建一个新版本的 cell。默认情况下,系统使用服务器的 currentTimeMillis,但您可以在每列级别上自己指定版本(等于长整数)。这意味着您可以分配过去或未来的时间,或将长时间值用于非时间目的。 

要覆盖现有值,请执行与要覆盖的单元格中的行、列和版本完全相同的 put。

隐式版本示例: 

HBase 会在当前时间隐式地对以下 Put 进行版本管理。

显示版本示例:

以下 Put 具有明确设置的版本时间戳。

注意:版本时间戳由 HBase 内部使用,用于诸如生存时间计算之类的事情。通常最好避免自己设置时间戳。优先使用该行的单独时间戳属性,或者将时间戳记作为行键的一部分,或者同时使用两者。

删除(delete)

有三种不同类型的内部删除标记。并添加另一个扫描 HBase:Prefix Delete Marker。

  • 删除(Delete):针对特定版本的列。- 删除列(Delete column):适用于所有版本的列。- 删除系列(Delete family):针对特定 ColumnFamily 的所有列
    删除列(Delete column):适用于所有版本的列。

当删除整行时,HBase 将在内部为每个 ColumnFamily(即不是每个单独的列)创建一个逻辑删除。

通过创建 tombstone 标记来删除作品。例如,假设我们想要删除一行。为此,您可以指定一个版本,或者默认情况下使用该 currentTimeMillis。这意味着删除版本小于或等于此版本的所有单元格。HBase 从不修改数据,例如删除不会立即删除(或标记为已删除)存储文件中对应于删除条件的条目。相反,所谓的 tombstone 被写入,这将掩盖已删除的值。当 HBase 进行重大压缩时,tombstone 将被处理以实际移除不能用的值以及 tombstone 本身。如果您在删除行时指定的版本大于行中任何值的版本,则可以考虑删除整行。

除非在列族中设置了 KEEP_DELETED_CELLS 选项,否则删除标记在存储区的下一个主要压缩过程中被清除。如果要将删除保留为可配置的时间量,可以通过hbase-site.xml 中的 hbase.hstore.time.to.purge.deletes 属性设置删除 TTL 。如果 hbase.hstore.time.to.purge.deletes 未设置或设置为 0,则将在下一次主要压缩过程中清除所有删除标记,包括将来使用时间戳的标记。否则,将保留在将来具有时间戳的删除标记,直到在由标记时间戳表示的时间加上hbase.hstore.time.to.purge.deletes 的值(以毫秒为单位)之后发生的主要压缩为止。

HBase-2.0.0中的可选新版本和删除行为

在 hbase-2.0.0 中,操作员可以通过将列描述符属性 NEW_VERSION_BEHAVIOR 设置为 true 来指定备用版本和删除处理(若要在列族描述符上设置属性,您必须首先禁用表,然后改变列族描述符)。

“新版本行为”解除了以下列出的局限性,取消了以下所列的限制,即如果在同一位置,Delete 总是会超过一个Put(即相同的行,列族,限定符和时间戳),而不管哪一个先到达。版本记帐也会因为删除版本考虑到版本总数而发生变化。这是为了确保在重大压缩情况下不会改变结果。

运行这个新配置目前的成本;我们将每个比较的 Cell MVCC 因素考虑在内,因此我们消耗更多的 CPU,这是减速所取决于的,在测试中,我们已经看到0%到25%的降级。

如果正在复制,建议您使用新的串行复制功能运行,因为现在突变到达的顺序是因子。

HBase目前的局限性

以下限制在 hbase-2.0.0 中解决。请参阅上面的“HBase-2.0.0 中的可选新版本和删除行为”部分。

删除标记Put

删除掩码放入,甚至在输入删除后发生。请记住,删除操作会写入逻辑删除,只有在下一次主要压缩运行后才会消失。假设你删除了所有的⇐ T 的内容,然后你做了一个带有时间戳 ⇐ T 的新放。这种情况下,即使在删除后发生,也会被删除 tombstone 屏蔽。执行投入不会失败,但是当你做出投注时,你会注意到投注没有任何效果。重大压缩后,它将再次开始工作。如果您使用不断增加的版本进行新的放置,则这些问题不应该是一个问题。但即使您不在乎时间,也可能发生这种情况:只需删除并立即放置在对方之后,并且有可能在同一毫秒内发生。

主要的压缩改变了查询结果

在 t1,t2 和 t3 中创建三个单元格版本,最大版本设置为 2。因此,获取所有版本时,只会返回 t2 和 t3 的值。但是如果在 t2 或 t3 删除版本,则 t1 中的版本将再次出现。显然,一旦主要的压实运行后,这种行为将不会是这样了。



HBase 排序顺序、列元数据以及联合查询

HBase排序顺序

所有数据模型操作 HBase 以排序顺序返回数据。首先按行,然后按列族(ColumnFamily),然后是列限定符,最后是时间戳(反向排序,因此首先返回最新的记录)。

HBase列元数据

ColumnFamily 的内部 KeyValue 实例之外不存储列元数据。因此,尽管 HBase 不仅可以支持每行大量的列数,而且还能对行之间的一组异构列进行维护,但您有责任跟踪列名。

获得 ColumnFamily 存在的一组完整列的唯一方法是处理所有行。

HBase联合查询

HBase 是否支持联合是该区列表中的一个常见问题,并且有一个简单的答案:它不是,至少在 RDBMS 支持它们的方式中(例如,使用 SQL 中的等连接或外连接)。如本章所述,HBase 中读取的数据模型操作是 Get 和 Scan,你可以参考“HBase数据模型操作”部分

但是,这并不意味着您的应用程序不支持等效的联合功能,但您必须自己动手。两个主要策略是在写入 HBase 时对数据进行非规格化,或者在您的应用程序或MapReduce 代码中使用查找表并进行HBase表之间的连接(并且正如 RDBMS 演示的那样,有几种策略取决于 HBase 的大小表,例如,嵌套循环与散列连接)。那么最好的方法是什么?这取决于你想要做什么,因此没有一个适用于每个用例的答案。

ACID

ACID,指数据库事务正确执行的四个基本要素的缩写,即:原子性(Atomicity),一致性(Consistency),隔离性(Isolation),持久性(Durability)。

HBase 支持特定场景下的 ACID,即对同一行的 Put 操作保证完全的 ACID(HBASE-3584增加了多操作事务,HBASE-5229增加了多行事务,但原理是一样的)



HBase 模式(Schema) 创建

你可以使用 Apache HBase Shell 或使用 Java API 中的 Admin 来创建或更新 HBase 模式。

进行 ColumnFamily 修改时,必须禁用表格,例如:

当对表或 ColumnFamilies (如区域大小、块大小) 进行更改时,这些更改将在下一次出现重大压缩并重新写入 StoreFiles 时生效。



HBase 表格模式经验法则

在 HBase 中有许多不同的数据集,具有不同的访问模式和服务级别期望。因此,这些经验法则只是一个概述。

  • 目标区域的大小介于10到50 GB之间。- 目的是让单元格不超过10 MB,如果使用 mob,则为50 MB 。否则,请考虑将您的单元格数据存储在 HDFS 中,并在 HBase 中存储指向数据的指针。- 典型的模式在每个表中有1到3个列族。HBase 表不应该被设计成模拟 RDBMS 表。- 对于具有1或2列族的表格,大约50-100个区域是很好的数字。请记住,区域是列族的连续段。- 尽可能短地保留列族名称。列族名称存储在每个值 (忽略前缀编码) 中。它们不应该像在典型的 RDBMS 中一样具有自我记录和描述性。- 如果您正在存储基于时间的机器数据或日志记录信息,并且行密钥基于设备 ID 或服务 ID 加上时间,则最终可能会出现一种模式,即旧数据区域在某个时间段之后永远不会有额外的写入操作。在这种情况下,最终会有少量活动区域和大量没有新写入的较旧区域。对于这些情况,您可以容忍更多区域,因为您的资源消耗仅由活动区域驱动。- 如果只有一个列族忙于写入,则只有该列族兼容内存。分配资源时请注意写入模式。
    目的是让单元格不超过10 MB,如果使用 mob,则为50 MB 。否则,请考虑将您的单元格数据存储在 HDFS 中,并在 HBase 中存储指向数据的指针。

对于具有1或2列族的表格,大约50-100个区域是很好的数字。请记住,区域是列族的连续段。

如果您正在存储基于时间的机器数据或日志记录信息,并且行密钥基于设备 ID 或服务 ID 加上时间,则最终可能会出现一种模式,即旧数据区域在某个时间段之后永远不会有额外的写入操作。在这种情况下,最终会有少量活动区域和大量没有新写入的较旧区域。对于这些情况,您可以容忍更多区域,因为您的资源消耗仅由活动区域驱动。



HBase 列族数量

HBase 目前对于两列族或三列族以上的任何项目都不太合适,因此请将模式中的列族数量保持在较低水平。目前,flushing 和 compactions 是按照每个区域进行的,所以如果一个列族承载大量数据带来的 flushing,即使所携带的数据量很小,也会 flushing 相邻的列族。当许多列族存在时,flushing 和 compactions 相互作用可能会导致一堆不必要的 I/O(要通过更改 flushing 和 compactions 来针对每个列族进行处理)。

如果你可以在你的模式中尝试使用一个列族。在数据访问通常是列作用域的情况下,仅引入第二和第三列族;即你查询一个列族或另一个列族,但通常不是两者同时存在。

ColumnFamilies的基数

在一个表中存在多个 ColumnFamilies 的情况下,请注意基数(即行数)。如果 ColumnFamilyA 拥有100万行并且 ColumnFamilyB 拥有10亿行,则ColumnFamilyA 的数据可能会分布在很多很多地区(以及 Region Server)中。这使得 ColumnFamilyA 的大规模扫描效率较低。



Rowkey(行键)设计

本节介绍了 HBase 中的行键(Rowkey)设计。

Hotspotting

HBase 中的行按行键按顺序排序。这种设计优化了扫描(scan),允许您将相关的行或彼此靠近的行一起读取。但是,设计不佳的行键是 hotspotting 的常见来源。当大量客户端通信针对群集中的一个节点或仅少数几个节点时,会发生 Hotspotting。此通信量可能表示读取、写入或其他操作。通信量压倒负责托管该区域的单个机器,从而导致性能下降并可能导致区域不可用性。这也会对由同一台区域服务器托管的其他区域产生不利影响,因为该主机无法为请求的负载提供服务。设计数据访问模式以使群集得到充分和均匀利用非常重要。

为了防止 hotspotting 写入,请设计行键,使真正需要在同一个区域中的行成为行,但是从更大的角度来看,数据将被写入整个群集中的多个区域,而不是一次。以下描述了避免 hotspotting 的一些常用技术,以及它们的一些优点和缺点。

Salting

从这个意义上说,Salting 与密码学无关,而是指将随机数据添加到行键的开头。在这种情况下,salting 是指为行键添加一个随机分配的前缀,以使它的排序方式与其他方式不同。可能的前缀数量对应于要传播数据的区域数量。如果你有一些“hotspotting”行键模式,反复出现在其他更均匀分布的行中,那么 Salting 可能会有帮助。请考虑以下示例,该示例显示 salting 可以跨多个 RegionServer 传播写入负载,并说明读取的一些负面影响。

使用实例

假设您有以下的行键列表,并且您的表格被拆分,以便字母表中的每个字母都有一个区域。前缀’a’是一个区域,前缀’b’是另一个区域。在此表中,所有以’f’开头的行都在同一个区域中。本示例重点关注具有以下键的行:

现在,想象你想要在四个不同的地区传播这些信息。您决定使用四个不同的 Salting:a,b,c 和 d。在这种情况下,每个这些字母前缀将位于不同的区域。应用 Salting 后,您可以使用以下 rowkeys。由于您现在可以写入四个不同的区域,因此理论上写入时的吞吐量是吞吐量的四倍,如果所有写入操作都在同一个区域,则会有这样的吞吐量。

然后,如果添加另一行,它将随机分配四种可能的 Salting 值中的一种,并最终靠近现有的一行。

由于这个任务是随机的,如果你想按字典顺序检索行,你需要做更多的工作。以这种方式,Salting 试图增加写入吞吐量,但在读取期间会产生成本。

Hashing

除了随机分配之外,您可以使用单向 Hashing,这会导致给定的行总是被相同的前缀“salted”,其方式会跨 RegionServer 传播负载,但允许在读取期间进行预测。使用确定性  Hashing 允许客户端重建完整的 rowkey 并使用 Get 操作正常检索该行。

Hashing 示例

考虑到上述 salting 示例中的相同情况,您可以改为应用单向 Hashing,这会导致带有键的行 foo0003 始终处于可预见的状态并接收 a 前缀。

然后,为了检索该行,您已经知道了密钥。

例如,您也可以优化事物,以便某些键对总是在相同的区域中。

反转关键

防止热点的第三种常用技巧是反转固定宽度或数字行键,以便最经常(最低有效位数)改变的部分在第一位。这有效地使行键随机化,但牺牲了行排序属性。

单调递增行键/时间序列数据

在 Tom White 的书“Hadoop: The Definitive Guide”(O’Reilly)的一章中,有一个优化笔记,关注一个现象,即导入过程与所有客户一起敲击表中的一个区域(并且因此是单个节点),然后移动到下一个区域等等。随着单调递增的行键(即,使用时间戳),这将发生。通过将输入记录随机化为不按排序顺序排列,可以缓解由单调递增密钥带来的单个区域上的堆积,但通常最好避免使用时间戳或序列(例如1,2,3)作为行键。

如果您确实需要将时间序列数据上传到 HBase 中,则应将 OpenTSDB 作为一个成功的示例进行研究。它有一个描述它在 HBase 中使用的模式的页面。OpenTSDB 中的关键格式实际上是 [metric_type] [event_timestamp],它会在第一眼看起来与之前关于不使用时间戳作为关键的建议相矛盾。但是,区别在于时间戳不在密钥的主导位置,并且设计假设是有几十个或几百个(或更多)不同的度量标准类型。因此,即使连续输入数据和多种度量类型,Puts也会分布在表中不同的地区。

尽量减少行和列的大小

在 HBase 中,值总是随着坐标而运行;当单元格值通过系统时,它将始终伴随其行,列名称和时间戳。如果你的行和列的名字很大,特别是与单元格的大小相比,那么你可能会遇到一些有趣的场景。其中之一就是 Marc Limotte 在 HBASE-3551 尾部描述的情况。其中,保存在 HBase商店文件( StoreFile(HFile))以方便随机访问可能最终占用 HBase 分配的 RAM 的大块,因为单元值坐标很大。上面引用的注释中的标记建议增加块大小,以便存储文件索引中的条目以更大的间隔发生,或者修改表模式,以便使用较小的行和列名称。压缩也会使更大的指数。在用户邮件列表中查看线程问题 storefileIndexSize。

大多数时候,小的低效率并不重要。不幸的是,这是他们的情况。无论为 ColumnFamilies,属性和 rowkeys 选择哪种模式,都可以在数据中重复数十亿次。

列族

尽量保持 ColumnFamily 名称尽可能小,最好是一个字符(例如,“d” 用于 data 或者 default)。

属性

虽然详细的属性名称(例如,“myVeryImportantAttribute”)更易于阅读,但更喜欢使用较短的属性名称(例如,“via”)来存储在 HBase 中。

Rowkey长度

保持它们尽可能短,这样它们仍然可以用于所需的数据访问(例如,Get 和 Scan)。对数据访问无用的短密钥并不比具有更好的 get/scan 属性的更长密钥更好。在设计行键时需要权衡。

字节模式

长为8个字节。您可以在这八个字节中存储最多18,446,744,073,709,551,615的未签名数字。如果您将此数字作为字符串存储 - 假定每个字符有一个字节 - 则需要接近3倍的字节。

以下是您可以自行运行的一些示例代码:

不幸的是,使用类型的二进制表示会使您的数据难以在代码之外读取。例如,这是您在增加值时在 shell 中将看到的内容:

shell 会尽最大努力打印一个字符串,并且它决定只打印十六进制。区域名称内的行键也会发生同样的情况。如果您知道存储的内容可能没问题,但如果可以将任意数据放入同一个单元格中,它可能也是不可读的。这是主要的权衡。

反向时间戳

反向扫描 API

HBASE-4811 实现一个 API,以反向扫描表中的表或区域,从而减少了为正向或反向扫描优化模式的需要。此功能在 HBase 0.98 和更高版本中可用。

数据库处理中的一个常见问题是快速找到最新版本的值。使用反向时间戳作为密钥的一部分的技术可以帮助解决这个问题的一个特例。在 Tom White 的书籍“Hadoop:The Definitive Guide(O’Reilly)”的 HBase 章节中也有介绍,该技术包括附加 Long.MAX_VALUE - timestamp 到任何密钥的末尾(例如,[key][reverse_timestamp])。

通过执行 Scan [key] 并获取第一条记录,可以找到表格中 [key] 的最新值。由于 HBase 密钥的排序顺序不同,因此该密钥在 [key] 的任何较旧的行键之前排序,因此是第一个。

这种技术将被用来代替使用版本号,其意图是永久保存所有版本(或者很长时间),同时通过使用相同的扫描技术来快速获得对任何其他版本的访问。

Rowkeys和ColumnFamilies

行键的范围为 ColumnFamilies。因此,相同的 rowkey 可以存在于没有碰撞的表中存在的每个 ColumnFamily 中。

Rowkeys的不变性

行键无法更改。他们可以在表格中“更改”的唯一方法是该行被删除然后重新插入。这是 HBase dist-list 上的一个相当常见的问题,所以在第一次(或在插入大量数据之前)获得 rowkeys 是值得的。

RowKeys与区域分割之间的关系

如果您预先拆分表格,了解您的 rowkey 如何在区域边界上分布是非常重要的。作为重要的一个例子,考虑使用可显示的十六进制字符作为键的前导位置(例如,“0000000000000000” 到 “ffffffffffffffff”)的示例。通过这些关键范围 Bytes.split(这是在 Admin.createTable(byte[] startKey, byte[] endKey, numRegions) 为10个区域创建区域时使用的分割策略)将生成以下分割:

(注意:前导字节作为注释列在右侧。)鉴于第一个分割是’0’而最后一个分割是’f’,一切都很好,但是还没有结束。

其中的问题是,所有的数据都会堆积在前两个区域和最后一个区域,从而产生一个“块状(lumpy)”(也可能是“hot”)区域问题。'0’是字节48,'f’是字节102,但字节值(字节58到96)之间存在巨大的差距,永远不会出现在这个密钥空间中,因为唯一的值是 [0-9] 和 [af]。因此,中间地区将永远不会被使用。要使用此示例键空间进行预分割工作,需要分割的自定义定义(即,不依赖于内置拆分方法)。

第1课:预分割表通常是最佳做法,但您需要预先拆分它们,以便可以在密钥空间中访问所有区域。虽然此示例演示了十六进制密钥空间的问题,但任何密钥空间都会出现同样的问题。了解你的数据。

第2课:尽管通常不可取,但只要所有创建的区域都可在密钥空间中访问,则使用十六进制键(更一般而言,可显示的数据)仍可用于预分割表。

为了总结这个例子,以下是如何为十六进制密钥预先创建恰当的分割的例子:



HBase 版本数量

HBase最大版本数量

HBase 通过 HColumnDescriptor 为每个列族配置要存储的最大行数版本。最大版本的默认值为1。这是一个重要的参数,因为如数据模型部分所述,HBase 也没有覆盖行的值,而是按时间(和限定符)存储不同的值。在重要的压缩过程中删除多余的版本。最大版本的数量可能需要根据应用程序需求增加或减少。

不建议将最高版本数设置为极高的级别(例如,数百个或更多),除非这些旧值对您非常重要,因为这会大大增加 StoreFile 大小。

HBase最小版本数量

与最大行版本数一样,HBase 通过 HColumnDescriptor 为每个列族配置要保留的最小行数版本。最小版本的默认值为0,这意味着该功能被禁用。行版本参数的最小数目与生存时间参数一起使用,并且可以与行版本参数的数目组合在一起,以允许诸如“保留最多T分钟值的数据,最多N个版本,但是至少保留 M 个版本 “(其中M 是最小行版本数的值,M <N)。仅当对列族启用了生存时间并且必须小于行版本的数量时,才应设置此参数。



HBase 支持的数据类型

HBase 通过 Put 操作和 Result 操作支持 “byte-in / bytes-out” 接口,所以任何可以转换为字节数组的内容都可以作为一个值存储。输入可以是字符串、数字、复杂对象、甚至可以是图像,只要它们可以呈现为字节。 

值的大小有实际的限制(例如,在 HBase 中存储 10-50MB 的对象可能太多了)。在邮件列表中搜索关于此主题的对话。HBase 中的所有行都符合数据模型,并包含版本控制。在进行设计时考虑到这一点,以及 ColumnFamily 的块大小。

计数器

值得特别提及的一种支持的数据类型是“计数器(counters)”(即,能够执行数字的原子增量)。

计数器上的同步是在区域服务器(RegionServer)上完成的,而不是在客户端上进行的。



HBase 生存时间(TTL)

ColumnFamilies 可以以秒为单位来设置 TTL(Time To Live)长度,一旦达到到期时间,HBase 将自动删除行。这适用于所有版本的行 - 即使是当前版本。在该 HBase 行的中编码的TTL时间以UTC指定。

仅在小型压缩时删除包含过期行的存储文件。设置 hbase.store.delete.expired.storefile 为 false 将禁用此功能。将最小版本数设置为 0 以外的值也会禁用此功能。

最近的 HBase 版本也支持设置时间以每个单元为基础生存。单元 TTL 是使用突变 #setTTL 作为突变请求(例如:Appends、Increments、Puts)的属性提交的。如果设置了 TTL 属性,则该操作将应用于服务器上更新的所有单元。单元 TTL 处理和 ColumnFamily TTL 之间有两个显着的区别:

  • 单元 TTL 以毫秒为单位而不是秒。- 单元 TTL 不能将一个单元的有效生命周期延长超过 ColumnFamily 级 TTL 设置。
    单元 TTL 不能将一个单元的有效生命周期延长超过 ColumnFamily 级 TTL 设置。


保留已删除的HBase单元格

默认情况下,删除标记会向后扩展到开始时间。因此,即使 Get 或 Scan 操作指示放置删除标记之前的时间范围,Get 或 Scan 操作也不会看到已删除的单元格(行或列)。

ColumnFamilies 可以选择保留已删除的单元格。在这种情况下,只要这些操作指定的时间范围在影响单元格的任何删除的时间戳之前结束,则仍然可以检索已删除的单元格。这允许甚至在存在删除的情况下进行时间点查询。

删除的单元格仍然受到TTL的限制,并且永远不会超过“最大数量的版本”删除的单元格。新的“原始”扫描选项将返回所有已删除的行和删除标记。

示例 - 使用HBase Shell更改 KEEP_DELETED_CELLS 的值

示例 - 使用 API 更改 KEEP_DELETED_CELLS 的值

让我们来说明在 KEEP_DELETED_CELLS 表上设置属性的基本效果。

首先,没有:

注意删除单元格是如何放开的。

现在,让我们只用 KEEP_DELETED_CELLS 设置在表上运行相同的测试(您可以执行表或每列族):

KEEP_DELETED_CELLS 是为了避免从 HBase 中删除单元格时,删除它们的唯一原因是删除标记。因此,如果您编写的版本多于配置的最大版本,或者您有TTL且单元格超过配置的超时等,则 KEEP_DELETED_CELLS 启用的已删除单元格将被删除。



HBase 二级索引和备用查询路径

你也可以将本节的标题理解为“如果我的表 rowkey 看起来像这样,但我也希望我的查询表这样。” dist-list 上的一个常见示例是 row-key 格式为“user-timestamp”格式,但对于特定时间范围内的用户活动有报告要求。因此,用户选择容易,因为它处于密钥的主导位置,但时间不是。

没有一个最好的方法来解决这个问题的答案,因为它取决于:

  • 用户数量- 数据大小和数据到达率- 报告要求的灵活性(例如,完全特定的日期选择与预先配置的范围)- 期望的查询执行速度(例如,对于临时报告来说90秒可能是合理的,而对于其他情况来说可能太长)
    数据大小和数据到达率

期望的查询执行速度(例如,对于临时报告来说90秒可能是合理的,而对于其他情况来说可能太长)

而且解决方案也受到集群规模和解决方案所需的处理能力的影响。常见的技巧在下面的部分中介绍。这是一个全面但并非详尽的方法清单。

二级索引需要额外的集群空间和处理并不令人惊讶。这正是 RDBMS 中发生的情况,因为创建备用索引的操作需要更新空间和处理周期。RDBMS产品在这方面更加先进,可以处理替代索引管理。但是,HBase 在更大的数据量下可以更好地扩展,所以这是一项功能交换。

实施这些方法时请注意 Apache HBase 性能调整。

另外,请参阅在这个 dist-list 线程 HBase,mail#user - Stargate + hbase 中的 David Butler 响应。

HBase过滤查询

根据具体情况,使用客户端请求过滤器可能是适当的。在这种情况下,不会创建二级索引。但是,请不要在应用程序(如单线程客户端)上对这样的大表进行全面扫描。

HBase定期更新二级索引

可以在另一个表中创建二级索引,通过 MapReduce 作业定期更新。该作业可以在一天内执行,但要取决于加载策略,它可能仍然可能与主数据表不同步。

HBase双写二次索引

另一种策略是在将数据发布到集群时构建二级索引(例如,写入数据表,写入索引表)。如果这是在数据表已经存在之后采取的方法,那么对于具有 MapReduce 作业的二级索引将需要引导。

HBase汇总表

在时间范围非常广泛的情况下(例如,长达一年的报告)以及数据量大的地方,汇总表是一种常见的方法。这些将通过 MapReduce 作业生成到另一个表中。

HBase协处理器二级索引

协处理器行为类似于 RDBMS 触发器。这些在 0.92 增加。



HBase 限制因素


HBase模式(Schema)设计案例


HBase模式案例:日志数据和时间序列数据

本节为你介绍了 HBase 模式案例之一:日志数据和时间序列数据

假设正在收集以下数据元素。

  • 主机名(Hostname)- 时间戳(timestamp)- 日志事件(Log event)- 值/消息(Value/message)
    时间戳(timestamp)

值/消息(Value/message)

我们可以将它们存储在名为 LOG_DATA 的 HBase 表中,但 rowkey 会是什么呢?从这些属性中,rowkey 将是主机名,时间戳和日志事件的一些组合,但具体是什么?

行密钥(Rowkey)主导位置中的时间戳(Timestamp)

rowkey [timestamp][hostname][log-event] 受单调递增的行键/时间戳数据(Monotonically Increasing Row Keys/Timeseries Data)中描述的单调增长 rowkey 问题的影响。

通过在时间戳上执行 mod 操作,在关于 “bucketing” 时间戳的 dist-lists 中经常提到另一种模式。如果时间扫描很重要,这可能是一个有用的方法。必须注意 bucket 的数量,因为这需要相同数量的扫描来返回结果。

构造:

如上所述,要选择特定时间范围(timerange)的数据,需要为每个存储 bucket 执行 Scan。例如,100个存储 bucket 将在密钥空间中提供广泛的分布,但它需要 100 次 Scan 才能获得单个时间戳的数据,因此存在权衡。

行密钥(Rowkey)主导位置中的主机(Host)

如果有大量的主机在整个密钥空间中进行写入和读取操作,则 rowkey [hostname][log-event][timestamp] 是一个候选项。如果按主机名扫描是优先事项,则此方法非常有用。

时间戳或反向时间戳

如果最重要的访问路径是拉取最近的事件,则将时间戳存储为反向时间戳(例如,timestamp = Long.MAX_VALUE – timestamp)将创建能够对 [hostname][log-event] 执行 Scan 以获取最近捕获的事件的属性。

这两种方法都不是错的,它只取决于什么是最适合的情况。

反向扫描 API

HBASE-4811 实现了一个 API,它以反向扫描表格或范围内的表格,从而减少了对正向或反向扫描进行模式优化的需求。此功能在 HBase 0.98 和更高版本中可用。

可变长度或固定长度的行键

记住,在 HBase 的每一列上加盖行密码是非常重要的。如果主机名为 a,并且事件类型是 e1,那么结果 rowkey 会很小。但是,如果摄入的主机名是myserver1.mycompany.com 和事件类型是 com.package1.subpackage2.subsubpackage3.ImportantService,会怎么样?

在 rowkey 中使用一些替换可能是有意义的。至少有两种方法:哈希和数字。在 Rowkey Lead Position 示例中的主机名中,它可能如下所示:

带有哈希的复合 Rowkey:

  • [主机名的MD5哈希] = 16个字节([MD5 hash of hostname] = 16 bytes)- [事件类型的MD5哈希] = 16个字节([MD5 hash of event-type] = 16 bytes)- [时间戳] = 8个字节([timestamp] = 8 bytes)
    [事件类型的MD5哈希] = 16个字节([MD5 hash of event-type] = 16 bytes)

具有数值替换的复合 Rowkey:

对于这种方法,除了 LOG_DATA(称为LOG_TYPES)之外,还需要另一个查找表。LOG_TYPES 的 rowkey 是:

  • [type],(例如,指示主机名与事件类型的字节)。- [bytes],原始主机名或事件类型的可变长度字节。
    [bytes],原始主机名或事件类型的可变长度字节。

此 rowkey 的列可能是一个具有指定编号的长整数,可通过使用 HBase 计数器获得。

所以得到的复合 rowkey 将是:

  • [代替主机名长] = 8个字节([substituted long for hostname] = 8 bytes)- [长时间取代事件类型] = 8个字节([substituted long for event type] = 8 bytes)- [时间戳] = 8个字节([timestamp] = 8 bytes)
    [长时间取代事件类型] = 8个字节([substituted long for event type] = 8 bytes)

在 Hash 或 Numeric 替换方法中,主机名和事件类型的原始值可以存储为列。



HBase模式案例:Steroids上的日志数据/时间序列上

这实际上是 OpenTSDB 的方法。OpenTSDB 做的是重写数据并将行打包到某些时间段中的列中。

但是,这是一般概念的工作原理:例如,以这种方式摄入数据:



HBase模式案例:客户/订单

假设 HBase 用于存储客户和订单信息。有两种核心记录类型被摄取:客户记录类型和订单记录类型。

客户记录类型将包含您通常期望的所有内容:

  • 客户编号
    - 客户名称
    - 地址(例如,城市,州,邮编)- 电话号码等
    客户名称

电话号码等

订单记录类型将包含如下内容:

  • 客户编号
    - 订单编号
    - 销售日期- 一系列用于装运位置和订单项的嵌套对象
    订单编号

一系列用于装运位置和订单项的嵌套对象

假设客户编号和销售订单的组合唯一地标识一个订单,对于一个订单(ORDER)表,这两个属性将组成 rowkey,特别是一个组合键,例如:

但是,还有更多的设计决策需要:原始值是 rowkeys 的最佳选择吗?

Log Data 用例中的相同设计问题在这里面对我们。客户编号的密钥空间是什么,以及格式是什么(例如,数字或是字母数字?)由于在HBase中使用固定长度的密钥以及可以在密钥空间中支持合理分布的密钥是有利的,因此会出现类似的选项:

带有哈希的复合 Rowkey:

  • [客户号码的 MD5] = 16字节- [订单号的 MD5] = 16字节
    [订单号的 MD5] = 16字节

复合数字/哈希组合 Rowkey:

  • [代替客户编号] = 8个字节- [订单号的 MD5] = 16字节
    [订单号的 MD5] = 16字节

单个表/多个表

传统的设计方法会为有单独的 CUSTOMER 和 SALES 表格。另一种选择是将多个记录类型打包到一个表中(例如,CUSTOMER ++)。

客户记录类型 Rowkey:

  • [customer-id]
    - [type] = 表示客户记录类型为’1’的类型
    [type] = 表示客户记录类型为’1’的类型

订单记录类型Rowkey:

  • [customer-id]
    - [type] = 指示订单记录类型为’2’的类型- [order]

    [type] = 指示订单记录类型为’2’的类型

这种特殊的 CUSTOMER ++ 方法的优点是通过客户 ID 来组织许多不同的记录类型(例如,一次扫描就可以得到关于该客户的所有信息)。缺点是扫描特定的记录类型并不容易。

HBase订单对象设计

现在我们需要解决如何建模 Order 对象。假设类结构如下:

Order

Order 可以有多个 ShippingLocations

LineItem

一个 ShippingLocation 可以有多个 LineItems

存储这些数据有多种选择。

完全标准化

通过这种方法,ORDER,SHIPPING_LOCATION和LINE_ITEM 将会有单独的表格。

上面描述了 ORDER 表的 rowkey:schema.casestudies.custorder

SHIPPING_LOCATION 的复合 rowkey 就像这样:

  • [order-rowkey]- [shipping location number] (例如,第一地点,第二地点等)
    [shipping location number] (例如,第一地点,第二地点等)

LINE_ITEM 表的复合 rowkey 将如下所示:

  • [order-rowkey]- [shipping location number] (例如,第一地点,第二地点等)- [line item number] (例如,第一条线,第二条等)
    [shipping location number] (例如,第一地点,第二地点等)

这样的标准化模型很可能是 RDBMS 的方法,但这不是 HBase 唯一的选择。这种做法的缺点是要检索任何订单的信息,您需要:

  • 获取订单的订单表- 在 SHIPPING_LOCATION 表上扫描该订单以获取 ShippingLocation 实例- 扫描每个 ShippingLocation 的 LINE_ITEM
    在 SHIPPING_LOCATION 表上扫描该订单以获取 ShippingLocation 实例

这是一个 RDBMS 无论如何都会在封面下做的事情,但由于 HBase 中没有加入,所以您只是更加意识到这一点。

具有记录类型的单个表

采用这种方法,将会存在一个包含单个表的ORDER

Order rowkey 如上所述:schema.casestudies.custorder

  • [order-rowkey]- [ORDER record type]
    [ORDER record type]

ShippingLocation 复合 rowkey 将如下所示:

  • [order-rowkey]- [SHIPPING record type]- [shipping location number] (例如,第一地点,第二地点等)
    [SHIPPING record type]

LineItem 复合 rowkey 将如下所示:

  • [order-rowkey]- [LINE record type]- [shipping location number] (例如,第一地点,第二地点等)- [line item number] (例如,第一条线,第二条等)
    [LINE record type]

[line item number] (例如,第一条线,第二条等)

非规范化

具有记录类型的单个表格的一种变体是对一些对象层次结构进行非规范化和扁平化,比如将 ShippingLocation 属性折叠到每个 LineItem 实例上。

LineItem 复合 rowkey 将如下所示:

  • [order-rowkey]- [LINE record type]- [line item number] (例如,第一条线,第二条等,必须注意的是,在整个订单中都是唯一的)
    [LINE record type]

LineItem 列将是这样的:

  • 项目编号(itemNumber)- 数量(quantity)- 价钱(price)- shipToLine1(从 ShippingLocation 非正规化)- shipToLine2(从 ShippingLocation 非正规化)- shipToCity(从 ShippingLocation 非正规化)- shipToState(从 ShippingLocation 非正规化)- shipToZip(从 ShippingLocation 非正规化)
    数量(quantity)

shipToLine1(从 ShippingLocation 非正规化)

shipToCity(从 ShippingLocation 非正规化)

shipToZip(从 ShippingLocation 非正规化)

这种方法的优点包括不太复杂的对象层次结构,但其中一个缺点是,如果这些信息发生变化,更新会变得更加复杂。

BLOB对象

通过这种方法,整个 Order 对象图都以某种方式处理为 BLOB。例如,上面描述了 ORDER 表的 rowkey:schema.casestudies.custorder,而一个名为“order”的列将包含一个可以反序列化的对象,该对象包含一个容器 Order,ShippingLocations 和 LineItems。

这里有很多选项:JSON,XML,Java 序列化,Avro,Hadoop Writable等等。所有这些都是相同方法的变体:将对象图编码为字节数组。应该注意这种方法,以确保在对象模型发生更改时保持向后兼容性,使旧的持久结构仍能从 HBase 中读出。

优点是能够以最少的 I/O 来管理复杂的对象图(例如,在本例中每个 HBase Get 有 Order),但缺点包括前面提到的关于序列化的向后兼容性,序列化的语言依赖性(例如 Java 序列化只适用于 Java 客户端),事实上你必须反序列化整个对象才能获得 BLOB 中的任何信息,以及像 Hive 这样的框架难以使用像这样的自定义对象。



HBase模式案例:“高/宽/中”架构设计Smackdown

本节将介绍出现在远程列表中的其他模式设计问题,特别是关于高和宽表。这些是一般准则而不是法律 - 每个应用程序都必须考虑到自己的需求。

HBase行与版本

一个常见的问题是应该更喜欢行还是 HBase 的内置版本。上下文通常是保留行的“多个”版本的地方(例如,它明显高于1个最大版本的HBase默认值)。rows-approach 需要在 rowkey 的某些部分存储一个时间戳,以便在每次连续更新时不会覆盖它们。

首选项:行(一般来说)。

HBase行与列

另一个常见问题是,是否应该更喜欢行还是列。上下文通常在宽表格的极端情况下,例如具有1行100万个属性,或每100万行1列。

首选项:行(一般来说)。需要说明的是,本指南在上下文中是非常宽泛的情况,而不是标准的用例,其中需要存储几十或者一百列。但是这两个选项之间也有一条中间路径,那就是“行作为列”。

HBase行作为列

HBase行与列之间的中间路径将打包数据,对于某些行,这些数据将成为单独的行。在这种情况下,OpenTSDB就是最好的例子,其中一行表示一个定义的时间范围,然后将离散事件视为列。这种方法通常更加复杂,并且可能需要重写数据的额外复杂性,但具有 I/O高效的优点。



HBase模式案例研究:列表数据

以下是用户 dist-list 中关于一个相当常见问题的的交流:如何处理 Apache HBase 中的每个用户列表数据。

问题:

我们正在研究如何在 HBase 中存储大量(每用户)列表数据,并且我们试图弄清楚哪种访问模式最有意义。一种选择是将大部分数据存储在一个密钥中,所以我们可以有如下的内容:

我们的另一个选择是完全使用如下内容:

每行将包含多个值。所以在一种情况下,读取前三十个值将是:

而在第二种情况下会是这样:

一般的使用模式是只读取这些列表的前30个值,并且很少的访问会深入到列表中。一些用户在这些列表中总共有30个值,并且一些用户将拥有数百万(即幂律分布)。

单值格式似乎会占用 HBase 上的更多空间,但会提供一些改进的检索/分页灵活性。是否有任何显着的性能优势能够通过获取和扫描的页面进行分页?

我最初的理解是,如果我们的分页大小未知(并且缓存设置恰当),那么执行扫描应该会更快,但如果我们始终需要相同的页面大小,则扫描速度应该更快。我听到不同的人告诉了我关于表现的相反事情。我假设页面大小会相对一致,所以对于大多数使用情况,我们可以保证我们只需要固定页面长度的情况下的一页数据。我还会假设我们将不经常更新,但可能会插入这些列表的中间(这意味着我们需要更新所有后续行)。

答案:

如果我理解正确,你最终试图以“user,valueid,value”的形式存储三元组,对吗?例如:

(但用户名是固定宽度,而 valueids 是固定宽度)。

而且,您的访问模式符合以下要求:“对于用户 X,列出接下来的30个值,以valueid Y开头”。是对的吗?这些值应该按 valueid 排序返回?

tl、dr 版本是,你可能应该为每个用户+值添加一行,除非你确定需要,否则不要自行构建复杂的行内分页方案。

您的两个选项反映了人们在设计 HBase 模式时常见的问题:我应该选择“高”还是“宽”?您的第一个模式是“高(tall)”:每行代表一个用户的一个值,因此每个用户的表中有很多行;行键是 user + valueid,并且会有(可能)单个列限定符,表示“值(value)”。如果您希望按行键来扫描排序顺序中的行, 这是很好的。你可以在任何用户 + valueid 开始扫描,阅读下一个30,并完成。你放弃的是能够在一个用户的所有行周围提供事务保证,但它听起来并不像你需要的那样。

第二个选项是“宽”:使用不同的限定符(其中限定符是valueid)将一堆值存储在一行中。简单的做法是将一个用户的所有值存储在一行中。我猜你跳到了“分页”版本,因为你认为在单行中存储数百万列会对性能造成影响,这可能是也可能不是真的; 只要你不想在单个请求中做太多事情,或者做一些事情,比如扫描并返回行中的所有单元格,它不应该从根本上变坏。客户端具有允许您获取特定的列的片段的方法。

请注意,这两种情况都不会从根本上占用更多的磁盘空间; 您只是将部分识别信息“移动”到左侧(在行键中,在选项一中)或向右(在选项2中的列限定符中)。在封面下,每个键/值仍然存储整个行键和列名称。

正如你注意到的那样,手动分页版本有很多复杂性,例如必须跟踪每个页面中有多少内容,如果插入新值,则重新洗牌等。这看起来要复杂得多。在极高的吞吐量下它可能有一些轻微的速度优势(或缺点!),而要真正知道这一点的唯一方法就是试用它。如果您没有时间来构建它并进行比较,我的建议是从最简单的选项开始(每个用户 + valueid)。开始简单并重复!



HBase 操作和性能配置选项

调试HBase服务器RPC处理

  • 设置 hbase.regionserver.handler.count(在 hbase-site.xml)为用于并发的核心 x 轴。- 可选地,将调用队列分成单独的读取和写入队列以用于区分服务。该参数 hbase.ipc.server.callqueue.handler.factor 指定调用队列的数量:
    • - 0 意味着单个共享队列。
      可选地,将调用队列分成单独的读取和写入队列以用于区分服务。该参数 hbase.ipc.server.callqueue.handler.factor 指定调用队列的数量:
  • 1 意味着每个处理程序的一个队列。- 一个0和1之间的值,按处理程序的数量成比例地分配队列数。例如,0.5 的值在每个处理程序之间共享一个队列。
    使用 hbase.ipc.server.callqueue.read.ratio(hbase.ipc.server.callqueue.read.share在0.98中)将调用队列分成读写队列:
  • 0.5 意味着将有相同数量的读写队列。- <0.5 表示为读多于写。- >0.5 表示写多于读。
    设置 hbase.ipc.server.callqueue.scan.ratio(HBase 1.0+)将读取调用队列分为短读取和长读取队列:
  • 0.5 意味着将有相同数量的短读取和长读取队列。- <0.5表示更多的短读取队列。- >0.5表示更多的长读取队列。
    禁用RPC的Nagle

禁用 Nagle 的算法。延迟的 ACKs 可以增加到200毫秒的 RPC 往返时间。设置以下参数:

  • 在 Hadoop 的 core-site.xml 中:
    • - ipc.server.tcpnodelay = true
      ipc.server.tcpnodelay = true
  • ipc.client.tcpnodelay = true
    在 HBase 的 hbase-site.xml 中:
  • hbase.ipc.client.tcpnodelay = true- hbase.ipc.server.tcpnodelay = true
    限制服务器故障影响

尽可能快地检测区域服务器故障。设置以下参数:

  • 在 hbase-site.xml 中设置 zookeeper.session.timeout 为30秒或更短的时间内进行故障检测(20-30秒是一个好的开始)。- 检测并避免不健康或失败的 HDFS 数据节点:in hdfs-site.xml 和 hbase-site.xml 设置以下参数:
    • - dfs.namenode.avoid.read.stale.datanode = true
      检测并避免不健康或失败的 HDFS 数据节点:in hdfs-site.xml 和 hbase-site.xml 设置以下参数:
  • dfs.namenode.avoid.write.stale.datanode = true
    针对低延迟优化服务器端
  • 跳过本地块的网络。在 hbase-site.xml 中,设置以下参数:
    • - dfs.client.read.shortcircuit = true
      dfs.client.read.shortcircuit = true
  • dfs.client.read.shortcircuit.buffer.size = 131072 (重要的是避免 OOME)
    确保数据局部性。在 hbase-site.xml 中,设置 hbase.hstore.min.locality.to.skip.major.compact = 0.7(意味着 0.7 <= n <= 1)

确保 DataNode 有足够的处理程序进行块传输。在 hdfs-site.xml 中,设置以下参数:

  • dfs.datanode.max.xcievers >= 8192- dfs.datanode.handler.count = 主轴数量
    JVM调优

调整JVM GC以获取低收集延迟

  • 使用 CMS 收集器: -XX:+UseConcMarkSweepGC- 保持 eden 空间尽可能小,以减少平均收集时间。例:-XX:CMSInitiatingOccupancyFraction = 70- 优化低收集延迟而不是吞吐量: -Xmn512m- 并行收集 eden: -XX:+UseParNewGC- 避免在压力下收集: -XX:+UseCMSInitiatingOccupancyOnly- 限制每个请求扫描器的结果大小,所以一切都适合幸存者空间,但没有任职期限。在 hbase-site.xml 中,设置 hbase.client.scanner.max.result.size 为 eden 空间的1/8(使用 - Xmn512m,这里是〜51MB)- 设置 max.result.sizex handler.count 小于 survivor 空间
    保持 eden 空间尽可能小,以减少平均收集时间。例:-XX:CMSInitiatingOccupancyFraction = 70

并行收集 eden: -XX:+UseParNewGC

限制每个请求扫描器的结果大小,所以一切都适合幸存者空间,但没有任职期限。在 hbase-site.xml 中,设置 hbase.client.scanner.max.result.size 为 eden 空间的1/8(使用 - Xmn512m,这里是〜51MB)

OS级调整

  • 关闭透明的大页面(THP):- 设置 vm.swappiness = 0- 设置 vm.min_free_kbytes 为至少 1GB(较大内存系统为 8GB)- 使用 vm.zone_reclaim_mode = 0 禁用 NUMA 区域回收。
    设置 vm.min_free_kbytes 为至少 1GB(较大内存系统为 8GB)


HBase 特殊情况

对于快速失败优于等待的应用程序

  • 在客户端的 hbase-site.xml 中,设置以下参数:
    • - 设置 hbase.client.pause = 1000
      设置 hbase.client.pause = 1000
  • 设置 hbase.client.retries.number = 3- 如果你想跨越分裂和区域移动,大幅增加 hbase.client.retries.number(> = 20)- 设置 RecoverableZookeeper 重试计数: zookeeper.recovery.retry = 1(不重试)
    在 hbase-site.xml 服务器端,设置 Zookeeper 会话超时以检测服务器故障:zookeeper.session.timeout⇐30秒(建议 20-30)。

对于可以容忍略有过时的信息的应用程序

HBase 时间线一致性(HBASE-10070) 启用了只读副本后,区域(副本)的只读副本将分布在群集中。一个 RegionServer 为默认或主副本提供服务,这是唯一可以服务写入的副本。其他 Region Server 服务于辅助副本,请遵循主要 RegionServer,并仅查看提交的更新。辅助副本是只读的,但可以在主服务器故障时立即提供读取操作,从而将读取可用性的时间间隔从几秒钟减少到几毫秒。Phoenix 支持时间线一致性为 4.4.0 的提示:

  • 部署 HBase 1.0.0 或更高版本。- 在服务器端启用时间线一致性副本。- 使用以下方法之一设置时间线一致性:
    • - 使用 ALTER SESSION SET CONSISTENCY = 'TIMELINE’
      在服务器端启用时间线一致性副本。

使用 ALTER SESSION SET CONSISTENCY = 'TIMELINE’

  • 在JDBC连接字符串中设置连接属性 Consistency 为 timeline


HBase和MapReduce

Apache MapReduce 是一个用于分析大量数据的软件框架。它由 Apache Hadoop 提供。MapReduce 本身超出了本文档的范围。开始使用 MapReduce 的好地方是 https://hadoop.apache.org/docs/r2.6.0/hadoop-mapreduce-client/hadoop-mapreduce-client-core/MapReduceTutorial.html。MapReduce 版本2(MR2)现在是 YARN 的一部分。

本章讨论在 HBase 中对数据使用 MapReduce 时需要采取的具体配置步骤。另外,它讨论了 HBase 和 MapReduce 作业之间的其他交互和问题。最后,它讨论了Cascading,MapReduce 的另一种 API。

mapred 和 mapreduce

HBase 中有两个 mapreduce 包,就像 MapReduce 本身一样:org.apache.hadoop.hbase.mapred 和org.apache.hadoop.hbase.mapreduce。前者使用旧式 API,后者使用新模式。后者有更多的设施,尽管你通常可以在旧的包装中找到相同的设备。选择与MapReduce 部署配合使用的软件包。如果有疑问或重新开始,请选择org.apache.hadoop.hbase.mapreduce。在下面的注释中,我们引用了oahhmapreduce,但是如果这是你正在使用的,则用 oahhmapred 替换。



HBase、MapReduce和CLASSPATH

默认情况下,部署到 MapReduce 集群的 MapReduce 作业无权访问 $HBASE_CONF_DIR 类或 HBase 类下的 HBase 配置。

要为 MapReduce 作业提供他们需要的访问权限,可以添加 hbase-site.xml_to _ $ HADOOP_HOME / conf,并将 HBase jar 添加到 $ HADOOP_HOME / lib 目录。然后,您需要在群集中复制这些更改。或者你可以编辑 $ HADOOP_HOME / conf / hadoop-env.sh,并将 hbase 依赖添加到HADOOP_CLASSPATH 变量中。这两种方法都不推荐使用,因为它会使用 HBase 引用污染您的 Hadoop 安装。它还需要您在 Hadoop 可以使用 HBase 数据之前重新启动 Hadoop 集群。

推荐的方法是让 HBase 添加它的依赖 jar 并使用 HADOOP_CLASSPATHor -libjars。

自 HBase 0.90.x 以来,HBase 将其依赖 JAR 添加到作业配置本身。依赖关系只需要在本地 CLASSPATH 可用,从这里它们将被拾取并捆绑到部署到MapReduce 集群的 fat 工作 jar 中。一个基本的技巧就是将完整的 hbase 类路径(所有 hbase 和依赖 jar 以及配置)传递给 mapreduce 作业运行器,让hbase 实用程序从完整类路径中选取需要将其添加到 MapReduce 作业配置中的源代码。

下面的示例针对名为 usertable 的表运行捆绑的 HBase RowCounter MapReduce 作业。它设置为 HADOOP_CLASSPATH 需要在 MapReduce 上下文中运行的 jar 包(包括配置文件,如 hbase-site.xml)。确保为您的系统使用正确版本的 HBase JAR;请在下面的命令行中替换 VERSION 字符串 w/本地 hbase 安装的版本。反引号(`符号)使 shell 执行子命令,设置输入 hbase classpath 为 HADOOP_CLASSPATH。这个例子假设你使用 BASH 兼容的 shell。

hbase-mapreduce.jar 的主要内容是一个 Driver(驱动程序),它列出了几个与 hbase 一起使用的基本 mapreduce 任务。例如,假设您的安装是hbase 2.0.0-SNAPSHOT:

对于不打包它们的依赖关系或调用 TableMapReduceUtil#addDependencyJars 的作业,以下命令结构是必需的:

如果您从构建目录运行 HBase 而不是安装位置,该示例可能无法运行。您可能会看到类似以下的错误:

一些使用 HBase 的 MapReduce 作业无法启动。该症状是类似于以下情况的异常:

这会影响两个作业,即使用 libjars 选项和  “fat jar” (在嵌套的 lib 文件夹中打包其运行时依赖项)。

为了满足新的加载器要求,hbase-protocol.jar 必须包含在 Hadoop 的类路径中。以下内容包括用于历史目的。

通过在 Hadoop 的 lib 目录中包括对 hbase-protocol.jar 协议的引用,通过 symlink 或将 jar 复制到新的位置,可以解决整个系统。

这也可以通过 HADOOP_CLASSPATH 在作业提交时将它包含在环境变量中来实现。启动打包依赖关系的作业时,以下所有三个启动命令均满足此要求:

对于不打包它们的依赖关系的 jar,下面的命令结构是必需的:



MapReduce扫描缓存

现在,TableMapReduceUtil 恢复了在传入的 Scan 对象中设置扫描程序缓存(在将结果返回给客户端之前缓存的行数)的选项。由于 HBase 0.95(HBASE-11558)中的错误,此功能丢失。这是为 HBase 0.98.5 和0.96.3 而定的。选择扫描仪缓存的优先顺序如下:

  1. 在扫描对象上设置的缓存设置。
    1. 通过配置选项 hbase.client.scanner.caching 指定的缓存设置,可以在 hbase-site.xml 中手动设置或通过辅助方法 TableMapReduceUtil.setScannerCaching() 设置。1. 默认值 HConstants.DEFAULT_HBASE_CLIENT_SCANNER_CACHING,设置为 100。
    通过配置选项 hbase.client.scanner.caching 指定的缓存设置,可以在 hbase-site.xml 中手动设置或通过辅助方法 TableMapReduceUtil.setScannerCaching() 设置。

优化缓存设置是客户端等待结果的时间和客户端需要接收的结果集的数量之间的一种平衡。如果缓存设置过大,客户端可能会等待很长时间,否则请求可能会超时。如果设置太小,扫描需要返回几个结果。如果将 scan 视为 shovel,则更大的缓存设置类似于更大的 shovel,而更小的缓存设置相当于更多的 shovel,以填充 bucket。

上面提到的优先级列表允许您设置合理的默认值,并针对特定操作对其进行覆盖。



捆绑HBase MapReduce作业

HBase JAR 也可作为一些捆绑 MapReduce 作业的驱动程序。要了解捆绑的 MapReduce 作业,请运行以下命令:

每个有效的程序名都是捆绑的 MapReduce 作业。要运行其中一个作业,请在下面的示例之后为您的命令建模。



HBase作为MapReduce作业数据源和数据接收器

对于 MapReduce 作业,HBase 可以用作数据源、TableInputFormat 和数据接收器、TableOutputFormat 或 MultiTableOutputFormat。编写读取或写入HBase 的 MapReduce作业,建议子类化 TableMapper 或 TableReducer。

如果您运行使用 HBase 作为源或接收器的 MapReduce 作业,则需要在配置中指定源和接收器表和列名称。

当您从 HBase 读取时,TableInputFormat 请求 HBase 的区域列表并制作一张映射,可以是一个 map-per-region 或 mapreduce.job.maps mapreduce.job.maps ,映射到大于区域数目的数字。如果您为每个节点运行 TaskTracer/NodeManager 和 RegionServer,则映射将在相邻的 TaskTracker/NodeManager 上运行。在写入 HBase 时,避免使用 Reduce 步骤并从映射中写回 HBase 是有意义的。当您的作业不需要 MapReduce 对映射发出的数据进行排序和排序时,这种方法就可以工作。在插入时,HBase ‘sorts’,因此除非需要,否则双重排序(并在您的 MapReduce 集群周围混洗数据)没有意义。如果您不需要 Reduce,则映射可能会发出在作业结束时为报告处理的记录计数,或者将 Reduces 的数量设置为零并使用 TableOutputFormat。如果运行 Reduce 步骤在你的情况下是有意义的,则通常应使用多个减速器,以便在 HBase 群集上传播负载。

一个新的 HBase 分区程序 HRegionPartitioner 可以运行与现有区域数量一样多的 reducers。当您的表格很大时,HRegionPartitioner 是合适的,并且您的上传不会在完成时大大改变现有区域的数量。否则使用默认分区程序。



在批量导入时直接写入HFiles


RowCounter示例

包含的 RowCounter MapReduce 作业使用 TableInputFormat,并对指定表中的所有行进行计数。要运行它,请使用以下命令:

这将调用 HBase MapReduce 驱动程序类。从提供的工作选择中进行选择 rowcounter。这将打印 rowcounter 使用建议到标准输出。指定表名,要计数的列和输出目录。



Map-Task分割

默认的 HBase MapReduce Splitter

当 TableInputFormat 用于在 MapReduce 作业中发送 HBase 表时,其分割器将为表的每个区域创建一个映射任务。因此,如果表格中有 100 个区域,则无论在“扫描(Scan)”中选择多少个列族,该作业都会有 100 个 map-task。

自定义分配器

对于那些有兴趣在实现自定义的分割器的人,请参见 TableInputFormatBase 中 getSplits 的方法。这是 map-task 分配的逻辑所在。



HBase MapReduce示例


HBase MapReduce 读取示例

以下是以只读方式将 HBase 用作 MapReduce 源的示例。具体来说,有一个 Mapper 实例,但没有 Reducer,并且没有任何内容从 Mapper 发出。这项工作将被定义如下:

映射器实例将扩展 TableMapper:




HBase MapReduce读写示例

以下是使用 HBase 作为 MapReduce 的源代码和接收器的示例。这个例子将简单地将数据从一个表复制到另一个表。

需要解释的是 TableMapReduceUtil 正在做什么,特别是对于减速器。TableOutputFormat 被用作 outputFormat 类,并且正在配置几个参数(例如,TableOutputFormat.OUTPUT_TABLE),以及将 reducer 输出键设置为 ImmutableBytesWritable 和 reducer 值为 Writable。这些可以由程序员在作业和 conf 中设置,但 TableMapReduceUtil 试图让事情变得更容易。

以下是示例映射器,它将创建 Put 并匹配输入 Result 并发出它。注意:这是 CopyTable 实用程序的功能。

实际上并没有一个简化步骤,所以 TableOutputFormat 负责将 Put 发送到目标表。

这只是一个例子,开发人员可以选择不使用 TableOutputFormat 并连接到目标表



HBase MapReduce摘要到HBase示例

以下的示例使用 HBase 作为 MapReduce 源,并使用一个总结步骤。此示例将计算表中某个值的不同实例的数量,并将这些汇总计数写入另一个表中。

在此示例映射器中,选择一个带有字符串值的列作为要汇总的值。该值用作从映射器发出的密钥,IntWritable 代表实例计数器。

在 reducer 中,“ones” 被计数(就像任何其他的 MR 例子一样),然后发出一个 Put。



HBase MapReduce摘要到文件示例

这与HBase MapReduce摘要到HBase示例非常相似,不同之处在于,它将 HBase 用作 MapReduce 源,但将 HDFS 用作接收器。差异在于作业设置和减速器中。映射器保持不变。

如上所述,前面的Mapper可以与此示例保持不变。至于减速机,它是一种“通用”的减速机,而不是扩展的制表机和发射装置。



HBase MapReduce摘要到没有Reducer的HBase

如果您使用 HBase 作为减速器(reducer),也可以在不使用减速器的情况下执行摘要。

工作摘要需要 HBase 目标表。Table 方法 incrementColumnValue 将用于自动增加值。从性能角度来看,对于每个 map-task,保留一个 value 值为 map 的值,并且 在 mapper 的 cleanup 方法期间为每个 key 设置一次更新可能是有意义的。但是,根据要处理的行数和唯一键的不同,您的里程可能会有所不同。

最后,摘要结果在 HBase 中。



HBase MapReduce摘要到RDBMS

有时候给 RDBMS 生成摘要更为合适。对于这些情况,可以通过自定义减速器直接向 RDBMS 生成摘要。该 setup 方法可以连接到 RDBMS(连接信息可以通过上下文中的自定义参数传递),并且清理方法可以关闭连接。

有时候给 RDBMS 生成摘要更为合适。对于这些情况,可以通过自定义减速器直接向 RDBMS 生成摘要。该 setup 方法可以连接到 RDBMS(连接信息可以通过上下文中的自定义参数传递),并且清理方法可以关闭连接。

重要的是,要了解工作中的减速器的数量会影响到摘要的实现,您必须将其设计到您的减速器中。具体而言,它是否被设计为以单例(一个减速器)或多个减速器运行。是或不是,这取决于你的用例。认识到分配给作业的减速者越多,同时建立到 RDBMS 的连接就会越多 - 这将会扩展,但仅限于某一点。

最后,摘要结果将写入您的 RDBMS 表。



访问MapReduce作业中的其他HBase表

尽管当前框架允许一个 HBase 表作为 MapReduce 作业的输入,其他的HBase表可以作为查找表来访问,等等,在 MapReduce 作业中,通过在 Mapper 的 setup 方法中创建一个 Table 实例。



HBase 推测执行


MapReduce的替代API:Cascading

Cascading 是 MapReduce 的替代 API,它实际上使用 MapReduce,但允许您以简化的方式编写 MapReduce 代码。

以下示例显示了 Cascading Flow,它将数据“汇集(sinks)”到 HBase 集群中。同样的 hBaseTap API 也可以用于“源(source)”数据:



Apache HBase安全

安全漏洞报告

为了保护现有的 HBase 安装,请不要使用 JIRA 报告与安全相关的 bug。

HBase 遵循 Apache Software Foundation 关于报告漏洞的策略,可在 http://apache.org/security/ 上找到。

如果您希望发送一个加密的报告,您可以使用 GPG 的详细信息来提供一般的 ASF 安全列表。这可能会增加您报告的响应时间。

HBase 提供了一些机制来保护 HBase 的各种组件和 aspect,以及它如何与 Hadoop 基础架构的其余部分以及 Hadoop 之外的客户端和资源相关联。



为Web UI使用安全HTTP(HTTPS)

默认的 HBase 安装为主服务器和区域服务器的 Web UI 使用不安全的 HTTP 连接。要启用安全的 HTTP(HTTPS)连接,请在 hbase-site.xml 中设置 hbase.ssl.enabled 为 true。这不会更改 Web UI 使用的端口。要更改给定 HBase 组件的 Web UI 的端口,请在 hbase-site.xml 中配置该端口的设置。这些设置包括:

  • hbase.master.info.port- hbase.regionserver.info.port
    hbase.regionserver.info.port

如果启用 HTTPS,则客户端应该避免使用非安全的 HTTP 连接。

如果您启用了安全的 HTTP,则客户端应该使用 https:// URL 连接到 HBase。使用 http:// URL 的客户端将收到 200个 HTTP 响应,但不会接收任何数据。日志记录如下异常:

这是因为同一个端口用于 HTTP 和 HTTPS。

HBase 使用 Jetty 作为 Web UI。如果不修改 Jetty 本身,就不可能将 Jetty 配置为将一个端口重定向到同一主机上的另一个端口。如果您知道如何解决这个问题,而无需打开另一个 HTTPS 端口,则可以使用补丁程序。



将SPNEGO用于Web UI的Kerberos身份验证

通过使用 hbase-site.xml 中的 hbase.security.authentication.ui 属性配置 SPNEGO,可以启用对 HBase Web UI 的 Kerberos 身份验证(Kerberos-authentication)。启用此身份验证要求 HBase 也配置为对 RPC 使用 Kerberos 身份验证(例如,

通过使用 hbase-site.xml 中的 hbase.security.authentication.ui 属性配置 SPNEGO,可以启用对 HBase Web UI 的 Kerberos 身份验证(Kerberos-authentication)。启用此身份验证要求 HBase 也配置为对 RPC 使用 Kerberos 身份验证(例如,hbase.security.authentication = kerberos)。

存在许多用于为 Web 服务器配置 SPNEGO 身份验证的属性:



客户端安全访问Apache HBase

较新版本的 Apache HBase(> = 0.92)支持客户端的可选 SASL 身份验证。另请参阅 Matteo Bertozzi 关于了解 Apache HBase 中的用户身份验证和授权的文章。

本小章介绍如何设置 Apache HBase 和客户端以连接到安全 HBase 资源。

Hadoop 认证配置

要使用强身份验证运行 HBase RPC,您必须设置hbase.security.authentication为kerberos。在这种情况下,您还必须在 core-site.xml 中设置hadoop.security.authentication为kerberos。否则,您将对 HBase 使用强身份验证,但不会对基础 HDFS 使用强身份验证,否则会取消任何收益。

Kerberos KDC

您需要有一个可用的 Kerberos KDC。



HBase:用于安全操作的服务器端配置

首先,请参考“客户端安全访问Apache HBase”,以确保您的基础 HDFS 配置是安全的。

将以下内容添加到群集中每个服务器计算机上的 hbase-site.xml 文件中:

部署这些配置更改时,需要完全关闭并重新启动 HBase 服务。



HBase:用于安全操作的客户端配置

首先,请参阅“客户端安全访问Apache HBase”并确保您的基础 HDFS 配置是安全的。

将以下内容添加到每个客户端上的 hbase-site.xml 文件中:

客户端环境必须通过 kinit 命令从 KDC 或 keytab 登录到 Kerberos,然后才能与 HBase 群集通信。

请注意,如果客户端和服务器端站点文件中的 hbase.security.authentication 不匹配,则客户端将无法与群集进行通信。

一旦将 HBase 配置为安全 RPC,就可以选择配置加密通信。为此,请将以下内容添加到每个客户端上的 hbase-site.xml 文件中:

此配置属性也可以在每个连接的基础上进行设置。将其设置为 Configuration 提供给 Table:

对于加密通信,预计会有大约 10% 的性能损失。



用于安全操作的客户端配置:Thrift Gateway

将以下内容添加到每个Thrift网关的hbase-site.xml文件中:

分别替换“$ USER”和“$ KEYTAB”的相应凭证和密钥表。

为了使用Thrift API主体与HBase进行交互,还需要将hbase.thrift.kerberos.principal添加到该acl表中。例如,要赋予Thrift API主体,thrift_server,管理访问权限(administrative access),可以使用如下的命令:

Thrift网关将使用提供的凭证向HBase进行身份验证。Thrift网关本身不会执行任何身份验证。所有通过Thrift网关访问的客户端都将使用Thrift网关的凭证并拥有其权限。



配置Thrift网关以代表客户端进行身份验证

Thrift Gateway是用于安全操作的客户端配置,它描述了如何使用固定用户向HBase验证Thrift客户端。作为替代,您可以将Thrift网关配置为代表客户端向HBase进行身份验证,并使用代理用户访问HBase。这为Thrift 1在HBASE-11349中实现,并且为Thrift 2在HBASE-11474中实现。 

Thrift框架传输的局限性

如果使用框架传输,那么您目前还不能利用此功能,因为SASL目前不支持Thrift框架传输。

要启用它,请执行以下操作:

  1. 请确保Thrift以安全模式运行,方法是按照用于安全操作的客户端配置:Thrift Gateway中描述的过程。1. 确保HBase配置为允许代理用户,如REST网关模拟配置中所述。1. 在运行Thrift网关的每个群集节点的hbase-site.xml中,将该hbase.thrift.security.qop属性设置为以下三个值之一:privacy - 身份验证、完整性和保密性检查。integrity - 身份验证和完整性检查。authentication - 仅验证身份验证检查。1. 重新启动Thrift网关进程以使更改生效。如果一个节点正在运行Thrift,那么该jps命令的输出将列出一个ThriftServer进程。要停止节点上的Thrift,请运行该bin/hbase-daemon.sh stop thrift命令。要在节点上启动Thrift,请运行该bin/hbase-daemon.sh start thrift命令。
    确保HBase配置为允许代理用户,如REST网关模拟配置中所述。

privacy - 身份验证、完整性和保密性检查。

authentication - 仅验证身份验证检查。



配置Thrift网关以使用doAs功能

配置Thrift网关以代表客户端进行身份验证介绍了如何配置Thrift网关以代表客户端对HBase进行身份验证,以及如何使用代理用户访问HBase。这种方法的局限性在于,客户端使用特定的凭证集进行初始化后,在会话期间它不能更改这些凭证。但是,doAs功能提供了一种灵活的方法,可以使用相同客户端模拟多个主体。此功能在Thrift 1的HBASE-12640中属性,但目前不适用于Thrift 2。

要启用该doAs功能,请将以下内容添加到每个Thrift网关的hbase-site.xml文件中:

要在使用doAs模拟时允许代理用户,请将以下内容添加到每个HBase节点的hbase-site.xml文件中:

查看演示客户端, 以获得有关如何在客户端使用此功能的总体思路。



REST Gateway:客户端安全操作配置

将以下内容添加到每个REST网关的hbase-site.xml文件中:

分别为$ USER和$ KEYTAB替换适当的凭证和密钥表。

REST网关将使用提供的凭证对HBase进行身份验证。

为了使用REST API主体与HBase进行交互,还需要将hbase.rest.kerberos.principal添加到该acl表中。例如,要赋予REST API主体、rest_server、管理访问权限,像以下的命令就足够了:

HBase REST网关支持SPNEGO HTTP身份验证,以便客户端访问网关。要为客户端访问启用REST网关Kerberos身份验证,请将以下内容添加到每个REST网关的hbase-site.xml文件中:

用$ KEYTAB替代HTTP的keytab 。

HBase REST网关支持不同的’hbase.rest.authentication.type’:simple、kerberos。您也可以通过实现Hadoop AuthenticationHandler来实现自定义身份验证,然后将完整的类名称指定为’hbase.rest.authentication.type’值。



REST Gateway模拟配置

默认情况下,REST Gateway(REST网关)不支持模拟。它代表客户端访问HBase。对于HBase服务器,所有请求都来自REST网关用户,实际用户不详。您可以打开模拟支持。通过模拟,REST网关用户是代理用户。HBase服务器知道每个请求的实际/真实用户,因此它可以应用适当的授权。

要打开REST网关模拟,我们需要配置HBase服务器(主服务器和区域服务器)以允许代理用户;配置REST网关以启用模拟。

要允许代理用户,请将以下内容添加到每个HBase服务器的hbase-site.xml文件中:

将REST网关代理用户替换为$ USER,并将允许的组列表替换为$ GROUPS。

要启用REST网关模拟,请将以下内容添加到每个REST网关的hbase-site.xml文件中:

用$ KEYTAB替代HTTP的keytab 。



用户访问Apache HBase的简单方法

较新版本的Apache HBase(0.92版本以后)支持客户端的可选SASL身份验证。

本节介绍如何设置Apache HBase和客户端,以便用户访问HBase资源。

简单与安全访问

以下部分介绍如何设置用户访问Apache HBase的一种简单方法。简单的用户访问不是一种运行HBase的安全方法。此方法用于防止用户犯错。它可用于在开发系统上模拟访问控制,而无需设置Kerberos。

此方法不用于防止恶意或黑客入侵。为了使HBase能够抵御这些类型的攻击,您必须配置HBase进行安全操作。请参阅客户端安全访问Apache HBase部分并完成此处描述的所有步骤。

简单用户访问操作的服务器端配置

将以下内容添加到群集中每个服务器计算机上的hbase-site.xml文件中:

对于Apache HBase 0.94版本,请将以下内容添加到集群中每台服务器计算机上的hbase-site.xml文件中:

部署这些配置更改时,需要完全关闭并重新启动HBase服务。

简单用户访问操作的客户端配置

将以下内容添加到每个客户端上的hbase-site.xml文件中:

对于Apache HBase 0.94版本,请将以下内容添加到集群中每台服务器计算机上的hbase-site.xml文件中:

请注意,如果客户端和服务器端站点文件中的hbase.security.authentication不匹配,则客户端将无法与群集进行通信。

简单用户访问操作的客户端配置 - Thrift Gateway

用户将需要访问Thrift网关。例如,要为Thrift API用户提供thrift_server管理访问,你可能需要使用如下的命令:

Thrift网关将使用提供的凭证向HBase进行身份验证。Thrift网关本身不会执行任何身份验证。所有通过Thrift网关访问的客户端都将使用Thrift网关的凭证并拥有其权限。

简单用户访问操作的客户端配置 - REST Gateway

REST网关将使用提供的凭证对HBase进行身份验证。REST网关本身不会执行任何身份验证。所有通过REST网关访问的客户端都将使用REST网关的凭证并拥有其权限。

REST网关用户将需要访问。例如,要为REST API用户提供rest_server管理访问,你可能需要使用如下的命令:



安全访问HDFS和ZooKeeper

HBase需要安全的ZooKeeper和HDFS,以便用户无法访问或修改HBase下的元数据和数据。HBase使用HDFS(或配置的文件系统)来保留其数据文件以及预写日志(WAL)和其他数据。HBase使用ZooKeeper来存储操作的一些元数据(主地址(master address),表锁(table locks),恢复状态(recovery state)等)。

保护ZooKeeper数据

ZooKeeper具有可插入的身份验证机制,可以使用不同的方法访问客户端。ZooKeeper甚至允许同时允许经过身份验证和未经身份验证的客户端。通过为每个znode提供访问控制列表(ACL)来限制对znodes的访问。ACL包含两个组件,即身份验证方法和主体。ACL不是分层强制执行的。

HBase守护程序通过SASL和Kerberos向ZooKeeper进行身份验证(请参阅使用ZooKeeper进行SASL身份验证)。HBase设置znode ACL,以便只有HBase用户和配置的hbase超级用户(hbase.superuser)可以访问和修改数据。在ZooKeeper用于服务发现或与客户端共享状态的情况下,由HBase创建的znodes也将允许任何人(不管身份验证)读取这些znode(clusterId,主地址,元位置等),但只有HBase用户可以修改它们。

保护文件系统(HDFS)数据

所有管理的数据都保存在文件系统(hbase.rootdir)的根目录下。访问文件系统中的数据和WAL文件应受到限制,以便用户不能绕过HBase层,并从文件系统中查看底层数据文件。HBase假定使用的文件系统(HDFS或其他)分层次地强制执行权限。如果没有提供足够的文件系统保护(授权和身份验证),HBase级别授权控制(ACL,可见性标签等)就没有意义,因为用户可以随时访问文件系统中的数据。

HBase对其根目录执行posix-like权限700(rwx------)。这意味着只有HBase用户可以读写FS中的文件。可以通过在hbase-site.xml中进行配置hbase.rootdir.perms来更改默认设置。需要重新启动活动主服务器,以便更改使用的权限。对于1.2.0之前的版本,您可以检查是否提交了HBASE-13780,如果没有,您可以根据需要手动设置根目录的权限。使用HDFS,该命令将是:

在安全模式下,应配置SecureBulkLoadEndpoint并将其用于正确地将从MR作业创建的用户文件移交给HBase守护程序和HBase用户。用于批量加载(hbase.bulkload.staging.dir默认为/tmp/hbase-staging)的分布式文件系统中的状态目录应具有(模式711或rwx—x—x),以便用户可以访问在该父目录下创建的状态目录,但无法执行任何其他操作。



HBase 数据安全

本节将介绍如何保证HBase数据的安全性。

在HBase客户端和服务器进程和网关之间配置了安全身份验证后,您需要考虑数据本身的安全性。HBase提供了下列的几种保护数据的策略:

  • 基于角色的访问控制(RBAC),它控制哪些用户或组可以使用熟悉的角色范例来读取和写入给定的HBase资源或执行协处理器端点。- 可见性标签,允许您标记单元格并控制对标记单元格的访问,以进一步限制谁可以读取或写入数据的某些子集。可见性标签存储为标签。- 在HFile和WAL中对底层文件系统的静态数据进行透明加密。这可以保护您的数据免受可以访问底层文件系统的攻击者的影响,而无需更改客户端的实现。它还可以防止不正确放置的磁盘泄漏数据,这对法律和法规遵从性可能很重要。
    可见性标签,允许您标记单元格并控制对标记单元格的访问,以进一步限制谁可以读取或写入数据的某些子集。可见性标签存储为标签。

在本章节的后续内容中,我们将介绍这些功能中的每个功能的服务器端配置、管理和实现细节,以及任何性能权衡。最后将给出一个安全配置示例,所有的功能一起使用。

HBase安全的各个方面都在积极发展和快速演变。您为了保护您的数据而采取的任何策略都应该进行彻底的测试。另外,其中一些功能还处于实验阶段。要利用其中的许多功能,您必须运行HBase 0.98+并使用HFile v3文件格式。

你需要保护敏感文件,本节中的几个过程要求您在群集节点之间复制文件。复制包含敏感字符串的密钥,配置文件或其他文件时,请使用安全方法(例如ssh,以避免泄露敏感数据)。

基本的服务器端配置

1、通过在hbase-site.xml中将hfile.format.version设置为3来启用HFile v3 。这是HBase 1.0和更高版本的默认值。

2、为RPC和ZooKeeper启用SASL和Kerberos身份验证。



HBase:标签

标签(Tags)是HFile v3的一项功能。标签是作为单元的一部分的元数据,与密钥(key),值(value)和版本(version)分开。标签为其他与安全相关的功能(如单元级ACL和可见性标签)提供实现细节。标签存储在HFiles自身中。将来可能会使用标签来实现其他HBase功能。为了使用它们启用的安全功能,您无需了解很多关于标签的信息。

实现细节

每个单元可以有零个或多个标签。每个标签都有一个类型和实际的标签字节数组。

就像行键,列族,限定符和值可以被编码一样(参见data.block.encoding.types),标签也可以被编码。您可以在列族级别启用或禁用标签编码,并且默认情况下启用。使用该HColumnDescriptor#setCompressionTags(boolean compressTags)方法来管理列族的编码设置。您还需要为列族启用DataBlockEncoder,以使标记的编码生效。

如果启用WAL压缩,则可以通过在hbase-site.xml中设置hbase.regionserver.wal.tags.enablecompressionto的值为true来启用WAL中每个标记的压缩。标记压缩使用字典编码。

使用WAL加密时,不支持标记压缩。



HBase访问控制标签(ACL)

HBase中的ACL基于用户的成员身份或组中的排除,以及给定组访问给定资源的权限。ACL是作为一个称为AccessController的协处理器实现的。 

HBase不维护私有组映射,但依赖于Hadoop组映射器,它映射目录中的实体(LDAP或Active Directory)和HBase用户。任何支持的Hadoop组映射器都将起作用。然后,针对资源(全局,名称空间,表格,单元或端点)授予用户特定的权限(读取,写入,执行,创建,管理)。

启用Kerberos和访问控制后,客户端对HBase的访问将得到验证,并且用户数据是专用的,除非明确授予访问权限。

与关系数据库相比,HBase具有更简单的安全模型,特别是在客户端操作方面。例如,插入(新记录)和更新(现有记录)之间没有区别,两者都将折叠为已放置。

了解访问级别

HBase访问级别是相互独立授予的,并允许在给定范围内进行不同类型的操作。

  • 读取(R) - 可以读取给定范围的数据。- 写入(W) - 可以在给定范围写入数据。- 执行(X) - 可以在给定范围内执行协处理器端点。- 创建(C) - 可以在给定范围内创建表或删除表(甚至不创建它们)。- 管理员(A) - 可以执行群集操作,例如在给定的范围内平衡群集或分配区域。
    写入(W) - 可以在给定范围写入数据。

创建(C) - 可以在给定范围内创建表或删除表(甚至不创建它们)。

可能的范围是:

  • 超级用户(Superuser):Superuser可以执行HBase中可用的任何操作,以访问任何资源。在你的集群上运行HBase的用户就是superuser,就像所有指定给HMaster中的hbase-site.xml的hbase.superuser配置属性。- 全局(Global):在全局范围授予的权限允许管理员对集群的所有表进行操作。- 命名空间(Namespace):在命名空间范围授予的权限适用于给定名称空间内的所有表。- 表(Table):在表范围授予的权限适用于给定表中的数据或元数据。- ColumnFamily:在ColumnFamily范围内授予的权限适用于该ColumnFamily内的单元格。- 单元格(Cell):在单元格范围内授予的权限适用于该确切的单元格坐标(键,值,时间戳)(key, value, timestamp)。这允许政策与数据一起发展。 
    要更改特定单元格上的ACL,请使用新ACL写入更新后的单元格,以获得原始坐标的精确坐标。 
    如果您有多版本架构并且想要更新所有可见版本的ACL,则需要为所有可见版本编写新的单元格。该应用程序可以完全控制政策演变。 
    唯一的例外上述规则append和increment处理。追加和增量可以在操作中携带ACL。如果操作中包含一个,那么它将应用于appendor和increment的结果。否则,保存您正在追加或增加的现有单元的ACL。
    全局(Global):在全局范围授予的权限允许管理员对集群的所有表进行操作。

表(Table):在表范围授予的权限适用于给定表中的数据或元数据。

单元格(Cell):在单元格范围内授予的权限适用于该确切的单元格坐标(键,值,时间戳)(key, value, timestamp)。这允许政策与数据一起发展。 
要更改特定单元格上的ACL,请使用新ACL写入更新后的单元格,以获得原始坐标的精确坐标。 
如果您有多版本架构并且想要更新所有可见版本的ACL,则需要为所有可见版本编写新的单元格。该应用程序可以完全控制政策演变。 
唯一的例外上述规则append和increment处理。追加和增量可以在操作中携带ACL。如果操作中包含一个,那么它将应用于appendor和increment的结果。否则,保存您正在追加或增加的现有单元的ACL。

访问级别和作用域的组合创建了可授予用户的可能访问级别的矩阵。在生产环境中,根据执行特定工作所需的内容来考虑访问级别很有用。以下列表描述了一些常见类型的HBase用户的适当访问级别。重要的是不要授予比给定用户执行其所需任务所需的更多访问权限。

  • 超级用户(Superusers):在生产系统中,只有HBase用户应具有超级用户访问权限。在开发环境中,管理员可能需要超级用户访问才能快速控制和管理群集。但是,这种类型的管理员通常应该是全局管理员而不是超级用户。- 全局管理员(Global Admins):全局管理员可以执行任务并访问HBase中的每个表。在典型的生产环境中,管理员不应具有对表内数据的读取或写入权限。- 具有管理员权限的全局管理员可以在群集上执行群集范围的操作,例如平衡、分配或取消分配区域或调用明确的主要压缩。这是一个操作角色。
    全局管理员(Global Admins):全局管理员可以执行任务并访问HBase中的每个表。在典型的生产环境中,管理员不应具有对表内数据的读取或写入权限。

具有管理员权限的全局管理员可以创建或删除HBase中的任何表。这更像是一个DBA类型的角色。在生产环境中,不同的用户可能只有一个管理员权限和创建权限。在当前的实现中,具有Admin权限的全局管理员可以在桌上授予自己Read和Write权限并获得对该表的数据的访问权限。出于这个原因,只向实际需要的受信任用户授予全局管理员权限。另请注意,具有Create权限的全局管理员可以在ACL表上执行Put操作,模拟授予或吊销并绕过对全局管理权限的授权检查。由于这些问题,请谨慎授予全局管理员特权。

  • 命名空间管理员(Namespace Admins):具有Create权限的命名空间管理员可以在该命名空间内创建或删除表,并获取和恢复快照。具有Admin权限的名称空间管理员可以对该名称空间内的表执行操作,例如拆分或主要压缩。
    - 表管理员(Table Admins):表管理员只能在该表上执行管理操作。具有Create权限的表管理员可以从该表创建快照或从快照中恢复该表。具有Admin权限的表管理员可以在该表上执行操作:例如拆分或主要压缩。- 用户(Users):用户可以读取或写入数据,或两者兼有。如果授予Executable权限,用户还可以执行协处理器端点。
    表管理员(Table Admins):表管理员只能在该表上执行管理操作。具有Create权限的表管理员可以从该表创建快照或从快照中恢复该表。具有Admin权限的表管理员可以在该表上执行操作:例如拆分或主要压缩。

访问级别的实际示例

级别范围权限描述|------

高级管理员

Global 

访问,创建

管理群集并允许访问初级管理员。

初级管理员

Global 

创建

创建表并允许访问表管理员。

表管理员

Table 

访问

从操作的角度维护一个表格。

数据分析师

Table 

从HBase数据创建报告。

Web应用程序

Table 

读,写

将数据放入HBase并使用HBase数据执行操作。

实现细节

单元级ACL使用标签(tag)实现(请参阅HBase:标签)。为了使用单元级别的ACL,您必须使用HFile v3和HBase 0.98或更高版本。

  1. 由HBase创建的文件由运行HBase进程的操作系统用户拥有。要与HBase文件交互,您应该使用API或批量加载功能。1. HBase不在HBase内部建立“roles”。相反,组名可以被授予权限。这允许通过组成员身份对角色进行外部建模。通过Hadoop组映射服务在HBase外部创建和操作组。
    HBase不在HBase内部建立“roles”。相反,组名可以被授予权限。这允许通过组成员身份对角色进行外部建模。通过Hadoop组映射服务在HBase外部创建和操作组。

服务器端配置

1、请先参考基本的服务器端配置中的步骤。

2、通过在hbase-site.xml中设置以下属性来安装和配置AccessController协处理器。这些属性包含一个类的列表。

如果您使用AccessController以及VisibilityController,则AccessController必须首先位于列表中,因为在这两个组件都处于活动状态时,VisibilityController会将其系统表上的访问控制委派给AccessController。有关将两者一起使用的示例,请参阅安全性配置示例。

或者,您可以通过将hbase.rpc.protection设置为privacy来启用传输安全性。这需要HBase 0.98.4或更高版本。

3、在Hadoop namenode的core-site.xml中设置Hadoop组映射器。这是一个Hadoop文件,不是HBase文件。根据您的网站需求进行定制。以下是一个例子:

4、或者,启用早期的评估策略。在HBase 0.98.0之前,如果用户没有被授予访问列族或至少一个列限定符的权限,则会引发AccessDeniedException。HBase 0.98.0删除了这个异常,以便允许单元级别的异常授予。要恢复HBase 0.98.0-0.98.6中的旧行为,请在hbase-site.xml中将hbase.security.access.early_out设置为true。在HBase 0.98.6中,默认返回true。

5、分发您的配置并重新启动群集以使更改生效。

6、要测试您的配置,请以给定用户身份登录HBase Shell,并使用该whoami命令报告您的用户所属的组。在此示例中,用户被报告为该services组的成员。

Administration

管理任务可以从HBase Shell或通过API执行。

1、用户和组管理,在您的目录中,用户和组在HBase的外部维护。

2、授予对名称空间,表格,列族或单元格的访问权限 
授权语句有几种不同类型的语法。第一个也是最熟悉的是,表和列族是可选的:

组和用户以相同的方式被授予访问权限,但组前缀有一个@符号。以相同的方式,表和名称空间以相同的方式指定,但名称空间前缀有一个@符号。 
也可以在单个语句中针对同一资源授予多个权限,如本例中所示。第一个子语句将用户映射到ACL,第二个子语句指定资源。 
HBase Shell支持在单元级授予和撤销访问权限用于测试和验证支持,不应将其用于生产使用,因为它不会将权限应用于尚不存在的单元。应用单元级别权限的正确方法是在存储值时在应用程序代码中执行此操作。 
ACL粒度和评估顺序ACL,从最小粒度到最细粒度进行评估,当达到授予权限的ACL时,评估将停止。这意味着单元ACL不会以较小的粒度覆盖ACL。

示例-HBase Shell

  • Global:
    hbase> grant ‘@admins’, ‘RWXCA’
    - Namespace:
    hbase> grant’service’,‘RWXCA’,’@ test-NS’
    - Table:
    hbase> grant ‘service’, ‘RWXCA’, ‘user’
    - Column Family:
    hbase> grant ‘@developers’, ‘RW’, ‘user’, ‘i’
    - Column Qualifier:
    hbase> grant 'service, ‘RW’, ‘user’, ‘i’, 'foo’
  • Cell:授予单元ACL的语法使用以下语法:
    grant <table>, 
      { ‘<user-or-group>’ => \    ‘<permissions>’, … }, 
      { <scanner-specification> }
  • - <user-or-group>是用户名或组名,前缀@为组的情况。- <permissions>是一个包含任何或所有“RWXCA”的字符串,但只有R和W在单元范围内有意义。- <scanner-specification>是’scan’shell命令使用的扫描器(scan)规范语法和约定。有关扫描仪规格的一些示例,请发出以下HBase Shell命令。
    hbase> help "scan"
    如果您需要启用单元格acl,则hbase-site.xml中的hfile.format.version选项应该大于或等于3,并且hbase.security.access.early_out选项应设置为false。此示例授予’testuser’用户读取的访问权限以及对’developers’组进行读/写访问,'pii’列中与过滤器匹配的单元格。
    hbase> grant ‘user’, \   { ‘@developers’ => ‘RW’, ‘testuser’ => ‘R’ }, \    { COLUMNS => ‘pii’, FILTER => “(PrefixFilter (‘test’))” }
    shell将运行具有给定条件的扫描器,用新的ACL重写找到的单元格,并将其存储回其确切的坐标。
    Namespace:

Column Family:

Cell:授予单元ACL的语法使用以下语法:

<permissions>是一个包含任何或所有“RWXCA”的字符串,但只有R和W在单元范围内有意义。

如果您需要启用单元格acl,则hbase-site.xml中的hfile.format.version选项应该大于或等于3,并且hbase.security.access.early_out选项应设置为false。此示例授予’testuser’用户读取的访问权限以及对’developers’组进行读/写访问,'pii’列中与过滤器匹配的单元格。

示例-API:以下示例显示如何在表级别授予访问权限

要在单元级别授予权限,可以使用以下Mutation.setACL方法:

具体而言,此示例向名为user1的用户提供对特定Put操作中所包含的任何单元格的读取权限:

3、从名称空间,表,列系列或单元中撤消访问控制 

revoke命令和API是授权命令API的双胞胎,他们的语法是完全一样的。唯一的例外是您无法撤销单元级别的权限。您只能撤销先前已授予的访问权限,并且revoke语句与显式拒绝资源不同。 
HBase Shell支持授予和撤销访问权限用于测试和验证支持,不应将其用于生产使用,因为它不会将权限应用于尚不存在的单元。应用单元级权限的正确方法是在存储值时在应用程序代码中执行此操作。 
示例:撤销对表的访问

4、显示用户的有效权限

HBase Shell



HBase 可见性标签

可见性标签控件可用于仅允许与给定标签关联的用户或主体读取或访问具有该标签的单元格。例如,您可以标记一个单元格top-secret,并且只将该标签的访问权授予该managers组。可见性标签是使用标签实现的,标签是HFile v3的一个功能,并允许您以每个单元为基础存储元数据。标签是一个字符串,可以使用逻辑运算符(&,|或!)将标签组合为表达式,并使用圆括号进行分组。HBase不能对表达式进行任何形式的验证,除了基本的良好格式。可见性标签本身没有意义,可以用来表示敏感度级别、特权级别或任何其他任意的语义含义。 

如果用户的标签与单元格的标签或表达式不匹配,则拒绝用户访问该单元格。

在HBase 0.98.6及更高版本中,可见性标签和表达式支持UTF-8编码。当使用org.apache.hadoop.hbase.security.visibility.VisibilityClient类提供的addLabels(conf, labels)方法创建标签并通过扫描或获取在授权中传递标签时,标签可以包含UTF-8字符,以及可见标签中通常使用的逻辑运算符以及常规Java符号,而不需要任何转义方法。但是,当通过Mutation传递CellVisibility表达式时,如果使用UTF-8字符或逻辑运算符,则必须将该表达式与该CellVisibility.quote()方法一起放入。请参阅TestExpressionParser和源文件hbase-client/src/test/java/org/apache/hadoop/hbase/client/TestScan.java。

用户在Put操作期间向单元添加可见性表达式。在默认配置中,用户不需要访问标签就可以用它来标记单元格。此行为由配置选项hbase.security.visibility.mutations.checkauths控制。如果您设置此选项为true,则用户正在修改的标签必须与用户关联,否则修改将失败。在获取或扫描期间确定用户是否有权读取标记的单元格,并且不允许用户读取的结果被过滤掉。这会导致相同的I/O处罚,如同返回结果一样,但会减少网络负载。 

可见性标签也可以在删除操作中指定。有关可见性标签和删除的详细信息,请参阅HBASE-10885

当RegionServer首次收到请求时,将在RPC上下文中生成用户的有效标签集。用户与标签关联的方式是可插入的。默认插件通过添加到获取或扫描的授权中指定的标签,并检查针对主叫用户的已认证标签列表的标签。当客户端传递用户未通过身份验证的标签时,默认插件会删除它们。您可以通过Get#setAuthorizations(Authorizations(String,…))和Scan#setAuthorizations(Authorizations(String,…));方法传递用户经过身份验证的标签的子集。 

可以按照与用户相同的方式向组授予可见性标签。组前缀为符号@。当检查用户的可见性标签时,服务器将包括用户所属的组的可见性标签以及用户自己的标签。当使用API VisibilityClient#getAuths或Shell命令get_auths为用户检索可见性标签时,我们将返回专门为该用户添加的标签,而不是组级标签。 

可见性标签访问检查由VisibilityController协处理器执行。您可以使用VisibilityLabelService接口来提供自定义实现或控制可见性标签与单元格一起存储的方式。请参阅源文件hbase-server/src/test/java/org/apache/hadoop/hbase/security/visibility/TestVisibilityLabelsWithCustomVisLabService.java。

可见性标签可以与ACL一起使用,需要注意以下几点:

  • 标签必须在可见标签中使用之前明确定义。请参阅下面的示例来了解如何完成此操作。 
    - 目前没有办法确定哪些标签已应用于单元格。有关详细信息,请参阅HBASE-12470。 
    - 可见性标签目前不适用于超级用户(superusers)。 
    目前没有办法确定哪些标签已应用于单元格。有关详细信息,请参阅HBASE-12470。 

可见性表达式的示例

表达式解释|------

fulltime


允许访问与fulltime标签关联的用户。

!public

允许访问不与public标签关联的用户。

(secret | topsecret)&!probationary

允许访问与secret标签或topsecret标签相关联的用户,而不与probationary  标签




HBase可见性标签的服务器端配置

1、在开始HBase可见性标签的服务器端配置之前,你需要确认达到了基本的服务器端配置中的步骤。

2、通过在hbase-site.xml中设置以下属性来安装和配置VisibilityController协处理器。这些属性包含类名的列表。

如果将AccessController和VisibilityController协处理器一起使用,则AccessController必须位于列表中第一位,因为在这两个组件都处于活动状态时,VisibilityController会将其系统表上的访问控制委派给AccessController。

3、调整配置 默认情况下,用户可以用任何标签来标注单元格,包括它们没有关联的标签,这意味着用户可以放置他无法读取的数据。例如,即使用户没有与该标签相关联,用户也可以用(假设的)'topsecret’标签来标记单元格。如果您只希望用户能够标记与其关联的标签的单元格,请设置hbase.security.visibility.mutations.checkauths为true。在这种情况下,如果使用用户未关联的标签,则更改将失败。

4、分发您的配置并重新启动群集以使更改生效。



HBase可见性标签管理

管理(Administration)任务可以使用HBase Shell或Java API执行。为了定义可见性标签并将标签与用户关联,HBase Shell可能更简单。

1、定义可见性标签列表HBase Shell

2、将标签与用户关联:HBase Shell

1、将标签或表达式应用于单元格:该标签仅适用于数据写入时。该标签与给定版本的单元格相关联。HBase Shell

Java API



HBase使用标签读取单元格

当您发出扫描或获取时,HBase会使用您的一组默认授权来过滤掉您无权访问的单元格。超级用户(superuser)可以通过使用set_auths HBase Shell命令或VisibilityClient.setAuths()方法为给定用户设置默认授权集。

如果您使用API,则可以在扫描或获取期间通过在HBase Shell中传递AUTHORIZATIONS选项或在Scan.setAuthorizations()方法中指定不同的授权。此授权将与您的默认设置一起作为附加过滤器。它会进一步过滤你的结果,而不是给你额外的授权。

HBase Shell

例子:Java API



HBase安全批量加载

由于客户端必须将从MapReduce作业生成的文件的所有权转移给HBase,所以在安全模式下的批量加载比正常设置涉及更多。安全批量加载由名为SecureBulkLoadEndpoint的协处理器实现,该协处理器使用由配置属性hbase.bulkload.staging.dir配置的暂存目录,该目录默认为/tmp/hbase-staging/。

安全批量加载算法

  • 只有一次,创建一个临时目录,这个目录是全局通用的,并由运行HBase的用户拥有(模式711或rwx—x—x)。此目录的列表将类似于以下内容:- 用户将数据写入该用户拥有的安全输出目录。例如,/user/foo/data。- 在内部,HBase创建一个全局可读/可写(-rwxrwxrwx, 777)的秘密的临时目录。例如,/tmp/hbase-staging/averylongandrandomdirectoryname。该目录的名称和位置不会公开给用户。HBase管理这个目录的创建和删除。- 用户使数据具有全局可读性和可写性,将其移入随机的临时目录,然后调用该SecureBulkLoadClient#bulkLoadHFiles方法。
    在内部,HBase创建一个全局可读/可写(-rwxrwxrwx, 777)的秘密的临时目录。例如,/tmp/hbase-staging/averylongandrandomdirectoryname。该目录的名称和位置不会公开给用户。HBase管理这个目录的创建和删除。

安全的优势在于秘密目录的长度和随机性。

要启用安全批量加载,请将以下属性添加到hbase-site.xml。



安全启用HBase

在hbase-2.x之后,默认的“hbase.security.authorization”发生了变化。在hbase-2.x之前,它默认为true,在后来的HBase版本中,默认值变为false。因此,要启用hbase授权,必须在hbase-site.xml中配置以下属性:



HBase安全配置示例

此配置示例包括对HFile v3,ACL,可见性标签以及对静态数据和WAL的透明加密的支持。所有选项已在上面的章节中单独讨论。

示例:hbase-site.xml中的安全设置示例

示例:Hadoop core-site.xml中的组映射器示例

调整下述些设置以适用您的环境。



HBase架构

NoSQL

HBase是一种“NoSQL”数据库。“NoSQL”是一个通用术语,意思是数据库不是支持SQL作为其主要访问语言的RDBMS,但是有许多类型的NoSQL数据库:BerkeleyDB是本地NoSQL数据库的一个例子,而HBase是一个分布式数据库。从技术上讲,HBase实际上更像是一个“数据存储”而不是“数据库”,因为它缺少在RDBMS中找到的许多功能,例如键入列,二级索引,触发器和高级查询语言等。

但是,HBase具有很多支持线性和模块化缩放的功能。通过添加商品类服务器上托管的RegionServers来扩展HBase集群。例如,如果一个集群从10个扩展到20个RegionServers,则它在存储和处理能力方面都会翻倍。RDBMS可以很好地扩展,但只能达到某一点 - 具体而言就是单个数据库服务器的大小 - 并且为了获得最佳性能,需要专门的硬件和存储设备。HBase的特点是:

  • 一致的读/写:HBase不是“最终一致的”DataStore。这使它非常适合诸如高速计数器聚合之类的任务。- 自动分片:HBase表通过区域分布在集群上,随着数据增长,区域会自动分割和重新分配。- 自动RegionServer故障切换
    - Hadoop/HDFS集成:HBase支持HDFS作为其分布式文件系统。- MapReduce:HBase支持通过MapReduce进行大规模并行处理,以便将HBase用作源和接收器。- Java客户端API:HBase支持易于使用的Java API进行编程式访问。- Thrift/REST API:HBase还支持非Java前端的Thrift和REST。- 块缓存和Bloom过滤器:HBase支持块缓存和Bloom过滤器,以实现高容量查询优化。- 操作管理:HBase提供内置的网页以提供运营洞察力以及JMX指标。
    自动分片:HBase表通过区域分布在集群上,随着数据增长,区域会自动分割和重新分配。

Hadoop/HDFS集成:HBase支持HDFS作为其分布式文件系统。

Java客户端API:HBase支持易于使用的Java API进行编程式访问。

块缓存和Bloom过滤器:HBase支持块缓存和Bloom过滤器,以实现高容量查询优化。

何时使用HBase

HBase不适合所有问题。

  1. 确保你有足够的数据。如果你有数亿或数十亿行,那么HBase是一个很好的选择。如果只有几千行,那么使用传统的RDBMS可能是一个更好的选择,因为所有数据都可能在单个节点(或两个)上,而群集的其余部分可能处于闲置状态。1. 确保您可以在没有RDBMS提供的所有额外功能的情况下生存(例如,键入列,二级索引,事务,高级查询语言等)。针对RDBMS构建的应用程序无法通过简单更改而“移植”到HBase,例如,一个JDBC驱动程序。考虑从RDBMS转移到HBase作为一个完整的重新设计,而不是一个端口。1. 确保你有足够的硬件。即使是HDFs也不能很好地处理少于5个的数据流(由于HDFS块复制的默认值为3),加上NAMENODE。
    确保您可以在没有RDBMS提供的所有额外功能的情况下生存(例如,键入列,二级索引,事务,高级查询语言等)。针对RDBMS构建的应用程序无法通过简单更改而“移植”到HBase,例如,一个JDBC驱动程序。考虑从RDBMS转移到HBase作为一个完整的重新设计,而不是一个端口。

HBase可以在笔记本电脑上独立运行 - 但这应该只被视为一种开发配置。

HBase和Hadoop / HDFS有什么区别?

HDFS是一个非常适合存储大型文件的分布式文件系统。它的文档指出,它不是一个通用的文件系统,也没有在文件中提供快速的单个记录查找。另一方面,HBase建立在HDFS之上,为大型表提供快速记录查找(和更新)。这有时会成为概念混淆的一个观点。HBase内部将您的数据放入HDFS上的索引“StoreFiles”中进行高速查找。有关HBase如何实现其目标的更多信息,请参阅数据模型和本章的其余部分。



HBase目录表

目录表hbase:meta以HBase表的形式存在,并且被HBase shell的list命令过滤掉,但实际上与其他表一样。

hbase:meta

该hbase:meta表(以前称为.META.)保存了系统中所有区域的列表,并且该hbase:meta位置存储在ZooKeeper中。

该hbase:meta表结构如下:

键(key)

  • 格式的区域键([table],[region start key],[region id])
    值(value)
  • info:regioninfo(该区域的序列化HRegionInfo实例)- info:server (服务器:包含此区域的RegionServer端口)- info:serverstartcode (包含此区域的RegionServer进程的开始时间)
    info:server (服务器:包含此区域的RegionServer端口)

当一个表处于拆分过程中时,另外两个列将被创建,称为info:splitA和info:splitB。这些列代表两个子区域。这些列的值也是序列化的HRegionInfo实例。该区域被拆分后,最终该行将被删除。

关于 HRegionInfo 的说明

空键用于表示表格开始和表结尾。具有空启动键的区域是表中的第一个区域。如果区域同时具有空的开始和空的结束键, 则它是表中唯一的区域。

启动排序

首先,hbase:meta在ZooKeeper中查找位置。接下来,使用服务器和startcode值更新hbase:meta。



HBase客户端


HBase客户端的群集连接

API在HBase 1.0中进行了更改。有关连接配置信息,请参阅连接到HBase群集的客户端配置和依赖关系。

HBase 1.0.0的API

它已被清理并且用户被返回接口来处理而不是特定的类型。在HBase的1.0,从ConnectionFactory获得Connection对象,在需要的基础上从Table,Admin以及RegionLocator获取它的实例。完成后关闭获取的实例。最后,确保在退出之前清理您的Connection实例。 Connections是重量级的对象,但线程安全,所以你可以为你的应用程序创建一个并保持实例。 Table,Admin和RegionLocator实例是轻量级的。随时创建,然后在关闭它们后立即放手。

HBase 1.0.0之前的API

实例HTable是与1.0.0之前的HBase集群版本进行交互的方式。表实例不是线程安全的。在任何给定的时间,只有一个线程可以使用Table的一个实例。在创建Table实例时,建议使用相同的HBaseConfiguration实例。这将确保将ZooKeeper和套接字实例共享到RegionServers,而这通常是您想要的。例如,这是首选:

连接池

对于需要高端多线程访问的应用程序(例如,可在单个JVM中为多个应用程序线程提供服务的Web服务器或应用程序服务器),可以预先创建一个Connection,如以下示例所示:

例子:预先创建一个Connection

HTablePool已弃用

本指南的以前版本讨论了HTablePool,它在HBase 0.94、0.95和0.96中被否决, 并在0.98.1、HBASE-6580 或 HConnection 中删除, 这在 HBase 1.0 中被弃用连接。请改用连接,请改用Connection。



HBase客户端:WriteBuffer和批处理方法

在HBase 1.0和更高版本中,HTable不赞成使用Table,Table不使用autoflush。要执行缓冲写入操作,请使用BufferedMutator类。

在HBase 2.0和更高版本中,HTable不使用BufferedMutator来执行Put操作。有关更多信息,请参阅HBASE-18500

有关写入持久性的更多信息,请查看ACID语义页面



HBase异步客户端

它是HBase 2.0中引入的新API,旨在提供异步访问HBase的能力。

您可以从ConnectionFactory获取AsyncConnectionfrom,然后从中获取一个异步表实例来访问HBase。完成后关闭AsyncConnection实例(通常在程序退出时)。

对于异步表,大多数方法与旧Table界面有相同的含义,预期返回值通常包含CompletableFuture。我们在这里没有任何缓冲区,所以没有关于异步表的close方法,你不需要关闭它。它是线程安全的。

扫描(scan)有以下几个不同之处:

  • getScanner方法可以返回一个ResultScanner。你可以以旧的方式使用它,它的工作原理与旧的ClientAsyncPrefetchScanner一样。- scanAll方法会一次返回所有的结果。它旨在为小扫描提供一种更简单的方法,您通常希望一次获得全部结果。- 观察者(Observer)模式。有一种扫描方法接受ScanResultConsumer作为参数。它会将结果传递给消费者。
    scanAll方法会一次返回所有的结果。它旨在为小扫描提供一种更简单的方法,您通常希望一次获得全部结果。

注意,AsyncTable接口是模板化的。模板参数指定扫描使用的ScanResultConsumerBase类型,这意味着观察者模式扫描API是不同的。这两种类型的扫描用户是 ScanResultConsumer和AdvancedScanResultConsumer。

ScanResultConsumer需要一个单独的线程池,用于执行向返回的CompletableFuture注册的回调。由于使用单独的线程池可以释放RPC线程,所以回调可以自由地执行任何操作。如果回调不快,或者有疑问,请使用此功能。

AdvancedScanResultConsumer在框架线程内执行回调。不允许在回调中执行耗时的工作,否则它可能会阻塞框架线程并导致非常糟糕的性能影响。顾名思义,它是为想要编写高性能代码的高级用户而设计的。



HBase异步管理

您可以从ConnectionFactory中获取一个AsyncConnectionfrom,然后从中获取一个AsyncAdmin实例来访问HBase。请注意,有两种getAdmin方法来获取AsyncAdmin实例。一种方法有一个额外的线程池参数用于执行回调。它是为普通用户设计的。另一种方法不需要线程池,并且所有的回调函数都在框架线程中执行,所以不允许在回调中耗费时间。它专为高级用户设计。

默认的getAdmin方法将返回一个使用默认配置的AsyncAdmin实例。如果你想定制一些配置,你可以使用getAdminBuilder方法为创建AsyncAdmin实例来获得AsyncAdminBuilder。用户可以自由设置他们关心的配置来创建一个新的AsyncAdmin实例。

对于AsyncAdmin接口,大多数方法与旧的Admin界面有相同的含义,期望返回值通常是用CompletableFuture包装的。

对于大多数管理员操作,当返回的CompletableFuture完成时,这意味着管理操作也已完成。但对于紧凑型操作而言,这只表示紧凑的请求已发送给HBase,可能需要一些时间才能完成紧凑操作。对于rollWALWriter方法,它只意味着rollWALWriter请求已发送到区域服务器,可能需要一些时间才能完成rollWALWriter操作。

对于区域名称,我们只接受byte[]作为参数类型,它可能是完整的区域名称或编码的区域名称。对于服务器名称,我们只接受ServerName作为参数类型。对于表名,我们只接受TableName作为参数类型。对于list*操作,我们只接受Pattern作为参数类型,如果你想做正则表达式匹配。



HBase客户端请求过滤器

可以选择使用RegionServer上应用的过滤器配置获取(Get)和扫描(Scan)实例。

过滤器可能会混淆,因为有许多不同的类型,最好通过了解过滤器功能组来使用它们。



HBase结构过滤器

结构过滤器包含其他过滤器。

FilterList

FilterList表示Filters之间的FilterList.Operator.MUST_PASS_ALL或FilterList.Operator.MUST_PASS_ONE关系的Filters列表。以下示例显示了两个过滤器(在同一个属性上检查“我的值”或“我的其他值”)之间的’or’关系。



HBase列值

SingleColumnValueFilter

可以使用SingleColumnValueFilter(请参阅:https://hbase.apache.org/apidocs/org/apache/hadoop/hbase/filter/SingleColumnValueFilter.html)来测试相等(如,CompareOperaor.EQUAL),不相等(如,CompareOperaor.NOT_EQUAL)的列值或者范围(例如,CompareOperaor.GREATER)。以下是一个测试列与字符串值“my value”等效的示例:

ColumnValueFilter

在HBase-2.0.0版本中引入作为SingleColumnValueFilter的互补,ColumnValueFilter只获取匹配的单元格,而SingleColumnValueFilter获取匹配单元格所属的整个行(包含其他列和值)。ColumnValueFilter的构造函数的参数与SingleColumnValueFilter相同。

注意:对于“equals to a family:qualifier:value”这样的简单查询,我们强烈推荐使用以下方式,而不是使用SingleColumnValueFilter或ColumnValueFilter:

此扫描将限制为指定的列’family:qualifier’,避免扫描不相关的系列和列,这些列具有更好的性能,而ValueFilter是用于执行值过滤的条件。



HBase列值比较器

Filter包中有几个值得提及的Comparator类。这些比较器与其他Filter一起使用,例如,SingleColumnValueFilter。

RegexStringComparator

RegexStringComparator支持用于值比较的正则表达式。

请参阅Oracle JavaDoc以获取Java中受支持的RegEx模式。

SubstringComparator

SubstringComparator可用于确定给定的子字符串是否存在于某个值中,比较是不区分大小写的。

BinaryPrefixComparator

请参阅BinaryPrefixComparator

BinaryComparator

请参阅BinaryComparator



KeyValue元数据

由于HBase在内部将数据存储为KeyValue对,因此KeyValue元数据过滤器(KeyValue Metadata Filters)会评估一行中是否存在键(即,ColumnFamily:列限定符),而不是前一节中的值。

FamilyFilter

FamilyFilter可用于过滤ColumnFamily。在扫描(Scan)中选择ColumnFamilies通常比在过滤器(Filter)中选择ColumnFamilies更好。

QualifierFilter

QualifierFilter可用于基于列(aka Qualifier)名称进行过滤。

ColumnPrefixFilter

ColumnPrefixFilter可用于基于列(又名限定符)名称的主要部分进行过滤。

ColumnPrefixFilter提前查找匹配每行前缀和每个涉及列族的第一列。它可以用来高效地获取非常宽的行中的一个列的子集。

注意:同一列限定符可用于不同的列族。此过滤器将返回所有匹配的列。

示例:查找以“abc”开头的行和家族中的所有列

MultipleColumnPrefixFilter

MultipleColumnPrefixFilter的行为类似于ColumnPrefixFilter,但允许指定多个前缀。

像ColumnPrefixFilter一样,MultipleColumnPrefixFilter可以高效地搜索与最低前缀匹配的第一列,并且在前缀之间查找过去的列范围。它可以用来从很宽的行中有效地获得不连续的列集。

示例:查找以“abc”或“xyz”开头的行和家族中的所有列

ColumnRangeFilter

ColumnRangeFilter允许有效的帧内行扫描。

ColumnRangeFilter可以为每个涉及的列族寻找第一个匹配列。它可以用来有效地获得非常宽的行的“切片”。即,你连续有一百万列,但你只想看看列bbbb-bbdd。

注意:同一列限定符可用于不同的列族。此过滤器将返回所有匹配的列。

示例:查找“bbbb”(含)和“bbdd”(含)之间的行和族中的所有列



HBase架构:Master

HMaster是主服务器(Master Server)的实现。主服务器负责监视群集中的所有RegionServer实例,并且是所有元数据更改的接口。在分布式集群中,Master通常在NameNode上运行。

启动行为

如果在多主机(multi-Master)环境中运行,所有Master竞争运行集群。如果活动Master在ZooKeeper中失去租约(或Master关闭),则剩下的Master将争相接管角色。

运行时影响

当Master发生故障时,一个常见的dist-list问题涉及一个HBase集群会发生什么。由于HBase客户端直接与RegionServer对话,因此群集仍可以“稳定状态”运行。此外,每个目录表(Catalog Tables),hbase:meta作为HBase的表存在,而不是在Master中不存在。但是,Master控制关键功能,如RegionServer故障切换和完成区域分割。因此,虽然群集仍可以在没有Master的情况下运行很短的时间,但应尽快重新启动Master形状。

接口

HMasterInterface公开的方法主要是面向元数据(metadata-oriented)的方法:

  • 表(createTable,modifyTable,removeTable,enable,disable)- ColumnFamily(addColumn,modifyColumn,removeColumn)- 区域(move,assign,unassign),例如,调用该Admin方法disableTable时,它由Master服务器提供服务。
    ColumnFamily(addColumn,modifyColumn,removeColumn)

流程

Master运行几个后台线程:

负载平衡器

周期性地,当没有转换区域时,负载均衡器将运行并移动区域以平衡群集的负载。

有关区域分配的更多信息,将在后续的章节中介绍。

CatalogJanitor

定期检查并清理hbase:meta表格



HBase架构:RegionServer


RegionServer接口、进程与协处理器

HRegionRegionInterface公开的方法包含面向数据的和区域维护:

  • 数据(get,put,delete,next等)- 区域(splitRegion,compactRegion等)例如,当在表上调用该Admin方法majorCompact时,客户端实际上遍历指定表的所有区域,并直接向每个区域请求重大压缩。
    区域(splitRegion,compactRegion等)例如,当在表上调用该Admin方法majorCompact时,客户端实际上遍历指定表的所有区域,并直接向每个区域请求重大压缩。

RegionServer进程

RegionServer运行各种后台进程:

  • CompactSplitThread
    检查分割并处理较小的压缩。
    - MajorCompactionChecker
    检查重大压实。
    - MemStoreFlusher
    定期将MemStore中的内存中写入刷新到StoreFiles。
    - LogRoller
    定期检查RegionServer的WAL。

    MajorCompactionChecker
    检查重大压实。

LogRoller
定期检查RegionServer的WAL。

RegionServer协处理器

在HBase 0.92版本中,增加了协处理器。



HBase块缓存

HBase提供了两种不同的BlockCache实现,来缓存从HDFS中读取的数据:默认的on-heap LruBlockCache和BucketCache(通常是off-heap)。本节讨论每个实现的优点和缺点、如何选择适当的选项以及每种配置选项。 

缓存选择

LruBlockCache是原始实现,完全在Java堆内。 BucketCache是可选的,主要用于保持块缓存数据脱离堆,尽管BucketCache也可以是文件支持的缓存。 

当您启用BucketCache时,您将启用两层缓存系统。我们曾经将层描述为“L1”和“L2”,但是已经不赞成使用hbase-2.0.0的这个术语。“L1”缓存引用了LruBlockCache的一个实例,并且将“L2”引用到了堆外的BucketCache。相反,当启用BucketCache时,所有DATA块都保存在BucketCache层中,元块(INDEX和BLOOM块)在LruBlockCache堆中。这两个层次的管理以及控制它们之间的块移动的策略是由 CombinedBlockCache 完成的。

常规缓存配置

除了缓存实现本身之外,您可以设置一些常规配置选项来控制缓存的执行方式。请参阅CacheConfig。设置了其中任何选项后,重新启动或滚动重新启动群集以使配置生效。检查日志以查找错误或意外行为。 

LruBlockCache设计

LruBlockCache是一个LRU缓存,它包含三个块级别的优先级以允许扫描电阻和内存中的ColumnFamilies: 

  • 单一访问优先级:从HDFS首次加载块时,它通常具有此优先级,它将成为驱逐期间要考虑的第一个组的一部分。其优点是,扫描块比获得更多用量的块更有可能被驱逐。- 多重访问优先级:如果先前优先级组中的块再次被访问,则会升级到此优先级。因此它是在驱逐期间考虑的第二组的一部分。- 内存访问优先级:如果该块的系列配置为“内存中(in-memory)”,则无论访问次数如何,都将成为此优先级的一部分。目录表是这样配置的。这个小组是在驱逐过程中考虑的最后一个小组。要将列族标记为内存中,请调用:
    多重访问优先级:如果先前优先级组中的块再次被访问,则会升级到此优先级。因此它是在驱逐期间考虑的第二组的一部分。

如果从java创建表,或者在shell中创建或更改表时设置IN_MEMORY ⇒ true,例如:

LruBlockCache用法

所有用户表默认启用块缓存,这意味着任何读取操作都会加载LRU缓存。这对于大量的用例可能是有益的,但通常需要进一步的调整才能获得更好的性能。一个重要的概念是工作集大小或WSS,即:“计算问题答案所需的内存量”。对于一个网站,这将是在短时间内回答查询所需的数据。

计算缓存中HBase有多少内存的方法是:

number of region servers * heap size * hfile.block.cache.size * 0.99

块缓存的默认值为0.4,表示可用堆的40%。最后一个值(99%)是在驱逐开始之后LRU缓存中的默认可接受加载因子。它被包含在这个等式中的原因是,说可以使用100%的可用内存是不现实的,因为这会使得该过程从加载新块的位置阻塞。下面是一些示例:

  • 一个区域服务器的堆大小设置为1 GB,默认块高速缓存大小将具有405 MB的块高速缓存可用。- 20个区域服务器的堆大小设置为8 GB,并且默认块高速缓存大小将具有63.3个块高速缓存。- 堆大小设置为24 GB并且块缓存大小为0.5的100个区域服务器将拥有大约1.16 TB的块缓存。
    20个区域服务器的堆大小设置为8 GB,并且默认块高速缓存大小将具有63.3个块高速缓存。

您的数据不是块缓存的唯一常驻者。以下是您可能必须考虑的其他问题:

目录表

该hbase:meta表被强制进入块缓存并具有内存优先级,这意味着它们更难以驱逐。(根据区域的数量,hbase:meta表格可以占用几个MB。)

HFiles索引

一个HFILE是HBase的使用将数据存储在HDFS文件格式。它包含一个多层索引,它允许HBase在不必读取整个文件的情况下查找数据。这些索引的大小是块大小(默认为64KB),密钥大小和存储的数据量的一个因素。对于大数据集,每个区域服务器的数字大约为1GB并不罕见,但并不是所有的数据都会被缓存,因为LRU会逐出未使用的索引。

按键

存储的值仅为图片的一半,因为每个值都与其键一起存储(行键,族限定符和时间戳)。

Bloom过滤器

就像HFile索引一样,这些数据结构(启用时)都存储在LRU中。

目前,衡量HFile索引和bloom过滤器大小的推荐方法是查看区域服务器Web UI并检查相关度量标准。对于密钥,可以使用HFile命令行工具完成采样并查找平均密钥大小度量。从HBase 0.98.3开始,您可以在用户界面的特殊Block Cache部分查看有关BlockCache统计信息和指标的详细信息。 

当WSS不适合内存时,使用块缓存通常是不好的。例如,在所有区域服务器的块高速缓存中都有40GB可用的情况,但您需要处理1TB的数据。其中一个原因是由驱逐产生的流失会不必要地触发更多的垃圾收集。这里有两个用例:

  • 完全随机读取模式:这种情况下,几乎不会在短时间内访问同一行两次,从而使得缓存块的命中率接近于0。在这样的表上设置块缓存会浪费内存和CPU周期,更多的是它会产生更多的垃圾来由JVM提取。- 映射表:在典型的MapReduce作业中,每个行都只能读取一次,因此不需要将它们放入块缓存。Scan对象可以通过setCaching方法将其关闭(将其设置为false)。如果您需要快速随机读取访问,您仍然可以在此表上保持块缓存打开状态。一个例子就是统计表中提供实时流量的行数,缓存该表的每个块都会产生大量流失,并且肯定会驱逐当前正在使用的数据。
    映射表:在典型的MapReduce作业中,每个行都只能读取一次,因此不需要将它们放入块缓存。Scan对象可以通过setCaching方法将其关闭(将其设置为false)。如果您需要快速随机读取访问,您仍然可以在此表上保持块缓存打开状态。一个例子就是统计表中提供实时流量的行数,缓存该表的每个块都会产生大量流失,并且肯定会驱逐当前正在使用的数据。

仅高速缓存META块(fscache中的数据块)

一个有趣的设置是我们只缓存META块,并在每个访问中读取DATA块。如果DATA块适用于fscache,则当访问在非常大的数据集中完全随机时,此替代方法可能有意义。要启用此设置,请更改您的表格和每个列族集:BLOCKCACHE ⇒ ‘false’。您只对此列族 “禁用” BlockCache。您永远不能禁用META块的缓存。由于HBASE-4683总是缓存索引和bloom块,所以即使BlockCache被禁用,我们也会缓存META块。

堆外块缓存

如何启用BucketCache

BucketCache的通常部署是通过一个管理类来设置两个缓存层:由LruBlockCache实现的堆缓存和使用BucketCache实现的第二个缓存。管理类默认为CombinedBlockCache。上一个链接描述了CombinedBlockCache实现的缓存“策略”。简而言之,它的工作方式是将元块(INDEX和BLOOM)保留在堆上的LruBlockCache层中,并将DATA块保存在BucketCache层中。 

Pre-hbase-2.0.0版本

与原生堆内LruBlockCache相比,从hbase-2.0.0之前的BucketCache中获取数据时,抓取总是比较慢。但是,随着时间的推移,延迟趋于不那么不稳定,因为使用BucketCache时垃圾收集较少,因为它正在管理BlockCache分配,而不是GC。如果BucketCache部署在堆外模式下,则该内存根本不由GC管理。这就是为什么你会在2.0.0之前使用BucketCache,所以你的延迟不那么不稳定,为了减少GC和堆碎片,所以你可以安全地使用更多的内存。

在2.0.0之前版本中,可以配置BucketCache,以便接收LruBlockCache驱逐的victim。所有数据和索引块首先缓存在L1中。当驱逐发生在 L1,块(或victims)将移至L2。设置cacheDataInL1通过(HColumnDescriptor.setCacheDataInL1(true)或shell,设置CACHE_DATA_IN_L1为true:来创建或修改列族,如:

hbase-2.0.0 +版本

HBASE-11425更改了HBase读取路径,以便它可以将读取数据从堆中保留,避免将缓存数据复制到java堆上。在hbase-2.0.0中,堆外延迟接近堆缓存延迟时间,并且不会引发GC。 

从HBase 2.0.0开始,L1和L2的概念已被弃用。当BucketCache打开时,DATA块将总是进入BucketCache,而INDEX/BLOOM块将进入堆LRUBlockCache。cacheDataInL1支持已被删除。

BucketCache块缓存可以部署为堆外(off-heap)、文件(file)或mmaped文件模式。 

您可以通过hbase.bucketcache.ioengine设置来进行设置。将它设置为offheap使BucketCache将其分配置于堆外,并且file:PATH_TO_FILE的ioengine设置将指示BucketCache使用文件缓存(特别是在您将某些快速I/O附加到SSD等盒子时有用)。从2.0.0开始,可以有多个文件支持BucketCache。当缓存大小要求很高时,这非常有用。对于多个备份文件,将ioengine配置为files:PATH_TO_FILE1,PATH_TO_FILE2,PATH_TO_FILE3。BucketCache也可以配置为使用mmapped文件。将 ioengine 配置为 mmap: PATH_TO_FILE。

可以在我们绕过CombinedBlockCache策略的情况下部署分层设置,并将BucketCache作为严格的L2缓存工作到L1 LruBlockCache。对于这样的设置,设置hbase.bucketcache.combinedcache.enabled为false。在这种模式下,从L1中逐出时,块将转到L2。当一个块被缓存时,它会先在L1中缓存。当我们去寻找缓存块时,我们先看看L1,如果找不到,那么搜索L2。我们称这种部署格式为Raw L1 + L2。注意:这个L1 + L2模式从2.0.0中删除。当使用BucketCache时,它将严格地是DATA缓存,并且LruBlockCache将缓存INDEX/META块。

其他BucketCache配置包括:指定要在重新启动时保持缓存的位置、使用多少线程来编写缓存等。

要检查它是否启用,请查找描述缓存设置的日志行,它将详细介绍BucketCache的部署方式。另请参阅UI。它将详细介绍缓存分层及其配置。

BucketCache示例配置

此示例为具有1 GB堆缓存的4 GB脱离堆BucketCache提供配置。 

在RegionServer上执行配置。

设置hbase.bucketcache.ioengine和hbase.bucketcache.size> 0启用CombinedBlockCache。让我们假设RegionServer已经设置为以5G堆运行:即HBASE_HEAPSIZE=5g。

1、首先,编辑RegionServer的hbase-env.sh,并将HBASE_OFFHEAPSIZE设置为大于所需的堆外大小的值,在本例中为4 GB(表示为4G)。我们将其设置为5G。对于我们的堆外缓存,这将是4G,对于任何其他堆外内存使用(除了BlockCache以外,还有其他堆外存储器的用户,例如RegionServer中的DFSClient可以使用堆外存储器)。

2、接下来,将以下配置添加到RegionServer的hbase-site.xml。

3、重新启动或滚动重新启动群集,并检查日志是否有任何问题。

在上面,我们将BucketCache设置为4G。我们将堆上的LruBlockCache配置为RegionServer堆大小的20%(0.2)(0.2 * 5G = 1G)。换句话说,像通常一样配置L1 LruBlockCache(就好像没有L2高速缓存一样)。 

HBase-10641引入了为HBase 0.98和更高版本的BucketCache的bucket配置多种大小的功能。要配置多个存储区大小,请将新属性hfile.block.cache.sizes(而不是hfile.block.cache.size)配置为以逗号分隔的块大小列表(从最小到最大排列),并且不含空格。目标是根据您的数据访问模式优化存储bucket大小。以下示例配置大小为4096和8192的存储bucket。

HBase中的直接内存使用情况

默认的最大直接内存因JVM而异。传统上它是64M或某一关系到被分配的堆大小(-Xmx)或根本没有限制(JDK7)。HBase服务器使用直接内存,特别是短路读取,承载的DFSClient将分配直接内存缓冲区。DFSClient使用的数量不容易量化;它是打开的HFiles*hbase.dfs.client.read.shortcircuit.buffer.size的数目,其中hbase.dfs.client.read.shortcircuit.buffer.size设置为128k。如果你使用堆外缓存,你将会使用直接内存。RPCServer使用ByteBuffer池。从2.0.0开始,这些缓冲区是堆外ByteBuffers。启动您的JVM,在conf/hbase-env.sh中确保-XX:MaxDirectMemorySize设置,考虑堆外块缓存(hbase.bucketcache.size)、DFSClient使用,RPC端ByteBufferPool最大大小。这必须比堆外BlockCache大小和最大ByteBufferPool大小的总和要高一点。为最大直接内存大小分配额外的1-2 GB在测试中起作用。直接内存是Java进程堆的一部分,与-Xmx分配的对象堆是分开的。MaxDirectMemorySize分配的值不得超过物理RAM,并且由于其他内存要求和系统限制,可能会少于总可用RAM。 

您可以通过查看UI 中的“服务器度量标准:内存(Server Metrics: Memory)”选项卡,查看RegionServer配置为使用多少内存和堆外/直接内存以及以及每次使用的时间。它也可以通过JMX获取。特别是可以在java.nio.type=BufferPool,name=directbean 上找到服务器当前使用的直接内存。Terracotta在Java中使用非堆内存有一个很好的记录。这是为了他们的产品BigMemory,但是很多问题都提到了对任何试图外堆的尝试,检查出来。

hbase.bucketcache.percentage.in.combinedcache

这是一个HBase 1.0之前的配置,因为它很混乱。这是一个浮点数,你会设置0.0到1.0之间的某个值,它的默认值是0.9。如果部署使用CombinedBlockCache,则LruBlockCache L1大小计算为:(1 - hbase.bucketcache.percentage.in.combinedcache) * size-of-bucketcache ,BucketCache大小为:hbase.bucketcache.percentage.in.combinedcache * size-of-bucket-cache。如果size-of-bucket-cache指定为Megabytes,则它EITHER配置hbase.bucketcache.size的值;如果hbase.bucketcache.size在0到1.0之间,则hbase.bucketcache.size * -XX:MaxDirectMemorySize。

在1.0中,它应该更直接。Onheap LruBlockCache大小设置为使用hfile.block.cache.size设置(并非最佳)的java堆的一小部分,并且BucketCache在绝对兆字节中设置为上述值。

压缩BlockCache

HBASE- 11331引入了懒惰的BlockCache解压缩,更简单地称为压缩BlockCache。当启用压缩BlockCache时,数据和编码数据块将以磁盘格式缓存在BlockCache中,而不是在缓存之前解压缩和解密。 

对于承载更多数据而不适合缓存的RegionServer,通过SNAPPY压缩启用此功能可以使吞吐量增加50%,平均延迟增加30%,同时将垃圾收集增加80%,并增加整体CPU负载2%。有关如何衡量和实现性能的更多详细信息,请参阅HBASE-11331。对于容纳适合缓存的数据的RegionServer,或者如果您的工作负载对额外的CPU或垃圾收集负载敏感,则可能会收到较少的收益。

压缩的BlockCache默认是禁用的。要启用它,请在所有RegionServers的hbase-site.xml中设置hbase.block.data.cachecompressed为true。



RegionServer Offheap读/写路径

Offheap读取路径

在hbase-2.0.0中,HBASE-11425更改了HBase读取路径,以便它可以保存读取数据,避免将缓存数据复制到java堆上。这减少了GC暂停,因为生产的垃圾较少,所以清理的次数也较少。堆外读取路径的性能与堆内LRU缓存相似/更好。该功能自HBase 2.0.0开始可用。如果BucketCache处于file模式下,则与原生堆LruBlockCache相比,抓取总是比较慢。

对于端到端的非堆积式读取路径,首先应该有一个堆外备份的离堆块缓存(BC)。在hbase-site.xml中将’hbase.bucketcache.ioengine’配置为off-heap 。还要指定使用hbase.bucketcache.size配置指定BC的总容量。请记住调整hbase-env.sh中的’HBASE_OFFHEAPSIZE’的值。这是我们如何为RegionServer java进程指定最大可能的堆外存储器分配。这应该比BC的堆外尺寸大。请记住,默认情况下没有默认设置,hbase.bucketcache.ioengine默认关闭BC。

接下来要调整的是RPC服务器端的ByteBuffer(字节缓冲区)池。该池中的缓冲区将用于累积单元字节,并创建一个结果单元块以发送回客户端。hbase.ipc.server.reservoir.enabled可以用来打开或关闭此池。默认情况下,此池处于可用状态。HBase将创建堆外ByteBuffers并将它们合并。如果您想在读取路径中进行端到端的堆积,请确保不要将其关闭。如果关闭该池,服务器将在堆上创建临时缓冲区以累积单元格字节并生成结果单元格块。这可能会影响高度读取的加载服务器上的GC。用户可以根据池中有多少缓冲区以及每个ByteBuffer的大小来调整该池。使用配置hbase.ipc.server.reservoir.initial.buffer.size来调整每个缓冲区大小。默认值是64 KB。

当读取模式是一个随机行读取负载,并且每个行的大小与64 KB相比较小时,尝试减少此数量。当结果大小大于一个ByteBuffer大小时,服务器将尝试抓取多个缓冲区,并将结果单元格块取出。当池用完缓冲区时,服务器将最终创建临时堆缓冲区。

可以使用配置’hbase.ipc.server.reservoir.initial.max’来调整池中的最大ByteBuffers数量。它的值默认为配置了64 *个区域服务器处理程序。数学是这样的,默认情况下我们考虑2MB作为每个读取结果的单元块大小,每个处理程序将处理读取。对于2 MB大小,我们需要32个缓冲区,每个大小为64 KB。所以每个处理程序有32个ByteBuffers(BB)。我们将这个大小分配为最大BB计数的两倍,以便一个处理程序可以创建响应并将其交给RPC响应程序线程,然后处理新的请求,创建新的响应单元块(使用池缓冲区)。即使响应者不能立即发回第一个TCP响应,我们的计数应该允许我们在池中仍然有足够的缓冲区,而不必在堆上做临时缓冲区。再次对于较小尺寸的随机行读数,调整此最大数量。有懒惰地创建的缓冲区,计数是要汇集的最大数量。

如果在完成端到端读取路径堆外后仍然看到GC出现问题,请在适当的缓冲池中查找问题。使用INFO级别检查下面的RegionServer日志:

hbase-env.sh中HBASE_OFFHEAPSIZE的设置在RPC端也应考虑此关闭堆缓冲池。我们需要将RegionServer的这个最大堆外大小配置为比这个最大池大小和堆外缓存大小之和高一点。TCP层还需要为TCP通信创建直接的字节缓冲区。此外,DFS客户端将需要一些堆外工作来完成其工作,特别是如果配置了短路读取。为最大直接内存大小分配额外的1 - 2 GB已在测试中工作。

如果您正在使用协处理器并在读取结果中引用单元格,请不要将对这些单元格的引用存储在CP挂接方法的范围之外。某些时候,CP需要关于单元的存储信息(像它的行键),以考虑下一个CP挂接调用等。



RegionServer拆分实现

由于写入请求由区域服务器处理,它们累积在一个名为memstore的内存存储系统中。一旦memstore填充,它的内容就会作为附加的存储文件写入磁盘。这个事件被称为memstore刷新。当存储文件堆积时,RegionServer会将它们压缩成更少、更大的文件。每次刷新或压缩完成后,该区域中存储的数据量将发生变化。RegionServer会咨询区域拆分策略,以确定该地区是否因为其他策略特定的原因而变得太大或应该拆分。如果策略建议,则区域拆分请求排队。

从逻辑上讲,分割区域的过程很简单。我们在该区域的密钥空间找到一个合适的点,我们应该将该区域分成两半,然后在该点将区域的数据分成两个新的区域。然而,这个过程的细节并不简单。当发生拆分时,新创建的子区域不会立即将所有数据重新写入新文件。相反,他们创建类似于符号链接文件的小文件,称为引用文件,根据拆分点指向父存储文件的顶部或底部。引用文件与常规数据文件一样使用,但只考虑一半的记录。如果不再有对父区域的不可变数据文件的引用,则只能分割该区域。这些引用文件通过压缩逐渐清理,以便该地区将停止引用其父文件,并且可以进一步拆分。

尽管拆分区域是由RegionServer做出的本地决定,但拆分过程本身必须与许多参与者协调。RegionServer在拆分之前和之后通知Master,更新.META.表以便客户端可以发现新的子区域,并重新排列HDFS中的目录结构和数据文件。拆分是一个多任务过程。为了在发生错误时启用回滚,RegionServer会保留关于执行状态的内存日志。RegionServer拆分过程说明了RegionServer执行拆分所采取的步骤。每个步骤都标有其步骤编号。来自RegionServers或Master的操作显示为红色,而来自客户端的操作显示为绿色。

下图为RegionServer拆分过程:

//img.mukewang.com/wiki/5bf7bcdc09124c8f04910379.jpg
  1. RegionServer决定在本地拆分区域,并准备拆分。拆分已开始。作为第一步,RegionServer获取表上的共享读锁定,以防止在拆分过程中修改架构。然后它在zookeeper下的/hbase/region-in-transition/region-name创建一个znode,并将znode的状态设置为SPLITTING。1. Master开始了解znode,因为它有一个父region-in-transitionznode的观察器。1. RegionServer在HDFS中的父级region目录下创建一个子目录.splits。1. RegionServer关闭父区域并在其本地数据结构中将区域标记为离线。拆分区域现在处于离线状态。在这一点上,来到父区域的客户端请求将抛出NotServingRegionException。客户端将重试一些备份。关闭区域被刷新。1. RegionServer在.splits目录下为子区域A和B创建地区目录,并创建必要的数据结构。然后,它会拆分存储文件,因为它会在父区域中为每个存储文件创建两个引用文件。这些引用文件将指向父区域的文件。1. RegionServer在HDFS中创建实际的区域目录,并为每个子区域移动引用文件。1. RegionServer向.META.表发送一个Put请求,并将.META.表中的父级设置为离线,添加有关子区域的信息。在这一点上,.META.中的子区域将不会有单独的条目。客户端将看到父区域在扫描.META.时被拆分。但直到他们出现在.META.其中才会知道这些子区域。此外,如果Put到.META.成功后,父区域将会有效地拆分。如果RegionServer在此RPC成功之前失败,则Master和下一个Region Server打开该区域将清除有关区域拆分的不干净状态。更新.META.之后,区域分割将由Master进行前滚。1. RegionServer并行打开子区域A和B.1. RegionServer将子区域A和B添加到.META.,连同它承载区域的信息。拆分区域现在处于在线状态。在此之后,客户端可以发现新的区域并向他们发出请求。客户端在本地缓存.META.条目,但是当他们向RegionServer或者.META.发出请求时,他们的缓存将失效,他们将从.META.中了解新的区域。1. RegionServer更新ZooKeeper中的znode /hbase/region-in-transition/region-name以表示状态SPLIT,以便主服务器可以了解它。必要时,平衡器可以自由地将子区域重新分配给其他区域服务器。拆分事务现在已完成。1. 拆分之后,.META.和HDFS仍将包含对父区域的引用。在子区域中进行压缩重写数据文件时,这些引用将被删除。主服务器中的垃圾收集任务会定期检查子区域是否仍然引用父区域的文件。否则,父区域将被删除。
    Master开始了解znode,因为它有一个父region-in-transitionznode的观察器。

RegionServer关闭父区域并在其本地数据结构中将区域标记为离线。拆分区域现在处于离线状态。在这一点上,来到父区域的客户端请求将抛出NotServingRegionException。客户端将重试一些备份。关闭区域被刷新。

RegionServer在HDFS中创建实际的区域目录,并为每个子区域移动引用文件。

RegionServer并行打开子区域A和B.

RegionServer更新ZooKeeper中的znode /hbase/region-in-transition/region-name以表示状态SPLIT,以便主服务器可以了解它。必要时,平衡器可以自由地将子区域重新分配给其他区域服务器。拆分事务现在已完成。



HBase使用write Ahead Log(WAL)


HBase使用WAL的目的

Write Ahead Log(WAL)将HBase中数据的所有更改记录到基于文件的存储中。在正常操作下,不需要WAL,因为数据更改从MemStore移动到StoreFiles。但是,如果在刷新MemStore之前RegionServer崩溃或变得不可用,则WAL确保可以重播对数据所做的更改。如果写入WAL失败,则修改数据的整个操作将失败。

HBase使用WAL接口的实现。通常,每个RegionServer只有一个WAL实例。一个例外是携带hbase:Meta的RegionServer;meta表有自己的专用WAL。在将它们的Mutations MemStore记录到受影响的Store之前,RegionServer将Puts和Deletes记录到它的WAL中。

HLog:在2.0之前,HBase中的WAL接口被命名HLog。在0.94中,HLog是WAL实施的名称。您可能会在为这些旧版本定制的文档中找到对HLog的引用。

WAL位于HDFS中的/hbase/WALs/目录下,每个区域有子目录。



HBase:WAL供应方

在HBase中,有一些WAL 实现(或“Providers”)。每个都有一个简短的名字标签,但是,它并不总是具有描述性的。您可以通过WAL provder短名称在hbase-site.xml中设置provider(供应方),以作为hbase.wal.provider属性的值(使用hbase.wal.meta_provider属性设置hbase:meta的供应方)

  • asyncfs:默认。自hbase-2.0.0以来的新版本(HBASE-15536,HBASE-14790)。这个AsyncFSWAL提供程序,它在RegionServer日志中标识自身,是基于新的非阻塞dfsclient实现构建的。它目前驻留在hbase代码库中,但其意图是将其备份到HDFS本身。WALs编辑以并行方式(“fan-out”)写入每个DataNode上的每个WAL块副本,而不是默认客户端的链式管道中,延迟应该会更好。- 文件系统:这是hbase-1.x版本的默认设置。它基于阻塞的DFSClient构建,并以经典的DFSCLient管道模式写入副本。在日志中它标识为FSHLog或FSHLogProvider。- multiwal:该供应方是由asyncfs或文件系统的多个实例组成。
    文件系统:这是hbase-1.x版本的默认设置。它基于阻塞的DFSClient构建,并以经典的DFSCLient管道模式写入副本。在日志中它标识为FSHLog或FSHLogProvider。

在RegionServer日志中查找下面的行,以查看哪个供应方处于适当的位置(下面显示了默认的AsyncFSWALProvider):



HBase:MultiWAL支持

每个RegionServer都有一个WAL,RegionServer必须以串行方式写入WAL,因为HDFS文件必须是连续的。这导致WAL成为性能瓶颈。

HBase 1.0在HBASE-5699中引入了支持MultiWal 。MultiWAL允许RegionServer通过在底层HDFS实例中使用多个管道来并行写入多个WAL流,从而在写入过程中增加总吞吐量。这种并行化是通过将区域传入的编辑分区来完成的。因此,当前的实现将无助于提高单个区域的吞吐量。

使用原始WAL实现的RegionServers和使用MultiWAL实现的RegionServers可以分别处理任意一组WAL的恢复,因此通过滚动重启可以实现零停机配置更新。

配置MultiWAL

要为RegionServer配置MultiWAL,请通过在XML中粘贴以下内容来将属性hbase.wal.provider的值设置为multiwal:

重新启动RegionServer以使更改生效。

要为RegionServer禁用MultiWAL,请取消设置该属性并重新启动RegionServer。



HBase:WAL拆分

RegionServer服务于许多区域。区域服务器中的所有区域共享相同活动的WAL文件。WAL文件中的每个编辑都包含有关它属于哪个区域的信息。当打开区域时,需要重播属于该区域的WAL文件中的编辑。因此,WAL文件中的编辑必须按区域分组,以便可以重播特定的集合以重新生成特定区域中的数据。按区域对WAL编辑进行分组的过程称为日志拆分。如果区域服务器出现故障,它是恢复数据的关键过程。 

在群集启动时由HMaster完成日志拆分,或者在区域服务器关闭时由ServerShutdownHandler完成日志拆分。为保证一致性,受影响的区域在数据恢复之前不可用。所有WAL编辑都需要在给定区域再次可用之前恢复并重播。因此,受到日志拆分影响的区域在该过程完成之前不可用。

过程:日志分割,分步执行

新目录按以下模式命名:

1、/hbase/WALs/<host>,<port>,<startcode>目录被重新命名。重命名该目录非常重要,因为即使HMaster认为它已关闭,RegionServer仍可能启动并接受请求。如果RegionServer没有立即响应,也没有检测到它的ZooKeeper会话,HMaster可能会将其解释为RegionServer失败。重命名日志目录可确保现有的有效WAL文件仍然由活动但繁忙的RegionServer使用,而不会意外写入。新目录根据以下模式命名:

这种重命名的目录的例子可能如下所示:

2、每个日志文件都被拆分,每次一个。日志拆分器一次读取一个编辑项的日志文件,并将每个编辑条目放入对应于编辑区域的缓冲区中。同时,拆分器启动多个编写器线程。编写器线程选取相应的缓冲区,并将缓冲区中的编辑项写入临时恢复的编辑文件。临时编辑文件使用以下命名模式存储到磁盘:

该文件用于存储此区域的WAL日志中的所有编辑。日志拆分完成后,.temp文件将被重命名为写入文件的第一个日志的序列ID。要确定是否所有编辑都已写入,将序列ID与写入HFile的上次编辑的序列进行比较。如果最后编辑的序列大于或等于文件名中包含的序列ID,则很明显,编辑文件中的所有写入操作都已完成。

3、日志拆分完成后,每个受影响的区域将分配给RegionServer。打开该区域时,会检查recoverededed文件夹以找到恢复的编辑文件。如果存在任何这样的文件,则通过读取编辑并将其保存到MemStore来重播它们。在重放所有编辑文件后,MemStore的内容被写入磁盘(HFile),编辑文件被删除。

处理日志分割期间的错误

如果您将该hbase.hlog.split.skip.errors选项设置为true,则错误处理如下:

  • 拆分过程中遇到的任何错误都将被记录。- 有问题的WAL日志将被移到hbase rootdir下的.corrupt目录中,- WAL的处理将继续进行
    有问题的WAL日志将被移到hbase rootdir下的.corrupt目录中,

如果该hbase.hlog.split.skip.errors选项设置为false默认值,则将传播该异常,并将该拆分记录为失败。

拆分崩溃的RegionServer的WAL时如何处理EOFException

如果在拆分日志时发生EOFException,即使hbase.hlog.split.skip.errors设置为false,拆分也会继续。在读取要拆分的文件集合中的最后一个日志时,可能会出现EOFException,因为RegionServer可能在崩溃时写入记录的过程中。 

在日志分割期间的性能改进

WAL日志拆分和恢复可能需要大量资源并需要很长时间,具体取决于崩溃中涉及的RegionServer的数量和区域的大小。启用或禁用分布式日志分割是为了提高日志分割期间的性能。

启用或禁用分布式日志拆分

分布式日志处理自HBase 0.92开始默认启用。该设置由hbase.master.distributed.log.splitting属性控制,可以设置为true或false,但默认为true。

分布式日志拆分,分步执行

配置分布式日志拆分后,HMaster控制进程。HMaster在日志拆分过程中注册每个RegionServer,实际拆分日志的工作由RegionServers完成。分布式日志拆分中逐步描述的日志拆分的一般过程在这里仍然适用。

1、如果启用分布式日志处理,则HMaster会在集群启动时创建拆分日志管理器实例。

拆分日志管理器管理所有需要扫描和拆分的日志文件。

拆分日志管理器将所有日志作为任务放入ZooKeeper splitWAL节点( hbase/splitWAL)中。

您可以通过发出以下zkCli命令来查看splitWAL的内容。显示示例输出。

输出包含一些非ASCII字符。解码后,它看起来更简单:

该列表表示要扫描和拆分的WAL文件名,这是日志拆分任务的列表。

2、拆分日志管理器监视日志拆分任务和工作人员。拆分日志管理器负责以下正在进行的任务:

  • 一旦拆分日志管理器将所有任务发布到splitWAL znode,它就会监视这些任务节点并等待它们被处理。- 检查是否有任何排队等待的分组日志工人。如果发现没有响应的工作人员所要求的任务,它将重新提交这些任务。如果由于某些ZooKeeper异常而导致重新提交失败,则无法使用的工作者将再次排队等待重试。- 检查是否有未分配的任务。如果找到,它会创建一个短暂的重新扫描节点,以便通知每个拆分的日志工作者通过nodeChildrenChangedZooKeeper事件重新扫描未分配的任务。- 检查已分配但过期的任务。如果发现任何东西,它们会再次返回到TASK_UNASSIGNED状态,以便它们可以重试。这些任务可能被分配给缓慢的工作人员,或者他们可能已经完成。这不是问题,因为日志拆分任务具有幂等性。换句话说,相同的日志拆分任务可以被处理多次而不会引起任何问题。- 拆分日志管理器不断监视HBase拆分日志节点。如果任何拆分日志任务节点数据发生更改,拆分日志管理器将检索节点数据。节点数据包含任务的当前状态。您可以使用该zkCli get命令来检索任务的当前状态。在下面的示例输出中,输出的第一行显示任务当前未分配。
    检查是否有任何排队等待的分组日志工人。如果发现没有响应的工作人员所要求的任务,它将重新提交这些任务。如果由于某些ZooKeeper异常而导致重新提交失败,则无法使用的工作者将再次排队等待重试。

检查已分配但过期的任务。如果发现任何东西,它们会再次返回到TASK_UNASSIGNED状态,以便它们可以重试。这些任务可能被分配给缓慢的工作人员,或者他们可能已经完成。这不是问题,因为日志拆分任务具有幂等性。换句话说,相同的日志拆分任务可以被处理多次而不会引起任何问题。

根据数据更改的任务的状态,拆分日志管理器将执行以下操作之一:

  • 如果任务未分配,请重新提交;- 如果任务被分配,则Heartbeat;- 如果任务失败,请重新提交或失败;- 如果任务完成时出现错误,请重新提交或失败;- 如果任务由于错误而无法完成,则请重新提交或失败;- 如果任务成功完成或失败,请将其删除。
    如果任务被分配,则Heartbeat;

如果任务完成时出现错误,请重新提交或失败;

如果任务成功完成或失败,请将其删除。

任务失败的原因:该任务已被删除;该节点不再存在;日志状态管理器无法将任务的状态移至TASK_UNASSIGNED;重新提交的次数超过了重新提交阈值。

3、每个RegionServer的拆分日志工作器执行日志拆分任务。
每个RegionServer运行一个称为拆分日志工作器的守护进程线程,它负责拆分日志。守护程序线程在RegionServer启动时启动,并注册自己以观察HBase znode。如果任何splitWAL znode子项发生更改,它会通知睡眠工作器线程唤醒并获取更多任务。如果工作人员当前任务的节点数据发生更改,则工作人员将检查该任务是否已由其他工作人员执行。如果是这样,工作线程会停止当前任务的工作。工作人员不断监视splitWAL znode。出现新任务时,拆分日志工作人员将检索任务路径并检查每个任务路径,直到找到未声明的任务,并尝试声明该任务。如果声明成功,它将尝试执行该任务并state根据拆分结果更新任务的属性。此时,拆分日志工作者会扫描另一个无人认领的任务。拆分日志工作者如何接近任务

  • 它查询任务状态,只在任务处于TASK_UNASSIGNED状态时采取行动。- 如果任务处于TASK_UNASSIGNED状态,则工作人员尝试TASK_OWNED自行设置状态。如果它没有设置状态,另一名工人将尝试抓住它。如果任务保持未分配,拆分日志管理器还会要求所有工作人员稍后重新扫描。- 如果工作人员成功地完成任务,它会尝试再次获取任务状态,以确保它真正异步获取它。同时,它启动一个拆分任务执行器来完成实际工作:
    • - 获取HBase根文件夹,在根目录下创建一个临时文件夹,并将日志文件拆分为临时文件夹。
      如果任务处于TASK_UNASSIGNED状态,则工作人员尝试TASK_OWNED自行设置状态。如果它没有设置状态,另一名工人将尝试抓住它。如果任务保持未分配,拆分日志管理器还会要求所有工作人员稍后重新扫描。

获取HBase根文件夹,在根目录下创建一个临时文件夹,并将日志文件拆分为临时文件夹。

  • 如果拆分成功,任务执行程序将任务设置为状态TASK_DONE。- 如果工作人员捕获到意外的IOException,则该任务将设置为状态TASK_ERR。- 如果工作人员正在关闭,请将任务设置为状态TASK_RESIGNED。- 如果任务是由另一名工作人员完成的,则只需登录即可。
    4、拆分日志管理器监视未完成的任务。拆分日志管理器在所有任务成功完成时返回。如果所有任务都完成并出现一些故障,则拆分日志管理器将引发异常,以便日志拆分可以重试。由于异步实现,在极少数情况下,拆分日志管理器会丢失一些已完成任务的跟踪。因此,它定期检查其任务图或ZooKeeper中剩余的未完成任务。如果没有找到,它会抛出一个异常,以便日志拆分可以马上重试,而不是挂在那里等待不会发生的事情。


HBase:WAL压缩

可以使用LRU Dictionary压缩来压缩WAL的内容。这可以用来加速WAL复制到不同的datanode。该Dictionary最多可以存储215个元素;超过这个数字后开始逐出。

要启用WAL压缩,请将hbase.regionserver.wal.enablecompression属性设置为true。此属性的默认值是false。默认情况下,启用WAL压缩时,WAL标记压缩处于打开状态。您可以通过将该hbase.regionserver.wal.tags.enablecompression属性设置为’false’来关闭WAL标签压缩。

WAL压缩的一个可能的缺点是,如果WAL中间写入不好,我们会丢失WAL中最后一个块的更多数据。如果最后一个块中的条目添加了新的字典条目,但由于突然终止而导致修改后的Dictionary失败,读取最后一个块可能无法解析最后写入的条目。



WAL耐久性

可以在每个突变或表格基础上设置耐久性。包含如下的选项:

  • SKIP_WAL:不要将突变写入WAL(请参阅下一节,禁用WAL)。- ASYNC_WAL:异步写入WAL;不要让客户端等待其写入文件系统的同步,而是立即返回。编辑变得可见。同时,在后台,突变将在稍后的时间冲刷到WAL。此选项目前可能会丢失数据。- SYNC_WAL:默认值。在我们将成功返回给客户端之前,每个编辑都会同步到HDFS。- FSYNC_WAL:在我们将成功返回给客户端之前,每个编辑都是fsync对HDFS和文件系统的。
    ASYNC_WAL:异步写入WAL;不要让客户端等待其写入文件系统的同步,而是立即返回。编辑变得可见。同时,在后台,突变将在稍后的时间冲刷到WAL。此选项目前可能会丢失数据。

FSYNC_WAL:在我们将成功返回给客户端之前,每个编辑都是fsync对HDFS和文件系统的。

不要将突变或表上的ASYNC_WAL选项与AsyncFSWAL写入器混淆;它们是不同的选项,只是它们的名字很接近。



HBase:禁用WAL

为了改善在某些特定情况下的性能,你可以禁用WAL。但是,禁用WAL会使数据处于危险之中。推荐这种情况的唯一情况是在批量加载过程中。这是因为,如果出现问题,可以重新运行批量负载,而不会有数据丢失的风险。

通过调用HBase客户端字段Mutation.writeToWAL(false)来禁用WAL。使用Mutation.setDurability(Durability.SKIP_WAL)和Mutation.getDurability()方法来设置和获取字段的值。没有办法只为特定的表禁用WAL。

如果您为批量加载之外的任何其他功能禁用WAL,则您的数据处于危险之中。



HBase区域

区域是表格可用性和分布的基本元素,它由每个列族(Column Family)的存储(Store)组成。对象的层次结构如下所示:



HBase区域数量

对HBase区域数量的考虑

一般来说,HBase被设计为每台服务器运行一个较小的(20-200)数量相对较大的(5-20Gb)区域。对此的考虑如下:

为什么我应该保持我的区域数低?

通常情况下,由于多种原因,您希望在HBase上保持较低的区域。通常每个RegionServer大约有100个区域产生了最好的结果。以下是保持区域数低的一些原因:

  1. MSLAB(MemStore本地分配缓冲区)需要每个MemStore 2MB(每个区域的每个家庭2MB)。1000个有两个家族的区域使用了3.9GB的堆,甚至还没有存储数据。注意:2MB值是可配置的。1. 如果以相同的速率填充所有区域,则全局内存使用情况会导致当您的区域太多而又产生压缩时,它会强制进行微小刷新。重写相同的数据几十次是你想要的最后一件事。一个例子是平均填充1000个区域(有一个家族),让我们考虑一下5GB的全局MemStore使用的下限(区域服务器会有一个大堆)。一旦它达到5GB,它将强制刷新最大的区域,那时它们应该几乎全部都有大约5MB的数据,所以它会冲洗这个数量。稍后插入5MB,它将刷新另一个区域,该区域现在会有超过5MB的数据,依此类推。目前这是地区数量的主要限制因素。1. 现在的主机对很多区域敏感,并且需要很多时间分配他们并分批移动他们。原因在于它对ZK的使用很重要,目前它不是非同步的(可以真正改进 - 在0.96 HBase中已经有所改进)。1. 在较早版本的HBase(前HFile v2,0.90和之前的版本)中,少数RS上的大量区域会导致存储文件索引上升,增加堆使用量,并可能在RS上创建内存压力或OOME。
    如果以相同的速率填充所有区域,则全局内存使用情况会导致当您的区域太多而又产生压缩时,它会强制进行微小刷新。重写相同的数据几十次是你想要的最后一件事。一个例子是平均填充1000个区域(有一个家族),让我们考虑一下5GB的全局MemStore使用的下限(区域服务器会有一个大堆)。一旦它达到5GB,它将强制刷新最大的区域,那时它们应该几乎全部都有大约5MB的数据,所以它会冲洗这个数量。稍后插入5MB,它将刷新另一个区域,该区域现在会有超过5MB的数据,依此类推。目前这是地区数量的主要限制因素。

在较早版本的HBase(前HFile v2,0.90和之前的版本)中,少数RS上的大量区域会导致存储文件索引上升,增加堆使用量,并可能在RS上创建内存压力或OOME。

另一个问题是区域数量对MapReduce作业的影响;每个HBase区域都有一个映射器是很典型的。因此,每个RS仅托管5个区域可能不足以获得足够数量的MapReduce作业任务,而1000个区域将生成太多的任务。



HBase区域服务器分配

本节介绍HBase区域如何分配给区域服务器。

HBase区域分配启动

当HBase启动区域分配如下(简短版本)时:

  • 主机在启动时调用AssignmentManager。- AssignmentManager查看hbase:meta中现有的区域分配。- 如果区域分配仍然有效(即,如果RegionServer仍处于联机状态),则将保留分配。- 如果分配无效,则调用LoadBalancerFactory来分配区域。负载均衡器(在HBase 1.0中默认StochasticLoadBalancer)将该区域分配给RegionServer。- hbase:meta使用RegionServer分配(如果需要)和RegionServer启动代码(RegionServer进程的开始时间)在RegionServer打开区域时进行更新。
    AssignmentManager查看hbase:meta中现有的区域分配。

如果分配无效,则调用LoadBalancerFactory来分配区域。负载均衡器(在HBase 1.0中默认StochasticLoadBalancer)将该区域分配给RegionServer。

故障转移

当RegionServer失败时:

  1. 区域立即变得不可用,因为RegionServer已关闭。1. 主机将检测到RegionServer失败。1. 区域分配将被视为无效,并将像启动序列一样被重新分配。1. 飞行中的查询被重新尝试,并且不会丢失。1. 操作在以下时间段内切换到新的RegionServer:
    主机将检测到RegionServer失败。

飞行中的查询被重新尝试,并且不会丢失。

区域负载平衡

区域可以由LoadBalancer定期移动。

区域状态转变

HBase维持每个区域的状态并在hbase:meta中保持状态。该hbase:meta地区本身的状态在ZooKeeper中保存。您可以在Master Web UI中查看转换中的区域状态。以下是可能的区域状态。

可能的区域状态:

  • OFFLINE:该区域处于离线状态,无法打开- OPENING:该区域正在被打开- OPEN:该区域已打开并且RegionServer已通知主机- FAILED_OPEN:RegionServer无法打开该区域- CLOSING:该区域正在关闭- CLOSED:RegionServer关闭了该区域并通知了主机- FAILED_CLOSE:RegionServer无法关闭该区域- SPLITTING:RegionServer通知主机该地区正在拆分- SPLIT:RegionServer通知主机该区域已完成拆分- SPLITTING_NEW:该区域正在建设中,正在进行中的拆分- MERGING:RegionServer通知主机这个区域正在与另一个区域合并- MERGED:RegionServer通知主机该区域已被合并- MERGING_NEW:这个区域是由两个区域合并创建的
    OPENING:该区域正在被打开

FAILED_OPEN:RegionServer无法打开该区域

CLOSED:RegionServer关闭了该区域并通知了主机

SPLITTING:RegionServer通知主机该地区正在拆分

SPLITTING_NEW:该区域正在建设中,正在进行中的拆分

MERGED:RegionServer通知主机该区域已被合并

区域状态转换图:

//img.mukewang.com/wiki/5bfb669309598cbb04520384.jpg

图表图例注释:

  • Brown:离线状态,一种特殊状态,可以是暂时的(打开之前关闭后),终端(已禁用表的区域)或初始(新创建表的区域)- Palegreen:区域可以满足请求的在线状态- Lightblue:瞬态状态- Red:需要OPS注意的失败状态- Gold:区域的终端国家拆分/合并- Grey:通过拆分/合并创建的区域的初始状态
    Palegreen:区域可以满足请求的在线状态

Red:需要OPS注意的失败状态

Grey:通过拆分/合并创建的区域的初始状态

过渡状态描述:

  1. 主机将区域从OFFLINE状态移动到OPENING状态并尝试将区域分配给RegionServer。RegionServer可能或可能未收到开放区域请求。主机会重试将开放区域请求发送到RegionServer,直到RPC通过或主机用尽重试。在RegionServer收到开放区域请求后,RegionServer开始打开该区域。1. 如果主服务器的重试耗尽,则即使RegionServer正在开始打开区域,主服务器也会通过将区域移至CLOSING状态并尝试关闭它来阻止RegionServer打开该区域。1. RegionServer打开该区域后,它将继续尝试通知主服务器,直到主服务器将区域移至OPEN状态并通知RegionServer。该地区现在开放。1. 如果RegionServer无法打开区域,它会通知主人。主服务器将该区域移至CLOSED状态并尝试在不同的RegionServer上打开该区域。1. 如果主机无法在某个区域的任何区域打开该区域,则会将该区域移至FAILED_OPEN状态,并且在操作员从HBase shell进行干预或服务器死机之前不会采取进一步的行动。1. 主机将区域从OPEN状态移动到CLOSING状态。持有区域的RegionServer可能已经或可能未收到关闭区域请求。主服务器重试向服务器发送关闭请求,直到RPC通过或主服务器用尽重试。1. 如果RegionServer未联机或抛出NotServingRegionException,则主服务器将该区域移至OFFLINE状态并将其重新分配给不同的RegionServer。1. 如果RegionServer处于联机状态,但在主服务器用完重试之后无法访问,则主服务器会将该区域移至FAILED_CLOSE状态,并且不会采取进一步的操作,直到操作员从HBase shell进行干预或服务器已死亡。1. 如果RegionServer获得关闭区域请求,它会关闭该区域并通知主机。主机将区域移至CLOSED状态并将其重新分配给不同的RegionServer。1. 在分配区域之前,如果主区域处于OFFLINE状态,主区域会自动将区域移至CLOSED状态。1. 当一个RegionServer即将分割一个区域时,它通知主机。主机将要分割的区域从OPEN状态移动到SPLITTING状态,并将要创建的两个新区域添加到RegionServer。这两个区域最初都处于SPLITTING_NEW状态。1. 通知主机后,RegionServer开始拆分区域。一旦经过了不返回的点,RegionServer会再次通知主服务器,以便主服务器可以更新该hbase:meta表。但是,在服务器通知拆分完成之前,主服务器不会更新区域状态。如果拆分成功,拆分区域从SPLITTING状态移动到SPLIT状态,并且将两个新的区域从SPLITTING_NEW状态移动到OPEN状态。1. 如果拆分失败,则拆分区域从SPLITTING状态移动回OPEN状态,其中创建的两个新的区域将从SPLITTING_NEW状态移动到OFFLINE状态。1. 当一个RegionServer即将合并两个区域时,它首先通知主机。主机将两个区域合并为OPEN到MERGING状态,并将新的区域添加到RegionServer中,该区域将合并区域的内容保存起来。新区域最初处于MERGING_NEW状态。1. 通知主机后,RegionServer开始合并这两个区域。一旦经过不返回的点方,RegionServer再次通知主机,以便主机可以更新META。但是,主服务器不会更新区域状态,直到RegionServer通知合并已完成。如果合并成功,则两个合并的区域是从MERGING状态移动到MERGED状态,并且新的区域是从MERGING_NEW状态移动到OPEN状态。1. 如果合并失败,两个合并区域从MERGING状态返回到OPEN状态,这是为了保存合并的区域的内容的新的区域是从MERGING_NEW状态移动到OFFLINE状态。1. 对于处于FAILED_OPEN或FAILED_CLOSE状态的区域,当主机通过HBase Shell重新分配主区域时,主区域会尝试再次关闭它们。
    如果主服务器的重试耗尽,则即使RegionServer正在开始打开区域,主服务器也会通过将区域移至CLOSING状态并尝试关闭它来阻止RegionServer打开该区域。

如果RegionServer无法打开区域,它会通知主人。主服务器将该区域移至CLOSED状态并尝试在不同的RegionServer上打开该区域。

主机将区域从OPEN状态移动到CLOSING状态。持有区域的RegionServer可能已经或可能未收到关闭区域请求。主服务器重试向服务器发送关闭请求,直到RPC通过或主服务器用尽重试。

如果RegionServer处于联机状态,但在主服务器用完重试之后无法访问,则主服务器会将该区域移至FAILED_CLOSE状态,并且不会采取进一步的操作,直到操作员从HBase shell进行干预或服务器已死亡。

在分配区域之前,如果主区域处于OFFLINE状态,主区域会自动将区域移至CLOSED状态。

通知主机后,RegionServer开始拆分区域。一旦经过了不返回的点,RegionServer会再次通知主服务器,以便主服务器可以更新该hbase:meta表。但是,在服务器通知拆分完成之前,主服务器不会更新区域状态。如果拆分成功,拆分区域从SPLITTING状态移动到SPLIT状态,并且将两个新的区域从SPLITTING_NEW状态移动到OPEN状态。

当一个RegionServer即将合并两个区域时,它首先通知主机。主机将两个区域合并为OPEN到MERGING状态,并将新的区域添加到RegionServer中,该区域将合并区域的内容保存起来。新区域最初处于MERGING_NEW状态。

如果合并失败,两个合并区域从MERGING状态返回到OPEN状态,这是为了保存合并的区域的内容的新的区域是从MERGING_NEW状态移动到OFFLINE状态。



HBase区域服务器位置

随着时间的推移,Region-RegionServer位置通过HDFS块复制来实现。在选择要写入副本的位置时,HDFS客户端默认执行以下操作:

  1. 第一个副本被写入本地节点1. 第二个副本写入另一个机架上的随机节点1. 第三个副本与第二个副本在同一个机架上,但在随机选择的不同节点上1. 后续的副本将写入群集中的随机节点上。
    第二个副本写入另一个机架上的随机节点

后续的副本将写入群集中的随机节点上。

因此,HBase最终会在一次刷新或一次压缩后实现一个区域的局部性。在区域服务器故障转移情况下,区域服务器可以被分配到非本地“存储文件(StoreFiles)”的区域(因为没有副本是本地的),但是由于新数据是在区域中写入的,或者表被压缩,并且存储文件被重新编写,它们将成为区域服务器的“本地”。



HBase区域拆分

区域在达到配置的阈值时拆分。下面我们简要介绍这个话题。有关更长的说明,请参见Enis Soztutar的Apache HBase Region拆分和合并。 

拆分在RegionServer上独立运行;即主机不参与。RegionServer拆分一个区域,脱离拆分区域,然后将子区域添加到hbase:meta,在父级的服务器RegionServer上打开子服务器,然后将拆分报告给Master。



HBase自定义拆分策略

您可以使用自定义RegionSplitPolicy(HBase 0.94+)重写默认拆分策略。通常,自定义拆分策略应该扩展HBase的默认拆分策略: IncreasingToUpperBoundRegionSplitPolicy。

该策略可以通过HBase配置或者也可以基于每个表在全局范围内进行设置。

在hbase-site.xml中全局配置拆分策略:

使用Java API在表上配置拆分策略:

使用HBase Shell在表上配置拆分策略:

该策略可以通过使用的HBaseConfiguration或按表进行全局设置:

该DisabledRegionSplitPolicy策略阻止手动区域拆分。



HBase手动拆分区域

你可以手动拆分表,无论是在创建表(预拆分)还是稍后作为管理操作。出于以下一种或多种原因,您可能会选择拆分您的区域。可能还有其他有效的原因,但手动拆分表的需求也可能指出您的模式设计存在问题。

手动拆分表格的原因:

  • 您的数据按时间序列或其他类似的算法进行排序,这些算法会在表格末尾对新数据进行排序。这意味着持有最后一个区域的区域服务器始终处于负载状态,而其他区域服务器处于空闲状态,或者大部分空闲状态。- 你在表的一个区域开发了一个意想不到的热点。例如,一旦有关于该名人的消息,跟踪网络搜索的应用程序可能会被大量搜索名人所淹没。- 在群集中的RegionServers数量大幅增加之后,可以快速扩展负载。- 在大批量装载之前,这可能会导致跨区域异常和不均匀的载荷。
    你在表的一个区域开发了一个意想不到的热点。例如,一旦有关于该名人的消息,跟踪网络搜索的应用程序可能会被大量搜索名人所淹没。

在大批量装载之前,这可能会导致跨区域异常和不均匀的载荷。

该DisabledRegionSplitPolicy策略阻止手动区域拆分。

确定分拆分点

手动拆分表格的目标是在单独使用良好的rowkey设计无法达到的情况下,提高跨集群平衡负载的可能性。牢记这一点,你拆分区域的方式非常依赖于数据的特征。这可能是你已经知道拆分你的表的最好方法。如果不是这样,你拆分表的方式取决于你的键是什么样的。

字母数字行键(Alphanumeric Rowkeys)

如果您的行键以字母或数字开头,则可以在字母或数字边界处拆分表格。例如,下面的命令创建一个表,其区域在每个元音处都有拆分,所以第一个区域有AD,第二个区域有EH,第三个区域有IN,第四个区域有OV,第五个区域有UZ。

使用自定义算法

RegionSplitter工具提供了HBase,并使用SplitAlgorithm为您确定拆分点。作为参数,您可以给出算法,所需的区域数量和列族。它包括三个分割算法。首先是 HexStringSplit 算法,它假定行键是十六进制字符串。第二种 DecimalStringSplit 算法是假定行键是00000000到99999999范围内的十进制字符串。第三种 UniformSplit假设行键是随机字节数组。您可能需要开发自己的 SplitAlgorithm,使用提供的模型。



HBase在线区域合并

Master和RegionServer都参与在线区域合并事件。客户端将合并RPC发送到主服务器,然后主服务器将这些区域一起移动到负载较重的区域所在的RegionServer。最后,主服务器将合并请求发送到该RegionServer,然后运行合并。与区域拆分过程类似,区域合并在RegionServer上作为本地事务运行。它将区域划分为多个区域,然后合并文件系统上的两个区域,从hbase:meta中删除合并区域,并将合并后的区域添加到hbase:meta,在RegionServer中打开合并区域并将合并报告给Master。

HBase shell中的区域合并示例:

这是一个异步操作,并且在没有等待合并完成的情况下立即调用返回。true作为可选的第三个参数传递将强制合并。通常只有相邻的区域可以合并。该force参数将覆盖此行为,仅供专门使用。



Store


MEMSTORE

MemStore对Store进行内存中修改。修改是Cells / KeyValues。当请求刷新时,当前的MemStore被移动到快照并被清除。HBase将继续处理来自新MemStore和备份快照的编辑,直到刷新器报告刷新成功为止。此时,快照将被丢弃。请注意,当发生刷新时,属于同一区域的MemStore将全部被刷新。

MemStore刷新

MemStore刷新可以在下列任何条件下触发。最小刷新单位是每个区域,而不是单独的MemStore级别。

  1. 当MemStore达到hbase.hregion.memstore.flush.size指定的大小时,属于其区域的所有MemStore将被刷新到磁盘。1. 当整体MemStore使用率达到hbase.regionserver.global.memstore.upperLimit指定的值时,来自各个区域的MemStore将被刷新到磁盘以减少RegionServer中的整体MemStore使用量。刷新顺序基于区域MemStore使用的降序。区域将刷新它们的MemStore,直到整个MemStore使用率降至或稍低于hbase.regionserver.global.memstore.lowerLimit。1. 当给定区域服务器的WAL中的WAL日志条目数达到hbase.regionserver.max.logs中指定的值时,来自各个区域的MemStores将被刷新到磁盘以减少WAL中的日志数量。刷新顺序基于时间。首先刷新具有最早MemStore的区域,直到WAL计数下降到hbase.regionserver.max.logs以下。
    当整体MemStore使用率达到hbase.regionserver.global.memstore.upperLimit指定的值时,来自各个区域的MemStore将被刷新到磁盘以减少RegionServer中的整体MemStore使用量。刷新顺序基于区域MemStore使用的降序。区域将刷新它们的MemStore,直到整个MemStore使用率降至或稍低于hbase.regionserver.global.memstore.lowerLimit。


Scans

  • 当客户端针对表发出扫描时,HBase会为每个区域生成一个RegionScanner对象来提供扫描请求。- 该RegionScanner对象包含一个StoreScanner对象列表,每列族一个。- 每个StoreScanner对象还包含StoreFileScanner对应的列表,对应于相应列族的每个StoreFile和HFile,以及MemStore的KeyValueScanner对象列表。- 这两个列表被合并为一个,该列表按照升序对列表末尾的MemStore扫描对象进行排序。- 当一个StoreFileScanner对象被构造时,它与一个MultiVersionConcurrencyControl读取点(即当前的memstoreTS)相关联,过滤出读取点之外的任何新的更新。
    该RegionScanner对象包含一个StoreScanner对象列表,每列族一个。

这两个列表被合并为一个,该列表按照升序对列表末尾的MemStore扫描对象进行排序。



HBase使用StoreFile(HFile)

StoreFiles是您的数据所在的地方。

HFile格式

所述HFILE文件格式是基于BigTable[2006]论文中所描述的SSTable文件和Hadoop的TFile(所述单元测试套件和压缩线束直接从TFile获取)。Schubert Zhang的博客文章,HFile:分块索引文件格式存储分类键值对,全面介绍了HBase的HFile。Matteo Bertozzi还提出了一个有用的描述,HBase I / O:HFile。 

HFile工具

要查看HFile内容的文本版本,可以使用该hbase hfile工具。输入以下内容查看用法:

例如,要查看文件,hdfs://10.81.47.41:8020/hbase/default/TEST/1418428042/DSMP/4759508618286845475的内容,请键入以下内容:

如果您放弃选项-v仅查看HFile的摘要。查看其他与该hfile工具相关的用法。

HDFS上的StoreFile目录结构

有关StoreFiles在HDFS上的外观与目录结构有关的详细信息,请参阅“浏览HDFS以获取HBase对象”,这将在之后的章节中进行介绍。



块和KeyValue

块(Blocks)

StoreFiles由块(blocks)组成。块大小基于每个ColumnFamily进行配置。

压缩发生在StoreFiles中的块级别。有关压缩的更多信息,请参阅HBase中的压缩和数据块编码。

KeyValue

KeyValue类是HBase中数据存储的核心。KeyValue包装一个字节数组,并将偏移量和长度放入传递的数组中,指定将内容开始解释为KeyValue的位置。

字节数组中的KeyValue格式是:

  • keylength- valuelength- key
    - value

    valuelength

value

Key进一步分解为:

  • rowlength- row(即,rowkey)- columnfamilylength- ColumnFamily- columnqualifier- timestamp(时间戳)- keytype(键类型)(例如,Put,Delete,DeleteColumn,DeleteFamily)
    row(即,rowkey)

ColumnFamily

timestamp(时间戳)

KeyValue实例不会跨块拆分。例如,如果有8 MB的KeyValue,即使块大小为64kb,该KeyValue也会作为一个连贯的块读入。

示例

为了强调以上几点,请检查两行不同列Put同一行上发生的情况:

  • Put #1: rowkey=row1, cf:attr1=value1- Put #2: rowkey=row1, cf:attr2=value2
    Put #2: rowkey=row1, cf:attr2=value2

即使这些是针对同一行的,也会为每列创建一个KeyValue:

Put #1的关键部分:

  • rowlength -----------→ 4- row -----------------→ row1- columnfamilylength --→ 2- columnfamily --------→ cf- columnqualifier -----→ attr1- timestamp -----------→ server time of Put- keytype -------------→ Put
    row -----------------→ row1

columnfamily --------→ cf

timestamp -----------→ server time of Put

Put #2的关键部分:

  • rowlength -----------→ 4- row -----------------→ row1- columnfamilylength --→ 2- columnfamily --------→ cf- columnqualifier -----→ attr2- timestamp -----------→ server time of Put- keytype -------------→ Put
    row -----------------→ row1

columnfamily --------→ cf

timestamp -----------→ server time of Put

了解rowkey,ColumnFamily和列(又名columnqualifier)嵌入在KeyValue实例中是很重要的。这些标识符越长,KeyValue就越大。



HBase批量加载

HBase包含几种将数据加载到表中的方法。最直接的方法是使用MapReduce作业中的TableOutputFormat类,或者使用普通的客户端API;然而,这些并不总是最有效的方法。

批量加载功能使用MapReduce作业以HBase的内部数据格式输出表格数据,然后直接将生成的StoreFiles加载到正在运行的群集中。使用批量加载将比使用HBase API使用更少的CPU和网络资源。

HBase批量加载限制

当批量加载绕过写入路径时,WAL不会被写入作为过程的一部分。复制通过读取WAL文件来工作,因此它不会看到批量加载的数据 - 对于使用Put.setDurability(SKIP_WAL)的编辑也是如此。处理这种情况的一种方法是将原始文件或HFile发送到其他群集,并在那里进行其他处理。



HBase批量加载架构

HBase批量加载过程包含两个主要步骤。

通过MapReduce作业准备数据

批量加载的第一步是使用HFileOutputFormat2从MapReduce作业生成HBase数据文件(StoreFiles)。这种输出格式以 HBase 的内部存储格式写出数据,以便以后可以非常高效地将其加载到群集中。

为了高效工作,必须对HFileOutputFormat2进行配置,使每个输出 HFile 适合单个区域。为了做到这一点,输出将被批量加载到HBase中的作业使用Hadoop的TotalOrderPartitioner类来将映射输出分区到密钥空间的不相交范围中,对应于表中区域的键范围。

HFileOutputFormat2包括一个方便函数,configureIncrementalLoad(),它根据根据表格的当前区域边界自动设置TotalOrderPartitioner。

完成数据加载

在准备好数据导入之后,无论是通过使用具有“importtsv.bulk.output”选项的importtsv工具,还是使用HFileOutputFormat的其他MapReduce作业,该completebulkload工具都可用于将数据导入到正在运行的集群中。这个命令行工具遍历准备好的数据文件,并且每个文件确定文件所属的区域。然后,它会联系采用HFile的相应RegionServer,将其移动到其存储目录并使数据可供客户端使用。

如果在批量加载准备过程中或者在准备和完成步骤之间区域边界发生了变化,completebulkload公用程序会自动将数据文件分成与新边界相对应的部分。这个过程并不是最佳效率,因此用户应该注意尽量减少在准备批量加载和将其导入群集之间的延迟,特别是如果其他客户端同时通过其他方式加载数据。

该-c config-file选项可用于指定包含适当的hbase参数的文件(例如,hbase-site.xml)(如果CLASSPATH中尚未提供此参数)(此外,如果zookeeper不是由HBase管理,则CLASSPATH必须包含具有zookeeper配置文件的目录)。

如果目标表在HBase中不存在,则此工具将自动创建表。



HDFS

由于HBase在HDFS上运行(并且每个StoreFile都是作为HDFS上的文件编写的),因此了解HDFS体系结构非常重要,特别是在它如何存储文件,处理故障转移和复制块方面。

NameNode

NameNode负责维护文件系统元数据。有关更多信息,请参阅上面的HDFS体系结构链接。

DataNode

DataNode负责存储HDFS块。有关更多信息,请参阅上面的HDFS体系结构链接。



HBase:Timeline-consistent高可用读取

在架构上,HBase从一开始就始终具有强大的一致性保证。所有读取和写入操作都通过单个区域服务器进行路由,这可以确保所有写入都按照顺序进行,并且所有读取操作都可以看到最近提交的数据。

但是,由于将这些读取单个归位到单个位置,因此如果服务器变得不可用,则在区域服务器中托管的表区域将在一段时间内变得不可用。区域恢复过程中有三个阶段:检测,分配和恢复。其中,检测通常是最长的,目前大约为20-30秒,具体取决于ZooKeeper会话超时时间。在此期间内,在恢复完成之前,客户端将无法读取区域数据。

但是,对于某些使用情况,数据可能是只读的,或者对某些陈旧的数据进行读取是可以接受的。通过时间线一致(Timeline-consistent)的高可用读取,HBase可以用于这类对延迟敏感的应用,这些应用可能会在读取完成时产生时间限制。

为了实现读取的高可用性,HBase提供了一个称为区域复制的功能。在此模型中,对于表的每个区域,将会有多个副本在不同的RegionServers中打开。默认情况下,区域复制设置为1,因此只部署单个区域副本,并且不会从原始模型发生任何更改。如果区域复制设置为2或更多,则主服务器将分配表的区域副本。Load Balancer确保区域副本不共同托管在相同的区域服务器中,并且也位于同一机架中(如果可能)。

所有单个区域的副本将具有唯一的replica_id,从0开始。具有replica_id == 0的区域副本称为主区域,其他次要区域或辅助。只有主服务器可以接受来自客户端的写入,主服务器将始终包含最新的更改。由于所有写入操作都必须经过主要区域,因此写入操作的可用性不高(意思是说,如果区域不可用,它们可能会阻塞一段时间)。



HBase时间轴一致性(Timeline Consistency)

HBase引入了一致性定义,可以根据读取操作(获取或扫描)提供一致性定义。

Consistency.STRONG是HBase提供的默认一致性模型。如果表的区域复制为1,或者在具有区域副本的表中,但是读取是以此一致性完成的,则读取总是由主区域执行,以便与先前的行为不会发生任何变化,并且客户端总是观察最新的数据。

如果执行读取操作Consistency.TIMELINE,则读取的RPC将首先发送到主要区域服务器。在很短的时间间隔(hbase.client.primaryCallTimeout.get默认为10ms)之后,如果主服务器没有响应,则也会发送用于辅助区域副本的并行RPC。在此之后,结果将从首先完成的RPC中返回。如果响应从主区域副本返回,则我们始终可以知道数据是最新的。为此,Result.isStale()API已被添加到检查失效。如果结果来自辅助区域,则Result.isStale()将被设置为true。然后用户可以检查该字段,以便了解有关数据的可能原因。

就语义而言,HBase实现的TIMELINE一致性与这些方面的纯粹最终一致性不同:

  • 单宿主和有序更新:区域复制与否,在写入端,仍然只有1个定义的副本(主)可以接受写入。此副本负责命令编辑并防止冲突。这保证了两个不同的写入不会被不同的副本同时提交,并且数据发散。有了这个,就不需要进行read-repair或last-timestamp-wins两种中的冲突解决。- 辅助还按照主要承诺的顺序应用编辑。通过这种方式,辅助数据将在任何时间点包含初选数据的快照。这与RDBMS复制相似,甚至与HBase自己的多数据中心复制类似,但在单个集群中也是如此。- 在读取端,客户端可以检测读取是来自最新数据还是旧数据。另外,客户端可以在每个操作的基础上发布具有不同一致性要求的读取,以确保其自身的语义保证。- 客户端仍然可以观察到无序编辑,并且如果它观察到首先从一个辅助副本读取,然后观察到另一个辅助副本的读取,则可以及时返回。对区域副本或基于交易ID的担保没有粘性。如果需要,这可以稍后实施。
    辅助还按照主要承诺的顺序应用编辑。通过这种方式,辅助数据将在任何时间点包含初选数据的快照。这与RDBMS复制相似,甚至与HBase自己的多数据中心复制类似,但在单个集群中也是如此。

客户端仍然可以观察到无序编辑,并且如果它观察到首先从一个辅助副本读取,然后观察到另一个辅助副本的读取,则可以及时返回。对区域副本或基于交易ID的担保没有粘性。如果需要,这可以稍后实施。

//img.mukewang.com/wiki/5bfb70d409d16aa404240256.jpg

为了更好地理解TIMELINE语义,让我们看看上面的图。假设有两个客户端,第一个客户端首先写入x=1,然后x=2和x=3。如上所述,所有写入都由主区域副本处理。写入保存在预写日志(WAL)中,并异步复制到其他副本。在上图中,请注意replica_id=1收到2次更新,其数据显示x=2,而replica_id=2只收到一次更新,其数据显示x=1。

如果client1以STRONG一致性读取,它只会与replica_id=0进行通信,因此保证观察x=3的最新值。如果客户端发出TIMELINE一致性读取,则RPC将转到所有副本(在主超时之后),并且第一个响应的结果将返回。因此,客户端可以将1,2或3看作x的值。假设主区域发生故障并且日志复制无法持续一段时间。如果客户端使用TIMELINE一致性进行多次读取,则它可以先观察x=2,然后观察x=1,依此类推。



HBase时间轴一致性的权衡取舍

在HBase时间轴一致性使用中,拥有用于读取可用性的次要区域会有一些权衡取舍,应根据每个用例仔细评估。以下是优点和缺点。

优点

  • 只读表的高可用性- 过时读取的高可用性- 能够以非常高的百分比(99.9%以上)延迟完成非常低的延迟读取
    过时读取的高可用性

缺点

  • 对于区域复制>1的表,使用双/三重MemStore(取决于区域复制计数)- 增加块缓存使用率- 用于日志复制的额外网络流量- 用于副本的额外备份RPC
    增加块缓存使用率

用于副本的额外备份RPC

为了从多个副本服务区域数据,HBase在区域服务器中以辅助模式打开区域。以辅助模式打开的区域将与主区域副本共享相同的数据文件,但每个辅助区域副本将具有自己的MemStore以保留未刷新的数据(只有主区域可以刷新)。同样为了从次要区域读取数据,数据文件块也可以缓存在次要区域的块缓存中。



HBase时间轴一致性:将写入传播到区域副本

如上所述,在HBase时间轴一致性中,写入只转到主要区域副本。为了将写入从主区域副本传播到次区域,有两种不同的机制。对于只读表,您不需要使用以下任何方法。禁用和启用表格应使数据在所有区域副本中可用。对于可变的表,你必须仅使用下列机制之一:storefile刷新,或异步WAL复制。建议使用后者。

StoreFile复习

第一种机制是在HBase-1.0 +中引入的存储文件刷新。存储文件刷新是每个区域服务器的一个线程,该服务器定期运行,并为辅助区域副本的主区域的存储文件执行刷新操作。如果启用,刷新器将确保次要区域副本及时查看来自主要区域的新刷新,压缩或批量加载的文件。但是,这意味着只有刷新的数据可以从辅助区域副本读取,并且在刷新完成后,使辅助数据在较长的时间内落后于主数据库。 

要打开此功能,您应该将hbase.regionserver.storefile.refresh.period配置为非零值。参见下面的配置部分。

Asnyc WAL复制

写入副本的第二种机制是通过“异步WAL复制”功能完成的,并且仅在HBase-1.1 +中可用。这与HBase的多数据中心复制类似,但是来自区域的数据被复制到次要区域。每个辅助副本总是按照主区域提交的顺序接收和观察写入。从某种意义上说,这种设计可以被认为是“群集内复制”,不是将数据复制到不同的数据中心,而是将数据转移到次要区域,以保持次区域的内存中状态是最新的。数据文件在主区域和其他副本之间共享,因此没有额外的存储开销。但是,次要区域的内存中会有近期未刷新的数据,这增加了内存开销。主要区域也将清除,压缩和批量加载事件写入其WAL,这些事件也通过wal复制复制到辅助节点。当他们观察到刷新/压实或批量加载事件时,次要区域重放该事件以拾取新文件并丢弃旧文件。

以与主服务器相同的顺序提交写入操作可确保次服务器不会偏离主要区域数据,但由于日志复制是异步的,因此数据在次要区域中可能仍旧过时。由于此功能可用作复制端点,因此预计性能和延迟特征与群集间复制类似。 

异步WAL复制默认是禁用的。您可以通过设置hbase.region.replica.replication.enabled为true来启用此功能。当您首次创建区域复制>1的表时,Asyn WAL复制功能将添加一个名为region_replica_replication复制对等点的新复制对等点。启用后,如果要禁用此功能,则需要执行两项操作:(1)将配置属性hbase.region.replica.replication.enabled设置为false hbase-site.xml(请参见下面的配置部分);(2)使用hbase shell或Adminclass禁用集群中指定的复制对等点region_replica_replication:



HBase时间轴一致性:存储文件TTL


HBase时间轴一致性:META表区域的区域复制


HBase时间轴一致性:内存报告

辅助区域副本是指主要区域副本的数据文件,但它们有自己的内存(在HBase-1.1 +中)并使用块缓存。但是,其中一个区别是当辅助区域副本存在内存压力时无法刷新数据。当主区域执行刷新并且该刷新被复制到辅助区域时,它们只能释放内存存储器。由于在承载某些区域的主要副本的区域服务器以及某些区域的副本中,副本可能会导致对同一主机中主要区域的额外刷新。在极端情况下,可能没有剩余内存用于通过wal复制添加来自主节点的新写入。为了解除这种情况(并且由于辅助不能自行冲洗),可以通过执行文件系统列表操作从辅助文件中拾取新文件,并可能丢弃其内存文件,从而允许辅助文件执行“存储文件刷新”。只有当最大的辅助区域副本的存储器大小至少是

主副本最大的内存的hbase.region.replica.storefile.refresh.memstore.multiplier(默认4倍)倍时,才会执行此刷新。需要注意的是,如果执行此操作,辅助节点可以观察整个列族的部分行更新(因为列族是独立刷新的)。默认值应该不会频繁地执行此操作。如果需要,您可以将此值设置为大数以禁用此功能,但要警告它可能会导致复制永久阻塞。



HBase时间轴一致性:辅助副本故障切换


HBase时间轴一致性:配置属性

要使用高可用读取,您应该在hbase-site.xml文件中设置以下属性。没有特定配置可启用或禁用区域副本。相反,您可以在创建表时或使用alter table更改每个表的区域副本数量以增加或减少。以下配置用于使用异步wal复制和使用3的元副本。

服务器端属性

还要记住的一点是,区域副本放置策略仅由StochasticLoadBalancer默认平衡器强制执行。如果您在hbase-site.xml(hbase.master.loadbalancer.class)中使用自定义负载平衡器属性,则区域副本最终可能会托管在同一台服务器中。

客户端属性

确保为将使用区域副本的所有客户端(和服务器)设置以下内容。

注意HBase-1.0.x用户应该使用hbase.ipc.client.allowsInterrupt而不是hbase.ipc.client.specificThreadForWriting。



HBase时间轴一致性:创建具有区域复制的表

区域复制是每个表的属性。默认情况下,所有表都有REGION_REPLICATION=1,这意味着每个区域只有一个副本。您可以通过在表描述符中提供REGION_REPLICATION属性来设置和更改表的每个区域的副本数。

Shell

Java

您还可以使用setRegionReplication()和更改表来增加,减少表的区域复制。



HBase时间轴一致性:读取API和用法

Shell

您可以使用Consistency.TIMELINE语义在shell中进行读取,如下所示:

您可以模拟区域服务器暂停或变得不可用,并从辅助副本执行读取操作:

使用扫描也是类似的:

Java

您可以为Get和Scans设置一致性,并按如下方式执行请求:

您还可以传递多个获取:

以及扫描:

您可以通过调用Result.isStale()方法来检查结果是否来自主区域:



HBase:存储中型对象(MOB)

数据有多种大小,并且在HBase中保存所有数据(包括图像和文档等二进制数据)是理想的选择。虽然HBase在技术上可以处理大小超过100 KB的单元格的二进制对象,但HBase的正常读取和写入路径针对小于100KB的值进行了优化。当HBase处理超过此阈值的大量对象(此处称为中型对象或MOB)时,由于拆分和压缩引起的写入放大,性能会降低。使用MOB时,理想情况下,您的对象将介于100KB和10MB之间(请参阅常见问题解答)。HBase FIX_VERSION_NUMBER增加了对更好地管理大量MOB的支持,同时保持了性能,一致性和低运营开销。MOB支持是由HBASE-11339完成的工作提供的。要利用MOB,您需要使用HFile版本3。(可选)为每个RegionServer配置MOB文件读取器的缓存设置(请参阅配置MOB缓存),然后配置特定列以保存MOB数据。客户端代码无需更改即可利用HBase MOB支持。该功能对客户端是透明的。

MOB压缩

在MemStore刷新后,MOB数据被刷新到MOB文件中。一段时间后会有很多MOB文件。为了减少MOB文件数量,有一个周期性任务可以将小型MOB文件压缩成大型MOB文件(MOB压缩)。



HBase:为MOB配置列

您可以在表创建或更改期间配置列以支持MOB,无论是在HBase Shell中还是通过Java API。两个相关的属性是boolean IS_MOB和MOB_THRESHOLD,它是一个对象被认为是MOB的字节数,只需要IS_MOB。如果未指定MOB_THRESHOLD,则使用默认阈值100 KB。

使用HBase Shell为MOB配置列:

示例23.使用Java API为MOB配置列:



HBase:配置MOB压缩策略

默认情况下,一个特定日期的MOB文件会压缩为一个大型MOB文件。为了更多地减少MOB文件数,还支持其他MOB压缩策略:

  1. 每日(daily)策略 - 每天将MOB文件压缩为一个大型MOB文件(默认策略)
    1. 每周(weekly)策略 - 每周将MOB文件压缩为一个大型MOB文件
    1. 每月(montly)策略 - 每月将MOB文件压缩为一个大型MOB文件
    每周(weekly)策略 - 每周将MOB文件压缩为一个大型MOB文件

使用HBase Shell配置MOB压缩策略:



HBase:配置MOB压缩可合并阈值

如果一个mob文件的大小小于默认值1280MB,它被认为是一个小文件,需要在mob compaction中合并。



HBase:测试MOB

HBase中提供了实用程序org.apache.hadoop.hbase.IntegrationTestIngestWithMOB以帮助测试MOB功能。该实用程序运行如下:

  • threshold是当cells被认为是MOB时的阈值;默认值为1 kB,以字节为单位表示。- minMobDataSize是MOB数据大小的最小值;默认值为512 B,以字节为单位表示。- maxMobDataSize是MOB数据大小的最大值;默认值为5 kB,以字节为单位表示。
    minMobDataSize是MOB数据大小的最小值;默认值为512 B,以字节为单位表示。


HBase:配置MOB缓存

因为可以随时存在大量MOB文件,与HFiles的数量相比,MOB文件并不总是保持打开状态。MOB文件读取器缓存是一个LRU缓存,它保持最近使用的MOB文件打开。要在每个RegionServer上配置MOB文件读取器的缓存,请将以下属性添加到RegionServer的hbase-site.xml中,根据您的环境自定义配置,然后重新启动或滚动重新启动RegionServer。

MOB缓存配置示例:



HBase:MOB优化任务

手动压缩MOB文件

要手动压缩MOB文件,而不是等待配置触发压缩,请使用compact或major_compactHBase shell命令。这些命令要求第一个参数为表名,并将列族作为第二个参数。并将压缩类型作为第三个参数。

这些命令也可以通过Admin.compact和Admin.majorCompact方法获得。



HBase内存压缩

概述

内存压缩(AKA Accordion)是hbase-2.0.0中的一项新功能。它首先在Accordion的Apache HBase博客上推出 :通过内存压缩进行HBase Breathes。引用博客:

Accordion重新应用LSM主体[ Log-Structured-Merge Tree,HBase基于MemStore的设计模式,以便在数据仍在RAM中时消除冗余和其他开销。这样做可以降低刷新到HDFS的频率,从而减少写入放大和整个磁盘占用空间。由于刷新次数较少,因此MemStore溢出时写入操作停止的频率降低,因此写入性能得到改善。磁盘上的数据越少,对块缓存的压力越小,命中率越高,最终读取响应时间越长。最后,减少磁盘写入也意味着在后台执行的压缩更少,即从生产(读取和写入)工作中窃取的周期更少。总而言之,内存压缩的效果可以被设想为催化剂,使系统整体上移动得更快。

Accordion提供开发人员视图:内存压缩的开发人员视图。

内存压缩在大量数据流失时效果最佳;当数据仍在内存中时,可以消除覆盖或过度版本。如果写入都是唯一的,则可能会拖动写入吞吐量(内存中压缩成本CPU)。我们建议您在部署到生产之前进行测试和比较。



启用HBase内存压缩

要启用HBase的内存压缩,请在您希望的行为的每个列族上设置IN_MEMORY_COMPACTION属性。该IN_MEMORY_COMPACTION属性可以是四个值之一:

  • NONE:没有内存压缩。- BASIC:基本策略允许刷新并保持一个刷新管道,直到我们跳过管道最大阈值,然后我们刷新到磁盘。没有内存压缩,但可以帮助提高吞吐量,因为数据从挥霍的原生ConcurrentSkipListMap数据类型转移到更紧凑(和高效)的数据类型。- EAGER:这是基本的策略加上内存压缩的刷新(很像是对hfiles进行的磁盘上压缩);在压缩时,我们应用磁盘规则来消除版本,重复,ttl’d单元格等。- ADAPTIVE:自适应压缩适应工作负载。它根据数据中重复单元格的比例应用索引压缩或数据压缩。实验。
    BASIC:基本策略允许刷新并保持一个刷新管道,直到我们跳过管道最大阈值,然后我们刷新到磁盘。没有内存压缩,但可以帮助提高吞吐量,因为数据从挥霍的原生ConcurrentSkipListMap数据类型转移到更紧凑(和高效)的数据类型。

ADAPTIVE:自适应压缩适应工作负载。它根据数据中重复单元格的比例应用索引压缩或数据压缩。实验。

要在radish表中的info列系列上启用BASIC,请禁用该表并将该属性添加到info列族,然后重新启用:

请注意IN_MEMORY_COMPACTION属性如何显示为METADATA映射的一部分。

还有一个全局配置hbase.hregion.compacting.memstore.type,您可以在hbase-site.xml文件中设置该配置。使用它来设置创建新表时的默认值(在创建列族存储时,我们首先查看列族配置,以查找IN_MEMORY_COMPACTION设置 ,如果没有,我们将查询hbase.hregion.compacting.memstore .type值使用其内容;默认为BASIC)。

默认情况下,新的hbase系统表将具有BASIC内存中压缩集。若要另行指定,在新表创建时,将hbase.hregion.compacting.memstore.type设置为NONE(注意,设置此值后创建系统表将不具有追溯效果;您将必须更改表以设置内存属性为NONE)。

当内存刷新发生时,通过将已配置的区域刷新大小(在表描述符中设置或从hbase.hregion.memstore.flush.size读取)除以列族数,然后乘以hbase.memstore.inmemoryflush.threshold.factor来计算。默认值为0.014。

监视管道承载的刷新次数,以便符合memstore大小调整的范围,但您也可以通过设置hbase.hregion.compacting.pipeline.segments.limit来设置总刷新次数的最大值。默认值为2。

创建列族Store时,它会说明哪些memstore类型有效。在撰写本文时,有一个老式的DefaultMemStore,它填充ConcurrentSkipListMap,然后刷新到磁盘或新的CompactingMemStore,它是提供这种新的内存中压缩工具的实现。以下是来自RegionServer的日志行,该日志行显示了一个名为family的列族Store,配置为使用CompactingMemStore:

请注意IN_MEMORY_COMPACTION属性如何显示为_METADATA_映射的一部分。

在CompactingMemStore类(org.apache.hadoop.hbase.regionserver.CompactingMemStore)上启用TRACE级别日志记录,以查看其操作的详细信息。



HBase备份与还原

备份和还原是许多数据库提供的标准操作。有效的备份和还原策略有助于确保用户可以在发生意外故障时恢复数据。HBase备份和还原功能有助于确保使用HBase作为规范数据存储库的企业可以从灾难性故障中恢复。另一个重要功能是能够将数据库还原到特定时间点,通常称为快照。

HBase备份和还原功能可以在HBase集群中的表上创建完整备份和增量备份。完整备份是应用增量备份以构建迭代快照的基础。可以按计划运行增量备份以捕获一段时间内的更改,例如通过使用Cron任务。增量备份比完全备份更具成本效益,因为它们仅捕获自上次备份以来的更改,并且还使管理员能够将数据库还原到任何先前的增量备份。此外,如果您不想还原备份的整个数据集,则实用程序还可以启用表级数据备份和还原。

备份和还原功能是对HBase Replication(复制)功能的补充。虽然HBase复制非常适合创建数据的“hot”副本(复制数据可立即用于查询),但备份和恢复功能非常适合创建“cold”数据副本(必须采取手动步骤来恢复系统)。以前,用户只能通过ExportSnapshot功能创建完整备份。增量备份实现是对ExportSnapshot提供的先前“art”的新颖改进。

术语

备份和还原功能引入了新术语,可用于了解控制如何在系统中流动。

  • 备份(A backup):数据和元数据的逻辑单元,可以将表还原到特定时间点的状态。- 完全备份(Full backup):一种备份类型,它在某个时间点完全封装表的内容。- 增量备份(Incremental backup):一种备份类型,包含自完整备份以来表中的更改。- 备份集(Backup set):用户定义的名称,用于引用可在其上执行备份的一个或多个表。- 备份ID(Backup ID):唯一的名称,用于标识其余备份,例如,backupId_1467823988425
    完全备份(Full backup):一种备份类型,它在某个时间点完全封装表的内容。

备份集(Backup set):用户定义的名称,用于引用可在其上执行备份的一个或多个表。



HBase备份与还原策略

策略

有一些常用策略可用于在您的环境中实现备份和还原。以下部分显示了如何实施这些策略并确定每种策略的潜在权衡。

此备份和还原工具尚未在启用透明数据加密(TDE)的HDFS群集上进行测试。这与开放式问题HBASE-16178有关。

在群集内备份

此策略将备份存储在与执行备份的位置相同的群集上。这种方法仅适用于测试,因为它不会在软件本身提供的内容之外提供任何额外的安全性。

//img.mukewang.com/wiki/5bfba4c4095ea39202250208.jpg

使用专用群集进行备份

该策略提供了更高的容错能力,并为灾难恢复提供了途径。在此设置中,您将备份存储在单独的HDFS群集上,方法是将备份目标群集的HDFS URL提供给备份实用程序。您应该考虑备份到不同的物理位置,例如不同的数据中心。

通常,备份专用HDFS群集使用更经济的硬件配置文件来节省资金。

//img.mukewang.com/wiki/5bfba4e30959950803630185.jpg

备份到云或存储供应商设备

保护HBase增量备份的另一种方法是将数据存储在属于第三方供应商且位于站点外的配置的安全服务器上。供应商可以是公共云提供商或使用Hadoop兼容文件系统(例如S3和其他与HDFS兼容的目标)的存储供应商。

//img.mukewang.com/wiki/5bfba50009f5589503690193.jpg

HBase备份实用程序不支持备份到多个目标,解决方法是从HDFS或S3手动创建备份文件的副本。



HBase备份与还原的首次配置

首次配置步骤

本节包含为使用备份和还原功能而必须进行的必要配置更改。由于此功能大量使用YARN的MapReduce框架来并行化这些I/O重载操作,因此配置更改不仅仅局限于此hbase-site.xml。

允许YARN中的“hbase”系统用户

YARN container-executor.cfg配置文件必须具有以下属性设置:allowed.system.users = hbase。此配置文件的条目中不允许有空格。

执行第一个备份任务时,跳过此步骤将导致运行时错误。

用于备份和还原的有效container-executor.cfg文件的示例:

HBase特定的变化

将以下属性添加到hbase-site.xml并重新启动HBase(如果它已在运行)。

“,…”是省略号,意味着这是一个以逗号分隔的值列表,而不是应该添加到hbase-site.xml的文字文本。



HBase备份和还原命令

这部分的内容包括管理员用于创建,还原和合并备份的命令行实用程序。有关检查特定备份会话详细信息的工具将在“备份映像管理”中介绍。

运行该hbase backup help <command>命令以访问联机帮助,该联机帮助提供有关命令及其选项的基本信息。以下信息将在此帮助消息中针对每个命令进行捕获。



Hbase创建备份映像

HBase备份的情况下,对系统目录表的访问可以帮助您恢复Phoenix与还原的数据的互操作性。

运行备份和还原实用程序的第一步是执行完整备份,并将数据存储在与源不同的映像中。至少,您必须执行此操作才能获得基准,然后才能依赖增量备份。

以HBase超级用户身份运行以下命令:

命令完成运行后,控制台将显示SUCCESS或FAILURE状态消息。SUCCESS消息包括备份ID,备份ID是HBase主机从客户端收到备份请求的Unix时间(也称为Epoch时间)。

记录在成功备份结束时出现的备份ID。如果源群集出现故障,并且您需要使用还原操作恢复数据集,则具有可用的备份ID可以节省时间。

位置命令行参数

type

要执行的备份类型:完整备份或增量备份。提醒一下,增量备份需要已完全备份。

BACKUP_PATH

该BACKUP_PATH参数指定来存储备份映像文件系统的完整URI的地方。有效的前缀是hdfs:,webhdfs:,gpfs:和s3fs :

命名命令行参数

-t <table_name [,table_name]>

要备份的以逗号分隔的表列表。如果未指定表,则备份所有表。不存在正则表达式或通配符支持; 必须明确列出所有表名。有关对表集合执行操作的详细信息,请参阅备份集(这将在之后的章节中进行介绍)。与-s选项互斥;其中一个命名选项是必需的。

-s <backup_set_name>

根据备份集确定要备份的表。有关备份集的用途和用法,请参阅使用备份集。与-t选项互斥。

-w <number_workers>

(可选)指定将数据复制到备份目标的并行工作器数。备份当前由MapReduce作业执行,因此该值对应于作业将生成的Mapper数。

-b <bandwidth_per_worker>

(可选)指定每个工作线程的带宽,以MB/秒为单位。

-d

(可选)启用“DEBUG”模式,该模式打印有关备份创建的其他日志记录。

-q <name>

(可选)允许指定应在其中执行创建备份的MapReduce作业的YARN队列的名称。此选项有助于防止备份任务从其他高重要性MapReduce作业中窃取资源。

用法示例

此命令在HDFS实例中创建两个表SALES2和SALES3的完整备份映像,这两个表在路径/data/backup中的NameNode为host5:8020。w选项指定不超过三个并行工作完成操作。



HBase恢复备份映像

以HBase超级用户身份运行以下命令。您只能在正在运行的HBase集群上还原备份,因为必须将数据重新分发到RegionServers才能成功完成操作。

BACKUP_PATH

该BACKUP_PATH参数指定的地方用来存储备份映像文件系统的完整URI。有效的前缀是hdfs:,webhdfs:,gpfs:和s3fs :

备份ID

唯一标识要还原的备份映像的备份ID。

命名命令行参数

-t <table_name [,table_name]>

要还原的以逗号分隔的表列表。有关对表集合执行操作的详细信息,请参阅备份集。与-s选项互斥;其中一个命名选项是必需的。

-s <backup_set_name>

根据备份集确定要备份的表。有关备份集的用途和用法,请参阅使用备份集。与-t选项互斥。

-q <name>

(可选)允许指定应在其中执行创建备份的MapReduce作业的YARN队列的名称。此选项有助于防止备份任务从其他高重要性MapReduce作业中窃取资源。

-C

(可选)执行还原的干运行(dry-run)。会检查操作,但不执行。

-m <target_tables>

(可选)要还原到的以逗号分隔的表列表。如果未提供此选项,则使用原始表名。提供此选项时,必须提供与-t选项中相同数量的条目。

-o

(可选)如果表已存在,则覆盖还原的目标表。

用法示例

此命令将恢复增量备份映像的两个表。在此示例中:

  • /tmp/backup_incremental是包含备份映像的目录的路径。
    - backupId_1467823988425是备份ID。
    - mytable1和mytable2是要还原的备份映像中的表的名称。
    backupId_1467823988425是备份ID。


HBase合并增量备份映像

此命令可用于将两个或多个增量备份映像合并为单个增量备份映像。这可用于将多个小型增量备份映像合并为一个较大的增量备份映像。此命令可用于将每小时增量备份合并到每日增量备份映像中,或将每日增量备份合并到每周增量备份中。

位置命令行参数

backup_ids

以逗号分隔的增量备份映像ID列表,它们将组合到单个映像中。

命名命令行参数

没有。

用法示例



HBase使用备份集

备份集可以通过减少表名重复输入的数量来简化HBase数据备份和还原的管理。您可以使用该hbase backup set add命令将表分组到命名备份集中。然后,您可以使用-set选项在hbase backup create或hbase backup restore中调用备份集的名称,而不是单独列出组中的每个表。您可以拥有多个备份集。

请注意hbase backup set add命令和-set选项之间的区别:必须先运行该hbase backup set add命令,然后才能在其他命令中使用该-set选项,因为在将备份集用作快捷方式之前,必须先命名并定义备份集。

如果运行该hbase backup set add命令并指定系统上尚不存在的备份集名称,则会创建一个新集。如果使用现有备份集名称的名称的命令,则指定的表将添加到该集合中。

在此命令中,备份集名称区分大小写。

备份集的元数据存储在HBase中。如果您无法访问具有备份集元数据的原始HBase群集,则必须指定单个表名以还原数据。

要创建备份集,请以HBase超级用户身份运行以下命令:

备份集子命令

以下列表详细介绍了hbase backup set命令的子命令。

在hbase backup set设置完成操作后,必须输入以下子命令中的一个(且不超过一个)。此外,备份集名称在命令行实用程序中区分大小写。

add

将表[s]添加到备份集。在此参数后面指定backup_set_name值以创建备份集。

remove

从集中删除表。在tables参数中指定要删除的表。

list

列出所有备份集。

describe

显示备份集的描述。该信息包括该集是否具有完整备份或增量备份,备份的开始和结束时间以及集合中的表列表。此子命令必须位于backup_set_name值的有效值之前。

delete

删除备份集。在命令后直接输入backup_set_name选项的值hbase backup set delete。

位置命令行参数

backup_set_name

用于分配或调用备份集名称。备份集名称必须仅包含可打印字符,并且不能包含任何空格。

tables

要包含在备份集中的表(或单个表)的列表。输入表名作为逗号分隔列表。如果未指定表,则所有表都包含在集中。

在单独或远程群集的备份策略中维护区分大小写的备份集名称的日志或其他记录以及每个集合中的相应表。此信息可以帮助您在主群集失败的情况下进行。

用法示例

根据不同的环境,在此命令导致一个以下操作:

  • 如果Q1Data备份集不存在,则创建包含表TEAM_3和TEAM_4的备份集。- 如果Q1Data备份集已经存在,表TEAM_3和TEAM_4添加到Q1Data备份集。
    如果Q1Data备份集已经存在,表TEAM_3和TEAM_4添加到Q1Data备份集。


HBase备份图像管理

该hbase backup命令有几个子命令,可帮助管理备份映像的累积。大多数生产环境都需要重复备份,因此必须使用实用程序来帮助管理备份存储库的数据。通过某些子命令,您可以查找有助于识别与搜索特定数据相关的备份的信息。您也可以删除备份映像。

本章内容详细介绍了可以帮助管理备份的hbase backup subcommand,以HBase超级用户身份运行完整的command-subcommand行。



HBase管理备份进度

您可以通过运行hbase backup progress命令并将备份ID指定为参数来监视另一个终端会话中正在运行的备份。

例如,以hbase超级用户身份运行以下命令以查看备份进度:

位置命令行参数

backup_id

通过查看进度信息指定要监视的备份,backupId需要区分大小写。

命名命令行参数

没有。

用法示例



HBase管理备份历史记录

此命令显示备份会话日志。每个会话的信息包括备份ID、类型(完整或增量),备份中的表、状态以及开始和结束时间。使用可选的-n参数指定要显示的备份会话数。

位置命令行参数

backup_id

通过查看进度信息指定要监视的备份,backupId要区分大小写。

命名命令行参数

-n <num_records>

(可选)最大备份记录数(默认值:10)。

-p <backup_root_path>

存储备份映像的完整文件系统URI。

-s <backup_set_name>

要获取其历史记录的备份集的名称。与-t选项互斥。

-t <table_name>

获取历史记录的表的名称。与-s选项互斥。

用法示例



HBase描述备份映像

此命令可用于获取有关特定备份映像的信息。

位置命令行参数

backup_id

要描述的备份映像的ID。

命名命令行参数

没有。

用法示例



HBase删除备份映像

此命令可用于删除不再需要的备份映像。

位置命令行参数

backup_id

应该删除备份映像的ID。

命名命令行参数

没有。

用法示例



HBase备份修复命令

此命令尝试更正由于软件错误或未处理的失败方案而存在的持久备份元数据中的任何不一致之处。虽然备份实现尝试自行更正所有错误,但在系统无法自动恢复的情况下,此工具可能是必需的。

没有。

命名命令行参数

没有。

用法示例



HBase配置密钥

备份和还原功能包括必需的和可选的配置密钥。

必需的属性

hbase.backup.enable:控制是否启用该功能,默认值为false,将此值设置为true。

hbase.master.logcleaner.plugins:清除HBase Master中的日志时调用的逗号分隔的类列表。将此值设置为org.apache.hadoop.hbase.backup.master.BackupLogCleaner或将其附加到当前值。

hbase.procedure.master.classes:使用Master中的Procedure框架调用的逗号分隔的类列表。将此值设置为org.apache.hadoop.hbase.backup.master.LogRollMasterProcedureManager或将其附加到当前值。

hbase.procedure.regionserver.classes:使用RegionServer中的Procedure框架调用的逗号分隔的类列表。将此值设置为org.apache.hadoop.hbase.backup.regionserver.LogRollRegionServerProcedureManager或将其附加到当前值。

hbase.coprocessor.region.classes:在表上部署的以逗号分隔的RegionObservers列表。将此值设置为org.apache.hadoop.hbase.backup.BackupObserver或将其附加到当前值。

hbase.master.hfilecleaner.plugins:在Master上部署的以逗号分隔的HFileCleaners列表。将此值设置为org.apache.hadoop.hbase.backup.BackupHFileCleaner或将其附加到当前值。

可选属性

hbase.backup.system.ttl:hbase:backup表中数据的生存时间(默认值:forever)。此属性仅在创建hbase:backup表之前相关。当此表已存在时,使用HBase shell中的“alter”命令修改TTL。

hbase.backup.attempts.max:获取hbase表快照时执行的尝试次数(默认值:10)。

hbase.backup.attempts.pause.ms:失败的快照尝试之间等待的时间(以毫秒为单位)(默认值:10000)。

hbase.backup.logroll.timeout.millis:等待RegionServers在Master的过程框架中执行WAL滚动的时间(以毫秒为单位)(默认值:30000)。



HBase备份与还原的最佳做法

制定恢复策略并对其进行测试

在依赖生产环境的备份和还原策略之前,请确定必须如何执行备份,更重要的是要确定必须如何执行还原。测试计划以确保它是可行的。至少,从不同群集或服务器上的生产群集存储备份数据。要进一步保护数据,请使用位于不同物理位置的备份位置。 

如果由于计算机系统问题导致主生产群集上的数据丢失不可恢复,则可以从同一站点的其他群集或服务器还原数据。但是,破坏整个站点的灾难使本地存储的备份变得毫无用处。考虑存储备份数据和必要资源(计算能力和操作员专业技能),以便在远离生产站点的站点上还原数据。如果在整个主要站点(fire,earthquake等)发生灾难的情况下,远程备份站点可能非常有价值。

首先保护完整备份映像

作为基准,您必须至少完成一次HBase数据的完整备份,然后才能依赖增量备份。完整备份应存储在源群集之外。要确保完整的数据集恢复,您必须运行恢复实用程序,并提供恢复基准完全备份的选项。完整备份是数据集的基础。在还原操作期间,增量备份数据应用于完整备份之上,以使您返回上次执行备份的时间点。 

定义和使用作为整个数据集的逻辑子集的表组和备份集

您可以将表分组到称为备份集的对象中。当您拥有一组您希望重复备份或还原的特定表组时,备份集可以节省时间。 

创建备份集时,可以键入要包括在组中的表名。备份集不仅包括相关表组,还保留HBase备份元数据。之后,您可以调用备份集名称来指示哪些表适用于命令执行,而不是单独输入所有表名。

记录备份和还原策略,最好记录有关每个备份的信息

记录整个过程,以便知识库可以在员工离职后转移给新的管理员。作为额外的安全预防措施,还要记录每个备份的数据的日历日期、时间以及其他相关详细信息。在源群集发生故障或主站点灾难的情况下,此元数据可能有助于查找特定数据集。维护所有文档的重复副本:一个副本位于生产集群站点,另一个副本位于备份位置,或者任何管理员可以从生产集群远程访问的地方。



HBase方案:在Amazon S3上保护应用程序数据集

此HBase方案描述了假设的零售业务如何使用备份来保护应用程序数据, 然后在失败后还原数据集。

HBase 管理团队使用备份集来存储一组表中的数据, 它们具有一个名为绿色的应用程序的相关信息。在此示例中, 一个表包含交易记录, 另一张包含客户详细信息。需要备份这两个表并作为一个组进行恢复。

管理团队还希望确保自动进行每日备份。

//img.mukewang.com/wiki/5bfbb4b409a174d302930276.jpg

以下是用于备份绿色应用程序的数据并稍后恢复数据的命令的步骤和示例的概述。以HBase超级用户身份登录时,将运行所有命令。 

  • 创建名为green_set的备份集作为transactions表和customer表的别名。备份集可用于所有操作,以避免键入每个表名。备份集名称区分大小写,应仅使用可打印字符且和不带空格的格式生成。- green_set数据的第一个备份必须是完整备份。以下命令示例显示如何将凭据传递到Amazon S3并使用s3a:前缀指定文件系统。- 应根据计划运行增量备份,以确保在发生灾难时进行必要的数据恢复。在这家零售公司,HBase管理团队决定自动每日备份以充分保护数据。团队决定他们可以通过修改在/etc/crontab中定义的现有Cron作业来实现此目的。因此,IT通过添加以下行来修改Cron作业:- 失败性IT事件会禁用绿色应用程序使用的生产群集。备份群集的HBase系统管理员必须将green_set数据集还原到最接近恢复目标的时间点。
    如果备份HBase群集的管理员具有可访问记录中具有相关详细信息的备份ID,则可以绕过以下使用该hdfs dfs -ls命令搜索和手动扫描备份ID列表的搜索。请考虑在环境中的生产群集外部持续维护和保护备份ID的详细日志。 
    管理员在存储备份的目录上运行以下命令,以在控制台上打印成功备份ID的列表:- 管理员扫描列表以查看在最接近恢复目标的日期和时间创建的备份。为此,管理员将恢复时间点的日历时间戳转换为Unix时间,因为备份ID是用Unix时间唯一标识的。备份ID按反向时间顺序列出,这意味着最先出现的最新成功备份。管理员注意到命令输出中的以下行与需要还原的green_set备份相对应:- 管理员恢复green_set调用备份ID和-overwrite选项。-overwrite选项截断目标中的所有现有数据,并使用备份数据集中的数据填充表。如果没有此标志,备份数据将附加到目标中的现有数据。在这种情况下,管理员决定覆盖数据,因为它已损坏。


HBase备份数据的安全性

使用此功能可以将数据复制到远程位置,需要花点时间清楚地说明数据安全性存在的程序问题。与HBase复制功能一样,备份和还原提供了将数据从公司边界内部自动复制到该边界之外的某个系统的构造。在存储具有备份和还原功能的敏感数据时(更不用说从HBase中提取数据的任何功能),发送数据的位置都经过安全审核以确保只有经过身份验证的用户才能访问数据。

例如,对于上一节中将数据备份到S3的示例,最重要的是将适当的权限分配给S3存储桶以确保仅允许最小的一组授权用户访问该数据。由于不再通过HBase访问数据及其身份验证和授权控制,因此我们必须确保存储该数据的文件系统提供相当级别的安全性。这是用户必须自己实施的手动步骤。



HBase增量备份和还原的技术细节

与以前尝试使用串行备份和还原解决方案(例如仅使用HBase导出和导入API的方法)相比,HBase增量备份可以更有效地捕获HBase表映像。增量备份使用“预写日志(WAL)”来捕获自上次备份创建以来的数据更改。在所有RegionServers上执行WAL roll(创建新的WAL)以跟踪需要在备份中的WAL。

创建增量备份映像后,源备份文件通常与数据源位于同一节点上。类似于DistCp(分布式副本)工具的过程用于将源备份文件移动到目标文件系统。当表还原操作启动时,启动两个步骤的进程。首先,从完整备份映像恢复完整备份。其次,来自上次完全备份和正在恢复的增量备份之间的增量备份的所有WAL文件都将转换为HFiles,HBase批量加载实用程序会自动将其导入为表中的已还原数据。

您只能在实时的HBase群集上进行还原,因为必须重新分发数据才能成功完成还原操作。



HBase关于文件系统增长的警告

需要提醒的是,增量备份是通过保留HBase主要用于数据持久性的预写日志来实现的。因此,为确保需要包含在备份中的所有数据在系统中仍然可用,HBase备份和还原功能将保留自上次备份以来的所有预写日志,直到执行下一个增量备份。

与HBase快照一样,对于高容量表,这可能对HBase的HDFS使用产生预期的巨大影响。注意启用和使用备份和还原功能,尤其要注意在未主动使用备份会话时删除备份会话。

对于保留的用于备份和恢复的预写日志,惟一的自动上限是基于hbase:backup system表的TTL,在撰写本文档时,这是无限的(备份表项永远不会自动删除)。这要求管理员按照计划执行备份,该计划的频率相对于HDFS上的可用空间量(例如,较少的可用HDFS空间需要更积极的备份合并和删除)。提醒一下,可以使用HBase shell中的alter命令在hbase:backup表上更改TTL 。在系统表存在后修改hbase-site.xml中的配置属性hbase.backup.system.ttl是无效的。



HBase容量规划

在设计分布式系统部署时,必须执行一些基本的数学严谨性,以确保在给定系统的数据和软件要求的情况下有足够的计算能力。对于此功能,在估计某些备份和还原实施的性能时,网络容量的可用性是最大的瓶颈。第二个最昂贵的功能是可以读/写数据的速度。

完全备份

要估计完整备份的持续时间,我们必须了解调用的一般操作:

  • 每个RegionServer上的预写日志滚动:每个RegionServer并行运行几十秒。相对于每个RegionServer的负载。- 获取表格的HBase快照:几十秒。相对于构成表的区域和文件的数量。- 将快照导出到目标:请参阅下文。相对于数据的大小和到到目标的网络带宽。
    获取表格的HBase快照:几十秒。相对于构成表的区域和文件的数量。

为了估计最后一步将花费多长时间,我们必须对硬件做出一些假设。请注意,这些对您的系统来说并不准确 - 这些是您或您的管理员为您的系统所知的数字。假设在单个节点上从HDFS读取数据的速度上限为80MB / s(在该主机上运行的所有Mapper上),现代网络接口控制器(NIC)支持10Gb / s,架顶式交换机可以处理40Gb / s,集群之间的WAN为10Gb / s。这意味着您只能以1.25GB / s的速度将数据发送到远程控制器 - 这意味着参与ExportSnapshot的16个节点(1.25 * 1024 / 80 = 16)应该能够完全饱和集群之间的链接。由于群集中有更多节点,我们仍然可以使网络饱和,但对任何一个节点的影响较小,这有助于确保本地SLA。如果快照的大小是10TB,这将完全备份将花费2.5小时(10 * 1024 / 1.25 / (60 * 60) = 2.23hrs)

作为一般性声明,本地群集与远程存储之间的WAN带宽很可能是完全备份速度的最大瓶颈。

当考虑将备份的计算影响限制为“生产系统”时,可以使用可选的命令行参数对hbase backup create: -b、-w、-q进行重用。该-b选项定义每个worker(Mapper)写入数据的带宽。该-w参数限制了在DistCp作业中生成的工作者数量。该-q允许指定的YARN队列可以可以限制生成worker的特定节点——这可以隔离备份工人执行复制到一组非关键节点。将-b和-w选项与前面的公式关联起来:-b用于限制每个节点读取80MB/s的数据,-w用于限制作业产生16个worker任务。

增量备份

就像我们为完整备份所做的那样,我们必须了解增量备份过程,以估计其运行时间和成本。

  • 识别自上次完全备份或增量备份以来的新预写日志:可忽略不计。来自备份系统表的Apriori知识。- 读取,过滤和写入“最小化”HFile相当于WAL:以写入数据的速度为主。相对于HDFS的写入速度。- 将HFiles分配到目的地:见上文。
    读取,过滤和写入“最小化”HFile相当于WAL:以写入数据的速度为主。相对于HDFS的写入速度。

对于第二步,该操作的主要成本是重写数据(假设WAL中的大部分数据被保留)。在这种情况下,我们可以假设每个节点的聚合写入速度为30MB / s。继续我们的16节点集群示例,这将需要大约15分钟来执行50GB数据(50 * 1024/60/60 = 14.2)的此步骤。启动DistCp MapReduce作业的时间可能会占据复制数据所需的实际时间(50 / 1.25 = 40秒)并且可以忽略。



HBase备份和还原实用程序的限制

串行备份操作

备份操作不能同时运行。操作包括创建,删除,还原和合并等操作。仅支持一个活动备份会话。HBASE-16391 将引入多备份会话支持。

无法取消备份

备份和还原操作都无法取消。(HBASE-15997,HBASE-15998)。取消备份的解决方法是终止客户端备份命令(control-C),确保已退出所有相关的MapReduce作业,然后运行该hbase backup repair命令以确保系统备份元数据一致。

备份只能保存到单个位置

将备份信息复制到多个位置是留给用户的练习。HBASE-15476将引入本质上指定多备份目标的功能。

需要HBase超级用户访问权限

只允许HBase超级用户(例如hbase)可以执行备份/恢复,这可能会对共享HBase安装造成问题。当前的缓解措施需要与系统管理员协调,以构建和部署备份和还原策略(HBASE-14138)。

备份还原是一种在线操作

要从备份执行还原,它需要HBase集群在线作为当前实现(HBASE-16573)的警告。

某些操作可能会失败并需要重新运行

HBase备份功能主要由客户端驱动。虽然HBase连接中内置了标准的HBase重试逻辑,但执行操作中的持久性错误可能会传播回客户端(例如,由于区域拆分导致的快照失败)。应将备份实现从客户端移到将来的ProcedureV2框架中,这将为瞬态/可重试故障提供额外的稳健性。该hbase backup repair命令用于纠正系统无法自动检测和恢复的状态。

避免公开API的声明

虽然存在与此功能交互的Java API,并且它的实现与接口分离,但没有足够的严格性来确定它是否正是我们要向用户运送的。因此,它被标记为一个Private受众,期望随着用户开始尝试该功能,将有必要修改兼容性(HBASE-17517)。

缺乏备份和还原的全局指标

单独的备份和还原操作包含有关操作所包含的工作量的指标,但没有集中位置(例如主用户界面),它提供信息用于消费(HBASE-16565)。



HBase同步复制

HBase中的当前的异步复制。因此,如果主集群崩溃,则从属集群可能没有最新数据。如果用户想要强一致性,那么他们就无法切换到从属集群。

设计

请参阅HBASE-19064上的设计文档

运行和维护

Case.1设置两个同步复制集群

  • 在源集群和对等集群中添加同步对等体。
    对于源集群:

对于对等集群:

对于同步复制,当前实现要求源和对等集群具有相同的对等ID。另一件需要注意的事情是:对等体不支持集群级,命名空间级或cf级复制,现在只支持表级复制。

  • 将对等集群转换为STANDBY状态- 将源群集转换为ACTIVE状态
    现在,已成功设置同步复制。HBase客户端只能请求源集群,如果请求到对等集群,则现在处于STANDBY状态的对等集群将拒绝读/写请求。

Case.2备用集群崩溃时的操作方法

如果备用群集已崩溃,则无法为活动群集写入远程WAL。所以我们需要将源集群转移到DOWNGRANDE_ACTIVE状态,这意味着源集群将不再写任何远程WAL,但正常复制(异步复制)仍然可以正常工作,它会对新写入的WAL进行排队,但是复制块直到对等集群返回。

一旦对等集群返回,我们就可以将源集群转移到ACTIVE,以确保复制是同步的。

Case.3活动集群崩溃时的操作方法

如果活动集群已崩溃(现在可能无法访问),那么让我们将备用集群转移到DOWNGRANDE_ACTIVE状态,之后,我们应该将所有请求从客户端重定向到DOWNGRADE_ACTIVE集群。

如果崩溃的集群再次返回,我们只需要将其直接转移到STANDBY。否则,如果将集群传输到DOWNGRADE_ACTIVE,则原始ACTIVE群集可能具有与当前ACTIVE集群相比的冗余数据。因为我们设计的是同时编写源集群WAL和远程集群WAL,所以源集群WALs可能比远程集群具有更多数据,这导致数据不一致。将ACTIVE转换为STANDBY的过程没有问题,因为我们将跳过重放原始的WAL。

然后,我们现在可以将DOWNGRADE_ACTIVE集群提升为ACTIVE,以确保复制是同步的。



Apache HBase API

本章提供有关使用HBase本机API执行操作的信息。此信息并非详尽无遗,除了User API Reference之外,还提供了快速参考。此处的示例不全面,仅用于说明目的。

Apache HBase也适用于多个外部API。有关更多信息,请参阅Apache HBase外部API(将在下一节的内容中介绍)。

示例

使用Java创建、修改和删除表:



Apache HBase外部API

本章将介绍如何通过非Java语言和自定义协议访问Apache HBase。

有关使用本机HBase API的信息,请参阅User API ReferenceHBase API章节。



HBase:REST服务器

REST代表状态转移,它于2000年在Roy Fielding的博士论文中引入,他是HTTP规范的主要作者之一。

REST本身超出了本文档的范围,但通常,REST允许通过与URL本身绑定的API进行客户端-服务器交互。本节讨论如何配置和运行HBase附带的REST服务器,该服务器将HBase表,行,单元和元数据作为URL指定的资源公开。

启动和停止REST服务器

包含的REST服务器可以作为守护程序运行,该守护程序启动嵌入式Jetty servlet容器并将servlet部署到其中。使用以下命令之一在前台或后台启动REST服务器。端口是可选的,默认为8080。

要停止REST服务器,请在前台运行时使用Ctrl-C,如果在后台运行则使用以下命令。

配置REST服务器和客户端

有关为SSL配置REST服务器和客户端以及为REST服务器配置doAs模拟的信息,请参阅配置Thrift网关以代表客户端进行身份验证以及Securing Apache HBase章节的其他部分。

使用REST端点

以下示例使用占位符服务器http://example.com:8000,并且可以使用curl或wget命令运行以下命令。您可以通过不为纯文本添加头信息来请求纯文本(默认),XML或JSON输出,或者为XML添加头信息“Accept:text / xml”,为JSON添加“Accept:application / json”或为协议缓冲区添加“Accept: application/x-protobuf”。

除非指定,否则使用GET请求进行查询,PUT或POST请求进行创建或修改,DELETE用于删除。

群集范围的端点

命名空间端点

表端点

Get操作的端点

Scan操作的端点

Put操作的端点

REST XML架构

REST Protobufs架构



将Java数据对象(JDO)与HBase一起使用

Java数据对象(JDO)是一种访问数据库中持久数据的标准方法,使用普通的旧Java对象(POJO)来表示持久数据。

依赖

此代码示例具有以下依赖项:

  1. HBase 0.90.x或更高版本1. commons-beanutils.jar(https://commons.apache.org/)1. commons-pool-1.5.5.jar(https://commons.apache.org/)1. transactional-tableindexed for HBase 0.90(https://github.com/hbase-trx/hbase-transactional-tableindexed)
    commons-beanutils.jar(https://commons.apache.org/)

transactional-tableindexed for HBase 0.90(https://github.com/hbase-trx/hbase-transactional-tableindexed)

下载 hbase-jdo

从http://code.google.com/p/hbase-jdo/下载代码。

JDO示例

此示例使用JDO创建一个表和一个索引,在表中插入行,获取行,获取列值,执行查询以及执行一些其他HBase操作



HBase与Scala一起使用

设置类路径

要将Scala与HBase一起使用,您的CLASSPATH必须包含HBase的类路径以及代码所需的Scala JAR。首先,在运行HBase RegionServer进程的服务器上使用以下命令,以获取HBase的类路径。

设置$CLASSPATH环境变量以包括您在上一步中找到的路径,以及项目所需的scala-library.jar路径和每个与Scala相关的其他JAR。

Scala SBT文件

您的build.sbt文件需要以下解析程序和libraryDependencies才能与HBase一起使用。

Scala代码示例

此示例列出HBase表,创建新表并向其添加行:



HBase与Jython一起使用

设置类路径

要将Jython与HBase一起使用,您的CLASSPATH必须包含HBase的类路径以及代码所需的Jython JAR。

将路径设置为包含Jython .jar的目录,以及每个项目需要的附加的Jython相关JAR。然后导出指向$ JYTHON_HOME环境变量的HBASE_CLASSPATH。

在类路径中使用HBase和Hadoop JAR启动Jython shell:$ bin / hbase org.python.util.jython

Jython代码示例

使用Jython创建表,填充,获取和删除表

以下Jython代码示例检查表,如果存在,则删除它然后创建它。然后,它使用数据填充表并获取数据。

使用Jython进行表扫描

此示例扫描表并返回与给定族限定符匹配的结果。



HBase:Thrift API和过滤器语言

Apache Thrift是一个跨平台的跨语言开发框架。HBase包含Thrift API和过滤器语言。Thrift API依赖于客户端和服务器进程。

您可以在服务器端和客户端为安全身份验证配置Thrift,方法可以参照“用于安全操作的客户端配置:Thrift Gateway”以及“配置Thrift网关以代表客户端进行身份验证”两节的内容进行操作。

本章的其余部分讨论了Thrift API提供的过滤器语言。

过滤语言

在HBase 0.92中引入了Thrift Filter Language。它允许您在通过Thrift或HBase shell访问HBase时执行服务器端筛选。您可以使用shell中的scan help命令找到有关shell集成的更多信息。

您将过滤器指定为字符串,在服务器上解析该过滤器以构造过滤器。



HBase:常规过滤字符串语法

一个简单的过滤表达式表示为一个字符串,如下所示:

请记住以下语法准则:

  • 指定过滤器的名称,后跟括号中以逗号分隔的参数列表。- 如果参数表示字符串,则应将其括在单引号(’)中。- 表示布尔值,整数或比较运算符(例如:<,>或!=)的参数不应包含在引号中- 过滤器名称必须是单个单词。除空格,单引号和括号外,允许使用所有ASCII字符。- 过滤器的参数可以包含任何ASCII字符。如果参数中存在单引号,则必须通过附加的前一个单引号对其进行转义。
    如果参数表示字符串,则应将其括在单引号(’)中。

过滤器名称必须是单个单词。除空格,单引号和括号外,允许使用所有ASCII字符。



HBase:复合过滤器和运算符

二元运算符

  • AND:如果使用AND运算符,则键值必须满足两个过滤器。- OR:如果使用OR运算符,则键值必须满足至少一个过滤器。
    OR:如果使用OR运算符,则键值必须满足至少一个过滤器。

一元运算符

  • SKIP:对于特定行,如果任何键值未通过过滤条件,则跳过整行。- WHILE:对于特定行,将发出键值,直到达到未通过过滤条件的键值。
    WHILE:对于特定行,将发出键值,直到达到未通过过滤条件的键值。

示例-复合运算符

您可以组合多个运算符来创建过滤器层次结构,例如以下示例:



HBase:过滤器计算顺序

  1. 括号具有最高优先级。1. 然后是一元运算符SKIP和WHILE,并具有相同的优先级。1. 接着是二元运算符,其中AND优先级最高,其次是OR。
    然后是一元运算符SKIP和WHILE,并具有相同的优先级。

优先级示例:

您可以使用括号明确的控制计算顺序。



HBase:过滤器比较运算符

在HBase中提供了以下的比较运算符:

  1. LESS(<)1. LESS_OR_EQUAL(⇐)1. EQUAL(=)1. NOT_EQUAL(!=)1. GREATER_OR_EQUAL(> =)1. GREATER(>)1. NO_OP(无操作)
    LESS_OR_EQUAL(⇐)

NOT_EQUAL(!=)

GREATER(>)

客户端应使用符号(<,⇐,=,!=,>,> =)来表示比较运算符。



HBase比较器

HBase比较器可以是以下任何一种:

  1. BinaryComparator - 使用Bytes.compareTo(byte[], byte[])比较指定的字节数组1. BinaryPrefixComparator - 按字典顺序与指定的字节数组进行比较。它只比较该字节数组的长度。1. RegexStringComparator - 使用给定的正则表达式与指定的字节数组进行比较。只有EQUAL和NOT_EQUAL比较对此比较器有效1. SubStringComparator - 测试给定的子字符串是否出现在指定的字节数组中。比较不区分大小写。只有EQUAL和NOT_EQUAL比较对此比较器有效
    BinaryPrefixComparator - 按字典顺序与指定的字节数组进行比较。它只比较该字节数组的长度。

SubStringComparator - 测试给定的子字符串是否出现在指定的字节数组中。比较不区分大小写。只有EQUAL和NOT_EQUAL比较对此比较器有效

比较器的一般语法是: ComparatorType:ComparatorValue

各种比较器的ComparatorType如下:

  1. BinaryComparator -二进制1. BinaryPrefixComparator - binaryprefix1. RegexStringComparator - regexstring1. SubStringComparator - substring
    BinaryPrefixComparator - binaryprefix

SubStringComparator - substring

ComparatorValue可以是任何值。

示例-ComparatorValues

  1. binary:abc将匹配所以字典顺序大于“abc”的所有内容1. binaryprefix:abc将匹配前3个字符在词典上等于“abc”的所有内容1. regexstring:ab*yz将匹配所有不以“ab”开头并以“yz”结尾的内容1. substring:abc123将匹配以子串“abc123”开头的所有内容
    binaryprefix:abc将匹配前3个字符在词典上等于“abc”的所有内容

substring:abc123将匹配以子串“abc123”开头的所有内容



HBase过滤器语言示例

使用过滤器语言的PHP客户端程序示例

过滤器字符串示例

  • “PrefixFilter (‘Row’) AND PageFilter (1) AND FirstKeyOnlyFilter ()” 将返回符合以下条件的所有键值对:1. 包含键值的行应该有前缀Row;1. 键值必须位于表的第一行;1. 键值对必须是行中的第一个键值
    键值必须位于表的第一行;
  • "(RowFilter (=, ‘binary:Row 1’) AND TimeStampsFilter (74689, 89734)) OR ColumnRangeFilter (‘abc’, true, ‘xyz’, false))"将返回符合以下两个条件的所有键值对:1. 键值对必须位于按字典顺序> = abc和<xyz排列的列中 1. 键值位于具有行键Row 1的行中;1. 键值必须具有74689或89734的时间戳;
    键值位于具有行键Row 1的行中;

或者它必须符合以下条件:

  • “SKIP ValueFilter (0)”,如果行中的任何值不为0,则将跳过整行


HBase单个过滤器语法

KeyOnlyFilter

此过滤器不带任何参数。它仅返回每个键值的关键组件。

FirstKeyOnlyFilter

此过滤器不带任何参数。它仅返回每行的第一个键值。

PrefixFilter

此过滤器采用一个参数 - 行键的前缀。它仅返回以指定行前缀开头的行中存在的键值

ColumnPrefixFilter

此过滤器采用一个参数 - 列前缀。它仅返回以指定列前缀开头的列中存在的键值。列前缀的格式必须为:“qualifier”。

MultipleColumnPrefixFilter

此过滤器采用列前缀列表。它返回以任何指定列前缀开头的列中存在的键值。每个列前缀必须采用以下形式:“qualifier”。

ColumnCountGetFilter

此过滤器采用一个参数 - 一个限制。它返回表中的第一个限制列数。

的PageFilter

此过滤器采用一个参数 - 页面大小。它返回表中的页面大小行数。

ColumnPaginationFilter

此过滤器有两个参数 - 限制和偏移。它返回偏移列数后的列数限制。它为所有行执行此操作。

InclusiveStopFilter

此过滤器使用一个参数 - 要停止扫描的行键。它返回行中存在的所有键值,包括指定的行。

TimeStampsFilter

此过滤器采用时间戳列表。它返回时间戳与任何指定时间戳匹配的键值。

的RowFilter

该过滤器采用比较运算符和比较器。它使用compare运算符将每个行键与比较器进行比较,如果比较返回true,则返回该行中的所有键值。

家庭过滤器

该过滤器采用比较运算符和比较器。它使用比较运算符将每个列族名称与比较器进行比较,如果比较返回true,则返回该列族中的所有单元格。

QualifierFilter

该过滤器采用比较运算符和比较器。它使用compare运算符将每个限定符名称与比较器进行比较,如果比较返回true,则返回该列中的所有键值。

ValueFilter

该过滤器采用比较运算符和比较器。它使用比较运算符将每个值与比较器进行比较,如果比较返回true,则返回该键值。

DependentColumnFilter

此过滤器有两个参数 - 族和限定符。它尝试在每一行中找到此列,并返回该行中具有相同时间戳的所有键值。如果该行不包含指定的列 - 将返回该行中的任何键值。

SingleColumnValueFilter

该过滤器采用列族,限定符,比较运算符和比较器。如果未找到指定的列 - 将发出该行的所有列。如果找到该列并且与比较器的比较返回true,则将发出该行的所有列。如果条件失败,则不会发出该行。

SingleColumnValueExcludeFilter

此过滤器采用相同的参数,其行为与SingleColumnValueFilter相同 - 但是,如果找到该列并且条件通过,则除了测试的列值之外,将发出该行的所有列。

ColumnRangeFilter

此过滤器仅用于选择列在minColumn和maxColumn之间的键。它还需要两个布尔变量来指示是否包含minColumn和maxColumn。



HBase和Spark

Apache Spark是一个软件框架,用于以分布式方式处理内存中的数据,并在许多用例中替换MapReduce。

Spark本身超出了本文档的范围,有关Spark项目和子项目的更多信息,请参阅Spark站点。本文档将重点介绍Spark和HBase之间的4个主要交互点。这些相互作用点是:

Basic Spark

能够在Spark DAG中的任何位置建立HBase连接。

Spark Streaming

能够在Spark Streaming应用程序中的任何位置拥有HBase连接。

Spark Streaming

能够直接写入HBase HFiles,以便批量插入HBase

SparkSQL / DataFrames

能够编写SparkSQL,它使用HBase中表示的表。

本章的剩余部分将介绍所有这些交互点的示例。



HBase:基本Spark

本节讨论最低和最简单级别的Spark HBase集成。所有其他交互点都建立在此处描述的概念之上。

所有Spark和HBase集成的根源都是HBaseContext。HBaseContext接受HBase配置并将它们推送到Spark执行程序。这允许我们在静态位置为每个Spark Executor建立一个HBase连接。

作为参考,Spark Executors可以与Region Servers位于相同的节点上,也可以位于不同的节点上,不依赖于co-location。将每个Spark Executor都视为多线程客户端应用程序。这允许在执行程序上运行的任何Spark任务访问共享的Connection对象。

HBaseContext用法示例

本示例演示如何使用HBaseContext在Scala的RDD上执行foreachPartition:

这是在Java中实现相同示例:

Scala和Java都支持Spark和HBase之间的所有功能,但SparkSQL除外,它支持Spark支持的任何语言。对于本文档的其余部分,我们现在将重点介绍Scala示例。

上面的示例说明了如何使用连接执行foreachPartition。一些其他的Spark基础功能是支持开箱即用:

bulkPut

用于向HBase大规模并行发送put

bulkDelete

用于向HBase大规模并行发送delete

bulkGet

用于向HBase大规模并行发送get,以创建新的RDD

mapPartition

使用Connection对象执行Spark Map功能以允许完全访问HBase

hBaseRDD

简化分布式扫描以创建RDD

有关所有这些功能的示例,请参阅HBase-Spark模块。



Spark Streaming

Spark Streaming是一个基于Spark构建的微批处理流处理框架。HBase和Spark Streaming是一个很好的搭档,因为HBase可以与Spark Streaming一起提供以下好处:

  • 即时获取参考数据或配置文件数据的地方- 以支持仅一次处理的Spark Streaming承诺的方式存储计数或聚合的位置。
    以支持仅一次处理的Spark Streaming承诺的方式存储计数或聚合的位置。

HBase-Spark模块与Spark Streaming的集成点类似于其常规的Spark集成点,因为以下命令可以直接通过Spark Streaming DStream实现。

bulkPut

用于向HBase大规模并行发送put

bulkDelete

用于向HBase大规模并行发送delete

bulkGet

用于大规模并行发送get到HBase以创建一个新的RDD

mapPartition

使用Connection对象执行Spark Map函数,以允许完全访问HBase

hBaseRDD

简化分布式扫描以创建RDD

带有DStream的bulkPut示例

下面是使用DStreams的bulkPut示例。RDD批量放置的感觉非常接近。


使用Spark将数据批量加载到HBase

使用Spark将数据批量加载到HBase有两种选择。有一些基本的批量加载功能适用于行具有数百万列的情况和未整合列的情况,以及Spark批量加载过程的映射侧之前的分区。

Spark还有一个精简记录批量加载选项,第二个选项是为每行少于10k列的表设计的。第二个选项的优点是Spark shuffle操作的吞吐量更高,而且负载更少。

这两种实现的工作方式或多或少类似于MapReduce批量加载过程,因为分区器根据区域拆分对rowkeys进行分区,并且行键按顺序发送到reducer,以便HFiles可以直接从reduce阶段写出。

在Spark术语中,批量加载将围绕Spark repartitionAndSortWithinPartitions实现,然后是Spark foreachPartition。

首先让我们看一下使用基本批量加载功能的示例

批量加载实例

以下示例显示了Spark的批量加载:

该hbaseBulkLoad函数需要三个必需参数:

  1. 我们打算批量加载的表的表名1. 将RDD中的记录转换为元组键值par的函数。该元组键是KeyFamilyQualifer对象,值是单元格值。KeyFamilyQualifer对象将保存RowKey,列族和列限定符。shuffle将在RowKey上进行分区,但将按所有三个值排序。1. HFile的临时路径也将被写出来
    将RDD中的记录转换为元组键值par的函数。该元组键是KeyFamilyQualifer对象,值是单元格值。KeyFamilyQualifer对象将保存RowKey,列族和列限定符。shuffle将在RowKey上进行分区,但将按所有三个值排序。

在Spark bulk load命令之后,使用HBase的LoadIncrementalHFiles对象将新创建的HFile加载到HBase中。

使用Spark进行批量加载的附加参数

您可以在hbaseBulkLoad上使用其他参数选项设置以下属性。

  • HFiles的最大文件大小- 从压缩中排除HFile的标志- compression,bloomType,blockSize和dataBlockEncoding的列族设置
    从压缩中排除HFile的标志

使用附加参数:

现在让我们看看如何调用精简记录大批量加载实现

使用精简记录批量加载示例:


SparkSQL / DataFrames

HBase-Spark连接器(在HBase-Spark模块中)利用Spark-1.2.0中引入的DataSource API (SPARK-3247),弥补了简单HBase KV存储和复杂关系SQL查询之间的差距,使用户能够使用Spark在HBase上执行复杂的数据分析工作。HBase Dataframe是标准的Spark Dataframe,能够与任何其他数据源(如Hive,Orc,Parquet,JSON等)进行交互。HBase-Spark Connector应用关键技术,如分区修剪,列修剪,谓词叠加和数据局部性。

要使用HBase-Spark连接器,用户需要为HBase和Spark表之间的模式映射定义Catalog,准备数据并填充HBase表,然后加载HBase DataFrame。之后,用户可以使用SQL查询在HBase表中进行集成查询和访问记录。以下说明了基本程序。

定义目录

Catalog定义了HBase和Spark表之间的映射。该目录有两个关键部分。一个是rowkey定义,另一个是Spark中的表列与HBase中的列族和列限定符之间的映射。上面定义了一个HBase表的模式,其名称为table1,行键为key,列数为col1 -col8。请注意,还必须将rowkey详细定义为column (col0),该列具有特定的cf(rowkey)。

保存DataFrame

用户准备的data是一个本地Scala集合,它有256个HBaseRecord对象。 sc.parallelize(data)函数分配data以形成RDD。toDF返回一个DataFrame。 writefunction返回一个DataFrameWriter,它用于将DataFrame写入外部存储系统(例如,HBase)。给定具有指定模式的DataFrame catalog,save函数将创建一个包含5个区域的HBase表,并将DataFrame保存在其中。

加载DataFrame

在’withCatalog’函数中,sqlContext是SQLContext的变量,它是在Spark中处理结构化数据(行和列)的入口点。 read返回一个DataFrameReader,可用于以DataFrame的形式读取数据。 option函数将基础数据源的输入选项添加到DataFrameReader,format函数指定DataFrameReader的输入数据源格式。该load()函数将输入作为DataFrame加载。withCatalog函数返回的日期框df可用于访问HBase表。

语言综合查询

DataFrame可以执行各种操作,例如join,sort,select,filter,orderBy等。上面的df.filter使用给定的SQL表达式过滤行。select选择一组列: col0,col1和col4。

SQL查询

registerTempTabledf使用表名将DataFrame注册为临时表table1。此临时表的生命周期与用于创建df的SQLContext相关联。sqlContext.sql函数允许用户执行SQL查询。

其他

示例-使用不同时间戳的查询

在HBaseSparkConf中,可以设置与时间戳相关的四个参数。它们分别是TIMESTAMP,MIN_TIMESTAMP,MAX_TIMESTAMP和MAX_VERSIONS。用户可以使用MIN_TIMESTAMP和MAX_TIMESTAMP查询具有不同时间戳或时间范围的记录。与此同时,在下面的示例中使用具体值而不是tsSpecified和oldMs。

下面的示例显示了如何使用不同的时间戳加载df DataFrame。tsSpecified由用户指定。HBaseTableCatalog定义HBase和Relation关系模式。writeCatalog定义模式映射的目录。

下面的示例显示了如何加载具有不同时间范围的df DataFrame。oldMs由用户指定。

加载df DataFrame后,用户可以查询数据。

示例-本地Avro支持

HBase-Spark Connector支持不同的数据格式,如Avro,Jason等。下面的用例显示了spark是如何支持Avro的。用户可以直接将Avro记录保存到HBase中。在内部,Avro模式自动转换为本机Spark Catalyst数据类型。请注意,HBase表中的两个键值部分都可以用Avro格式定义。

1)定义模式映射的目录:

catalog是名为Avrotable的HBase表的模式。行键作为键和一列col1。还必须将rowkey详细定义为column (col0),该列具有特定的cf(rowkey)。

2)准备数据:

首先定义schemaString,然后解析得到avroSchema。avroSchema用于生成AvroHBaseRecord。用户准备的data是一个包含256个AvroHBaseRecord对象的本地Scala集合。

3)保存DataFrame:

给定具有指定模式的数据框catalog,上面将创建一个包含5个区域的HBase表,并将数据框保存在其中。

4)加载DataFrame

在withCatalog函数中,read返回一个DataFrameReader,可用于以DataFrame的形式读取数据。该option函数将基础数据源的输入选项添加到DataFrameReader。有两个选项:一个是设置avroSchema为AvroHBaseRecord.schemaString,一个是设置HBaseTableCatalog.tableCatalog为avroCatalog。该load()函数将输入作为DataFrame加载。withCatalog函数返回的日期框df可用于访问HBase表。

5)SQL查询:


Apache HBase协处理器

HBase协处理器仿照Google BigTable的协处理器实现(http://research.google.com/people/jeff/SOCC2010-keynote-slides.pdf第41-42页)。

协处理器框架提供了直接在管理数据的RegionServers上运行自定义代码的机制。目前正在努力弥合HBase的实施与BigTable架构之间的差距。

本章中的信息主要来源于以下资源并大量重用:

  1. 赖明杰的博客文章:处理器简介。1. Gaurav Bhardwaj的博客文章:如何使用HBase协处理器
    Gaurav Bhardwaj的博客文章:如何使用HBase协处理器

使用你自己的协处理器

协处理器是HBase的高级功能,仅供系统开发人员使用。由于协处理器代码直接在RegionServer上运行,并且可以直接访问您的数据,因此它们引入了数据损坏、中间攻击或其他恶意数据访问的风险。目前,协处理器没有防止数据损坏的机制,尽管 HBASE-4047 正在进行工作。

此外,没有资源隔离,因此一个善意但行为不端的协处理器会严重降低群集性能和稳定性。



Apache HBase协处理器概述

在HBase中,使用“Get”或者“Scan”获取数据,而在RDBMS中使用SQL查询。为了仅获取相关数据,您可以使用HBase Filter过滤它 ,而在RDBMS中使用WHERE谓词。

获取数据后,您可以对其执行计算。这种范例适用于具有几千行和几列的“小数据”。但是,当您扩展到数十亿行和数百万列时,在网络中移动大量数据将在网络层产生瓶颈,客户端需要足够强大并且有足够的内存来处理大量数据和计算。此外,客户端代码可能变得庞大而复杂。

在这种情况下,协处理器可能有意义。您可以将业务计算代码放入在RegionServer上运行的协处理器中,与数据位于同一位置,并将结果返回给客户端。

这只是使用协处理器可以带来好处的一种情况。以下是一些类比,可能有助于解释协处理器的一些好处。

协处理器类比

触发器和存储过程

Observer协处理器类似于RDBMS中的触发器,因为它在特定事件(例如,Get或Put)发生之前或之后执行代码。端点协处理器类似于RDBMS中的存储过程,因为它允许您对RegionServer本身上的数据而不是客户端上的数据执行自定义计算。

MapReduce

MapReduce的工作原理是将计算移动到数据位置。协处理器在相同的主体上运行。

AOP

如果您熟悉面向方面编程(AOP),则可以将协处理器视为通过拦截请求然后运行某些自定义代码来应用建议,然后将请求传递到其最终目标(甚至更改目标)。

协处理器实现概述

  1. 您的类应该实现一个协处理器接口 - 协处理器, RegionObserver, CoprocessorService - 仅举几例。1. 使用HBase Shell静态或动态地加载协处理器。1. 从客户端代码调用协处理器。HBase透明地处理协处理器。
    使用HBase Shell静态或动态地加载协处理器。

框架API在协处理器包中提供。



Apache HBase协处理器的类型

观察者协处理器

在特定事件发生之前或之后触发观察者协处理器。在事件之前发生的观察者使用以pre前缀开头的方法,例如,prePut。观察者发生在以post前缀(如postPut)开头的事件覆盖方法之后。

用于观察者协处理器的用例

安全

在执行Get或Put操作之前,您可以使用preGet或prePut方法检查权限。

参照完整性

HBase不直接支持refential完整性的RDBMS概念,也称为外键。您可以使用协处理器来强制执行此类完整性。例如,如果您有一个业务规则,users表中的每个插入必须后跟user_daily_attendance表中的相应条目,您可以实现协处理器以在user使用该prePut方法向user_daily_attendance插入记录。

二级索引

您可以使用协处理器来维护二级索引。

观察者协处理器的类型

RegionObserver

RegionObserver协处理器允许您观察区域上的事件,例如Get 和Put操作。

RegionServerObserver

RegionServerObserver允许您观察与RegionServer操作相关的事件,例如启动,停止或执行合并,提交或回滚。

MasterObserver

MasterObserver允许您观察与HBase Master相关的事件,例如表创建,删除或架构修改。

WalObserver

WalObserver允许您观察与写入预写日志(WAL)相关的事件。

示例提供了观察者协处理器的工作示例。

端点协处理器

端点处理器允许您在数据位置执行计算。例如,需要计算横跨数以百计区域的整个表的运行平均值或求和。

与您的代码透明运行的观察器协处理器相比,端点协处理器必须使用Table或HTable中提供的CoprocessorService()方法显式调用。

从HBase 0.96开始,端点协处理器使用Google Protocol Buffers(protobuf)实现。以0.94版本编写的端点协处理器与0.96或更高的版本不兼容。见HBASE-5448)。要将HBase群集从0.94或更早版本升级到0.96或更高版本,您需要重新实现协处理器。

协处理器端点不应使用HBase内部构件,只能利用公共API;理想情况下,CPEP应仅依赖于接口和数据结构。这并不总是可行的,但要注意这样做会使端点变脆弱,随着HBase内部的发展而易于破损。注释为私有或演进的HBase内部API在删除之前不必遵守语义版本规则或关于弃用的一般Java规则。虽然生成的protobuf文件没有hbase受众注释 - 它们是由protobuf protoc工具创建的,它不知道HBase是如何工作的 - 它们应该被认为是@InterfaceAudience.Private,因此容易改变。

在接下来的“示例”一节,提供了端点协处理器的工作示例。



Apache HBase加载协处理器

要使您的协处理器可用于HBase,必须静态(通过HBase配置)或动态(使用HBase Shell或Java API)加载它。

静态加载

请按照以下步骤静态加载协处理器。请记住,必须重新启动HBase才能卸载已静态加载的协处理器。

1、在hbase-site.xml中定义协处理器,其中<property>元素带有<name>和<value>子元素。<name>应该是以下之一:

  • 对于RegionObservers和Endpoints是hbase.coprocessor.region.classes。- 对于WALObservers是hbase.coprocessor.wal.classes。- 对于MasterObservers是hbase.coprocessor.master.classes。
    <value>必须包含协处理器实现类的完全限定类名。
    例如,要加载协处理器(在类SumEndPoint.java中实现),您必须在RegionServer的’hbase-site.xml’文件中创建以下条目(通常位于’conf’目录下):
    对于WALObservers是hbase.coprocessor.wal.classes。

如果为加载指定了多个类,则类名必须以逗号分隔。框架尝试使用默认的类加载器加载所有已配置的类。因此,jar文件必须驻留在服务器端HBase类路径中。
以这种方式加载的协处理器将在所有表的所有区域上处于活动状态。这些也称为系统协处理器。将为第一个列出的协处理器分配优先级Coprocessor.Priority.SYSTEM。列表中的每个后续协处理器的优先级值都会增加1(这会降低其优先级,因为优先级具有整数的自然排序顺序)。
当调用注册的观察者时,框架以其优先级的排序顺序执行其回调方法。关系是任意破坏的。

2、将您的代码放在HBase的类路径上。一种简单的方法是将jar(包含代码和所有依赖项)放入HBase的安装目录lib/中。

3、重启HBase。

静态卸载

1、从hbase-site.xml中删除协处理器的<property>元素,包括子元素。

2、重启HBase。

3、(可选)从类路径或HBase的lib/目录中删除协处理器的JAR文件。

动态加载

您也可以动态加载协处理器,而无需重新启动HBase。这似乎比静态加载更好,但动态加载的协处理器是基于每个表加载的,并且只能用于加载它们的表。因此,动态加载的表有时称为表协处理器(Table Coprocessor)。

此外,动态加载协处理器充当表上的模式更改,并且必须使表脱机以加载协处理器。

有三种方法可以动态加载协处理器。

以下说明做了如下假设:

  • 一个叫做coprocessor.jar的JAR包含了协处理器实现以及它的所有依赖项。 
    - 该JAR在HDFS中的某些位置 (如,hdfs://<namenode>:<port>/user/<hadoop-user>/coprocessor.jar ) 中可用。
    该JAR在HDFS中的某些位置 (如,hdfs://<namenode>:<port>/user/<hadoop-user>/coprocessor.jar ) 中可用。

使用HBase Shell

1、使用HBase Shell禁用表:

2、使用如下命令加载协处理器:

协处理器框架将尝试从协处理器表属性值中读取类信息。该值包含由pipe(|)字符分隔的四条信息。

  • 文件路径:包含协处理器实现的jar文件必须位于所有区域服务器都可以读取它的位置。
    您可以将文件复制到每个区域服务器上的本地磁盘上,但建议将其存储在HDFS中。
    HBASE-14548允许指定包含jar或一些通配符的目录,例如:hdfs://<namenode>:<port>/user/<hadoop-user>/,或hdfs://<namenode>:<port>/user/<hadoop-user>/*.jar。请注意,如果指定了目录,则会添加目录中的所有jar文件(.jar)。它不搜索子目录中的文件。如果要指定目录,请不要使用通配符。此增强功能也适用于通过JAVA API的用法。- 类名:协处理器的完整类名。- 优先级:整数。该框架将使用优先级确定在同一个钩子上注册的所有已配置观察者的执行顺序。该字段可以保留为空。在这种情况下,框架将分配默认优先级值。参数(可选):此字段传递给协处理器实现。这是可选的。
    类名:协处理器的完整类名。

3、启用该表。

4、验证协处理器已加载:

协处理器应列在TABLE_ATTRIBUTES。

使用Java API(所有HBase版本)

下面的Java代码演示如何使用HTableDescriptor的setValue()方法在"用户"表上加载协处理器。

使用Java API(仅限HBase 0.96+)

在HBase 0.96及更新版本中,该HTableDescriptor的addCoprocessor()方法提供了一种动态加载协处理器的简便方法。

无法保证框架将成功加载给定的协处理器。例如,shell命令既不保证特定位置存在jar文件,也不验证给定类是否实际包含在jar文件中。

动态卸载

使用HBase Shell

1、禁用该表。

2、更改表以删除协处理器。

3、启用该表。

使用Java API

重新加载表定义,而无需使用setValue()或addCoprocessor()方法设置协处理器的值。这将删除附加到表的任何协处理器。

在HBase 0.96及更新版本中,您可以改为使用该HTableDescriptor类的removeCoprocessor()方法。



HBase观察者协处理器示例

示例

HBase提供了Observer Coprocessor(观察者协处理器)的示例。

下面给出更详细的例子。

这些示例假设一个名为users的表,其中有两个列族personalDet和salaryDet,包含个人和工资详细信息。下面是users表格:

personalDetsalaryDet
|------

jverne

Jules 

Verne 

02/08/1828 

12000

9000

3000

rowkey

name 

lastname 

dob 

gross 

net 

allowances 

admin 

Admin 

Admin 

cdickens

Charles 

Dickens 

02/07/1812 

10000

8000

2000

观察者示例

以下Observer协处理器可防止用户admin的详细信息在users表Get或者Scan中返回。 

  1. 编写一个实现RegionObserver类的类。1. 重写preGetOp()方法(不推荐使用该preGet()方法)以检查客户端是否已使用admin值查询rowkey。如果是,则返回空结果。否则,正常处理请求。1. 将您的代码和依赖项放在JAR文件中。1. 将JAR放在HDFS中,HBase可以在其中找到它。1. 加载协处理器。1. 写一个简单的程序来测试它。
    重写preGetOp()方法(不推荐使用该preGet()方法)以检查客户端是否已使用admin值查询rowkey。如果是,则返回空结果。否则,正常处理请求。

将JAR放在HDFS中,HBase可以在其中找到它。

写一个简单的程序来测试它。

以下是上述步骤的实现:

重写preGetOp()仅适用于Get操作。您还需要重写该preScannerOpen()方法以从扫描结果中过滤admin行。

这种方法有效,但有副作用。

如果客户端在其扫描中使用了过滤器,则该过滤器将替换该过滤器。相反,您可以显式删除扫描中的任何admin结果:

端点示例

仍然使用该users表,该示例使用端点协处理器实现协处理器以计算所有员工工资的总和。

1、创建一个定义服务的’.proto’文件。

2、执行protoc命令以从上面的.proto文件生成Java代码。

这将生成一个类调用Sum.java。

3、编写一个扩展生成的服务类的类,实现Coprocessor和CoprocessorService类,并重写服务方法。
注意:如果您从hbase-site.xml加载协处理器然后使用HBase Shell 再次加载同一个协处理器,它将再次加载。同一个类将存在两次,第二个实例将具有更高的ID(因此具有更低的优先级)。结果是有效地忽略了重复的协处理器。

4、加载协处理器。

5、编写客户端代码以调用协处理器。



HBase部署协处理器的准则

捆绑协处理器

您可以将协处理器的所有类捆绑到RegionServer类路径上的单个JAR中,以便于部署。否则,将所有依赖项放在RegionServer的类路径中,以便在RegionServer启动期间加载它们。RegionServer的类路径在RegionServer的hbase-env.sh文件中设置。

自动部署

您可以使用Puppet,Chef或Ansible等工具将协处理器的JAR发送到RegionServers文件系统上的所需位置,然后重新启动每个RegionServer,以自动执行协处理器部署。此类设置的详细信息超出了本文档的介绍范围。

更新协处理器

部署新版本的给定协处理器并不像禁用它、替换JAR和重新启用协处理器那么简单。这是因为除非删除对它的所有当前引用,否则无法在JVM中重新加载类。由于当前JVM引用了现有的协处理器,因此必须通过重新启动RegionServer来重新启动JVM,以便替换它。此行为不应更改。

**协处理器

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值