第 5 章 HBase分布式数据库 HBase是一个高可靠性、高性能、基于列进行数据存储的分布式数据库,可以 随着存储数据的不断增加而实时、动态地增加列。本章主要介绍HBase系统架构 和数据访问流程、HBase数据表、HBase安装与配置、HBase的Shel 操作、HBase 的JavaAPI操作、HBase案例实战和利用Python语言操作HBase。 ..5.1 HBase概述 HBase概述 5.1.1 HBase的技术特点 HBase是一个建立在HDFS之上的分布式数据库。HBase的主要技术特点 如下 ( 。 1)容量大。HBase中的一个表可以存储数十亿行、上百亿列。当关系数据 库的单个表的记录在亿级时,查询和写入的性能都会呈现指数级下降;而HBase 对于单表存储百亿级或更多的数据都没有性能问题。 (2)无固定模式(表结构不固定)。HBase可以根据需要动态地增加列,同一 张表中不同的行可以有截然不同的列。 (3)列式存储。HBase中的数据在表中是按照列存储的,可动态地增加列,并 且可以单独对列进行各种操作。 (4)稀疏性。HBase的表中的空列不占用存储空间,表可以非常稀疏。 (5)数据类型单一。HBase中的数据都是字符串。 5.2 HBse与传统关系数据库的区别 1.a HBase与传统关系数据库的区别主要体现在以下几方面。 (1)数据类型方面。关系数据库具有丰富的数据类型,如字符串型、数值型、 日期型、二进制型等。HBase只有字符串数据类型,即HBase把数据存储为未经 解释的字符串,数据的实际类型都是交由用户自己编写程序对字符串进行解 析的 ( 。 2)数据操作方面。关系数据库包含了丰富的操作,如插入、删除、更新、查询 等,其中还涉及各式各样的函数和连接操作。HBase只有很简单的插入、查询、删 除、清空等操作,表和表之间是分离的,没有复杂的表和表之间的关系。 102Hadoop大数据技术原理与编程(微课版) (3)存储模式方面。关系数据库是基于行存储的。在关系数据库中读取数据时,需要 按顺序扫描每个元组,然后从中筛选出要查询的属性。HBase是基于列存储的。HBase将 列划分为若干列族(columnfamily),每个列族都由几个文件保存,不同列族的文件是分离 的。它的优点是:可以降低I/O开销,支持大量并发用户查询,仅需要处理要查询的列,不 需要处理与查询无关的大量数据列。 (4)数据维护方面。在关系数据库中,更新操作会用最新的当前值替换元组中原来的 旧值。而HBase执行的更新操作不会删除数据旧的版本,而是添加一个新的版本,旧的版 本仍然保留。 (5)可伸缩性方面。HBase分布式数据库就是为了实现灵活的水平扩展而开发的,所 以它能够轻松增加或减少硬件的数量以实现性能的伸缩。而传统数据库通常需要增加中间 层才能实现类似的功能,很难实现横向扩展,纵向扩展的空间也比较有限。 5.1.3HBase与Hadoop中其他组件的关系 HBase作为Hadoop生态系统的一部分,一方面它的运行依赖于Hadoop生态系统中 的其他组件;另一方面,HBase又为Hadoop生态系统的其他组件提供了强大的数据存储和 处理能力。HBase与Hadoop生态系统中其他组件的关系如图5-1(同图1-1)所示。 图5- 1 HBase与Hadop生态系统中其他组件的关系 HBase使用HDFS作为高可靠的底层存储,利用廉价集群提供海量数据存储能力。 HBase使用MapReduce处理海量数据,实现高性能计算。 HBase用ZoKeper提供协同服务,ZoKeper用于提供高可靠的锁服务。ZoKeper保 证了集群中所有的计算机看到的视图是一致的。例如,节点A通过ZooKeper抢到了某个 独占的资源,那么就不会有节点B也宣称自己获得了该资源(因为ZooKeper提供了锁机 制),并且这一事件会被其他所有的节点观测到。HBase使用ZooKeper服务进行节点管 理及表数据的定位。 此外,为了方便在HBase上进行数据处理,Sqoop为HBase提供了高效、便捷的 RDBMS数据导入功能,Pig和Hive为HBase提供了高层语言支持。 ..5.2 HBase系统架构和数据访问流程 HBase系统 架构和数据5.2.1 HBase系统架构 访问流程 HBase采用主从架构,由客户端、HMaster服务器、HRegionServer和ZooKeper服务 器构成。在底层,HBase将数据存储于HDFS中。HBase系统架构如图5-2所示。 第5章HBase分布式数据库103 图5-2HBase系统架构 1.客户端 客户端包含访问HBase的接口,同时在缓存中维护着已经访问过的HRegion位置信 息,用来加快后续数据访问过程。HBase客户端使用远程过程调用(RemoteProcedure Call,RPC)机制与HMaster服务器和HRegionServer进行通信。对于管理类操作,客户端 与HMaster服务器进行RPC;对于数据读写类操作,客户端则会与HRegionServer进 行RPC 。 2.ZoKeper服务器 ZooKep(o) er服务器用来为HBase集群提供稳定可靠的协同服务,ZooKeper服务器存 储了-ROOT-表的地址和HMaster的地址,客户端通过-ROOT-表可找到自己所需的数据。 ZooKeper服务器并非一台单一的计算机,可能是由多台计算机构成的集群。每个 HRegionServer会以短暂的方式把自己注册到ZooKeper服务器中,ZooKeper服务器会 实时监控每个HRegionServer的状态并通知给HMaster服务器,这样,HMaster服务器就 可以通过ZooKeper服务器随时感知各个HRegionServer的工作状态。 具体来说,ZooKeper服务器的作用如下。 (1)保证任何时候集群中只有一个HMaster服务器作为集群的“总管”。HMaster服 务器记录了当前有哪些可用的HRegionServer,以及当前哪些HRegion分配给了哪些 HRegionServer,哪些HRegion还没有被分配。当一个HRegion需要被分配时,HMaster 服务器从当前运行着的HRegionServer中选取一个,向其发送一个装载请求,把HRegion 分配给这个HRegionServer。HRegionServer得到请求后,就开始加载这个HRegion。加 载完成后,HRegionServer会通知HMaster服务器加载的结果。如果加载成功,那么这个 HRegion就可以对外提供服务了。 (2)实时监控HRegionServer的状态。ZooKeper服务器将HRegionServer上线和下 线信息实时通知给HMaster服务器。 (3)存储HBase目录表的寻址入口。 (4)存储HBase的模式。HBase的模式包括有哪些表、每个表有哪些列族等各种元 104 Hadop大数据技术原理与编程(微课版) 信息 ( 。 5)锁定和同步服务。锁定和同步服务机制可以帮助自动故障恢复,同时连接其他的 分布式应用程序。 3.HMaster服务器 每台HRegionServer都会和HMaster服务器通信,HMaster服务器的主要任务就是告 诉每个HRegionServer它主要维护哪些HRegion。 当一台新的HRegionServer登录到HMaster服务器时,HMaster服务器会告诉它先等 待分配数据。而当一台HRegionServer发生故障失效时,HMaster服务器会把它负责的 HRegion标记为未分配,然后把它们分配给其他HRegionServer。 HMaster服务器用于协调多个HRegionServer,侦测各个HRegionServer的状态,负责 分配HRegion给HRegionServer,平衡HRegionServer之间的负载。在ZooKeper服务器 的帮助下,HBase允许多个HMaster服务器共存,但只有一个HMaster服务器提供服务, 其他的HMaster服务器处于待命状态。当正在工作的HMaster服务器宕机时,ZooKeper 服务器指定一个待命的HMaster服务器接管它。 HMaster服务器主要负责表和HRegion的管理工作,具体包括:管理HRegionServer,实 现其负载均衡;管理和分配HRegion,例如,在HRegion拆分时分配新的HRegion,在 HRegionServer退出时迁移其上的HRegion到其他HRegionServer上;监控集群中所有 HRegionServer的状态(通过心跳消息监听);处理模式更新请求(创建、删除、修改表的定 义)。 4.HRegionServer HRegionServer维护HMaster服务器分配给它的HRegion,处理用户对这些HRegion 的I/O请求,向HDFS文件系统中读写数据,此外,HRegionServer还负责拆分在运行过程 中变得过大的HRegion。 HRegionServer内部管理一系列HRegion对象,每个HRegion对应表中的一个分区。 HBase的表根据RowKey的范围被水平拆分成若干HRegion。每个HRegion都包含了这 个HRegion的startkey和endkey之间的所有行。HRegions被分配给集群中的某些 HRegionServer管理,由它们负责处理数据的读写请求。每个HRegionServer大约可以管 理1000个HRegion。HRegion由多个HStore组成,每个HStore对应表中的一个列族的 存储。每个列族其实就是一个集中的存储单元,因此最好将具备共同I/O特性的列放在一 个列族中,这样最高效。 HStore是HBase存储的核心。HStore由两部分组成,一部分是MemStore,另一部分 是StoreFile。MemStore是排序的内存缓冲区(sortedmemorybufer),用户写入的数据首 tortorflustoreFil 先会放入MemSe,当MemSe满了以后会刷写(h)成一个Se(其底层实现是 HFile)。当StoreFile文件数量达到一定阈值时,会触发合并(compact)操作,将多个 StoreFile合并成一个StoreFile,合并过程中会进行版本合并和数据删除,因此,HBase其实 只增加数据,所有的更新和删除操作都是在后续的合并过程中进行的,这使得用户的写操作 只要进入内存中就可以立即返回,保证了HBaseI/O的高性能。 当StoreFile合并后,会逐步形成越来越大的StoreFile,当单个StoreFile大小达到一定 阈值后,会触发拆分(split)操作,同时把当前分区拆分成两个分区,父分区会下线,新拆分出 第5章HBase分布式数据库105 的两个子分区会被HMaster服务器分配到相应的HRegionServer上,使得原先一个分区的 压力得以分流到两个分区上。图5-3描述了StoreFile的合并和拆分过程。 图5-3StoreFile的合并和拆分过程 Hadoop数据节点负责存储所有HRegionServer管理的数据。HBase中的所有数据都 是以HDFS 文件的形式存储的。出于使HRegionServer管理的数据本地化的考虑, HRegionServer是根据数据节点分布的。HBase的数据在写入的时候都存储在本地。但当 某一个HRegion被移除或被重新分配的时候,就可能产生数据不在本地的情况。名称节点 负责维护构成文件的所有物理数据块的元信息。 5.2.2HBase数据访问流程 HRegion是按照“表名+开始主键+分区号(tablename+startkey+regionId)”区分的, 每个HReion对应表中的一个分区。可以用上述标识符区分不同的HReion,这些标识符 gg 数据就是元数据,而元数据本身也是用一个HBase表保存在HRegion里面的,称这个表为 META. 表(元数据表), 其中保存的就是HRegion标识符和实际HRegion服务器的映射关(.) 系。 .META. 表也会增长,并且可能被分割为几个HRegion。为了定位这些HRegion,采 用-ROOT-表(根数据表)保存所有.META. 表的位置,而-ROOT-表是不能被分割的,永远只 保存在一个HRegion里。在客户端访问具体的业务表的HRegion时,需要先通过 -ROOT-表找到.META. 表,再通过.META. 表找到HRegion的位置,即这两个表主要解决 了HRegion的快速路由问题。 1.-ROOT-表 -ROOT-表记录了.META. 表的HRegion信息 。 -ROOT-表的结构如表5-1所示 。 表5- 1 -ROOT-表的结构 RowKey info historian regioninfo server serverstartcode .META.,Table1,0,12345678,12657843 HRS1 .META.,Table2,30000,12348765,12348675 HRS2 下面分析-ROOT-表的结构,每行记录了一个.META. 表的HRegion信息。 1)RowKeyRowKey(行键)由3个部分组成:.META. 表表名、StartRowKey和创建时间戳。Row 106 Hadop大数据技术原理与编程(微课版) Key存储的内容又称为.META.表对应的HRegion的名称。将组成RowKey的3个部分 用逗号连接,就构成了整个RowKey。 2)info info中包含regioninfo、server和serverstartcode。其中regioninfo就是HRegion的详 细信息,包括StartRowKey、EndRowKey等信息。server存储的是管理这个HRegion的 HRegionServer的地址。所以,当HRegion被拆分、合并或者重新分配的时候,都需要修改 ROOT-表的内容。 2..META.表 .META.表的结构如表5-2所示。 表5- 2 .META.表的结构 RowKey info historian regioninfo server serverstartcode Table1,RK0,12345678 HRS1 Table1,RK10000,12345678 HRS2 Table1,RK20000,12345678 HRS3 . . Table2,RK0,12345678 HRS1 Table2,RK20000,12345678 HRS2 HBase的所有HRegion元数据被存储在.META.表中。随着HRegion的增多, .META.表的数据量也会增大,并拆分成多个新的HRegion。为了定位.META.表中各个 HRegion的位置,把.META.表中所有HRegion的元数据保存在-ROOT-表中,最后由 ZooKeper服务器记录-ROOT-表的位置信息。所有客户端访问用户数据前,需要首先访问 ZooKeper服务器获得-ROOT-表的位置,然后访问-ROOT-表获得.META.表的位置,最后 根据.META.表中的信息确定用户数据存放的位置。 下面用一个例子介绍访问具体数据的过程。先构建-ROOT-表和.META.表。 假设HBase中只有两张用户表:Table1和Table2。Table1非常大,被划分成很多 HRegion,因此在.META.表中有很多行,用来记录这些HRegion。而Table2很小,只被划分成 两个HRegion,因此在.META.表中只有两行记录。这个.META.表如表5-2所示。 假设要从Table2中查询一条RowKey是RK10000的数据,应该按以下步骤进行。 (1)从.META.表中查询哪个HRegion包含这条数据。 (2)获取管理这个HRegion的HRegionServer地址。 (3)连接这个HRegionServer,查到这条数据。 对于步骤(.META.表也是一张普通的表, egionServer管理该 1),需要先知道哪个HR.META.表。因为Table1实在太大了,它的HRegion实在太多了,.META.表为了存储这些 HRegion信息,自己也需要划分成多个分区,这就意味着可能有多个HRegionServer管理这个 .META.表。HBase的做法是用-ROOT-表记录.META.表的分区信息。假设.META.表被分成 了两个分区,这个-ROOT-表如表5-1所示。客户端就需要先访问-ROOT-表。 第5章 HBase分布式数据库1 07 查询Table2中Row Key是RK10000数据的整个路由过程的主要代码在org.apache. hadoop.hbase.client.HConnectionManager.TableServers中: private HRegionLocation locateRegion(final byte[] tableName, final byte[] row, boolean useCache) throws IOException { if (tableName == null || tableName.length == 0) { throw new IllegalArgumentException( "table name cannot be null or zero length"); } if (Bytes.equals(tableName, ROOT_TABLE_NAME)) { synchronized (rootRegionLock) { //防止两个线程同时查找root 区域 if (!useCache || rootRegionLocation == null) { this.rootRegionLocation = locateRootRegion(); } return this.rootRegionLocation; } } else if (Bytes.equals(tableName, META_TABLE_NAME)) { return locateRegionInMeta(ROOT_TABLE_NAME, tableName, row, useCache, metaRegionLock); } else { //缓存中无此分区,需要访问meta RS return locateRegionInMeta(META_TABLE_NAME, tableName, row, useCache, userRegionLock); } } 这是一个递归调用的过程。获取Table2的RowKey为RK10000的HRegionServer→ 获取.META.表的RowKey为“Table2,RK10000,…”的HRegionServer→获取-ROOT-表 的RowKey为“.META.,Table2,RK10000,…,…”的HRegionServer→获取-ROOT-表的 HRegionServer→从ZooKeeper服务器得到-ROOT-表的HRegionServer→从-ROOT-表中 查到RowKey最接近(小于)“.META.,Table2,RK10000,…,…”的一行,并得到.META. 表的HRegionServer→从.META.表中查到RowKey最接近(小于)“Table2,RK10000,…” 的一行,并得到Table2的HRegionServer→从Table2中查到RK10000的行。 HBase 数据表 .. 5.3 HBase数据表 HBase是基于HadoopHDFS的数据库。HBase数据表是一个稀疏的、分布式的、序列 化的、多维排序的分布式多维表,表中的数据通过行键、列族、列名(columnname)、时间戳 (timestamp)进行索引和查询定位。表中的数据都是未经解释的字符串,没有数据类型。 在HBase表中,每一行都有一个可排序的行键和任意多个列。表的水平方向由一个或多个 列族组成,一个列族中可以包含任意多个列,同一个列族的数据存储在一起。列族支持动态 扩展,可以添加列族,也可以在列族中添加列,无须预先定义列的数量,所有列均以字符串形 式存储。 5.3.1 HBase数据表逻辑视图 HBase以表的形式存储数据,表由行和列组成,列可组合为若干列族,表5-3是一个班 1 08 Hadoop大数据技术原理与编程(微课版) 级学生HBase数据表的逻辑视图。此表中包含两个列族:StudentBasicInfo(学生基本信 息)列族,由Name(姓名)、Address(地址)、Phone(电话)3列组成;StudentGradeInfo(学生 课程成绩信息)列族,由Chinese(语文)、Maths(数学)、English(英语)3列组成。Row Key 为ID2的学生存在两个版本的电话,ID3有两个版本的地址,时间戳较大的数据版本是最新 的数据。 表5-3 班级学生HBase数据表 RowKey StudentBasicInfo StudentGradeInfo Name Address Phone Chinese Maths English ID1 LiHua Building1 135×××××××× 85 90 86 ID2 WangLi Building1 t2:136×××××××× t1:158×××××××× 78 92 88 ID3 ZhangSan t2:Building2 t1:Building1 132×××××××× 76 80 82 1.行键 任何字符串都可以作为行键,HBase表中的数据按照行键的字典序排序存储。在设计 行键时,要充分利用排序存储这个特性,将经常一起读取的行存放到一起,从而充分利用空 间局部性。如果行键是网站域名,如www.apache.org、mail.apache.org、jira.apache.org,应 该将网站域名进行反转(org.apache.www,org.apache.mail,org.apache.jira)再存储。这 样,所有apache域名将会存储在一起。行键是最大长度为64KB的字节数组,实际应用中 长度一般为10~100B。 2.列族和列名 HBase表中的每个列都归属于某个列族,列族必须作为表的模式定义的一部分预先定 义,如create'StudentBasicInfo','StudentGradeInfo'。在一个列族中可以存放很多列,而各 个列族中列的数量可以不相同。 列族中的列名以列族名为前缀,如StudentBasicInfo:Name、StudentBasicInfo:Address 都是StudentBasicInfo列族中的列。可以按需要动态地为列族添加列。在具体存储时,一 张表中的不同列族是分开独立存放的。HBase把同一列族里面的数据存储在同一目录下, 由几个文件保存。HBase的访问控制、磁盘和内存的使用统计等都是在列族层面进行的, 同一列族成员最好有相同的访问模式和大小。 3.单元格 在HBase表中,通过行键、列族和列名确定一个单元格(cell)。每个单元格中可以保存 一个字段数据的多个版本,每个版本对应一个时间戳。 4.时间戳 在HBase表中,一个单元格往往保存着同一份数据的多个版本,根据唯一的时间戳区 分不同版本,不同版本的数据按照时间倒序排序,最新版本的数据排在最前面。这样,在读 取时,将先读取最新版本的数据。 时间戳可以由HBase在数据写入时自动用当前系统时间赋值,也可以由客户显式赋 值。当写入数据时,如果没有指定时间,那么默认的时间就是系统的当前时间;当读取数据 时,如果没有指定时间,那么返回的就是最新版本的数据。保留版本的数量由每个列族的配 第5章HBase分布式数据库109 置决定。默认的版本数量是3。为了避免数据存在过多版本造成的存储和管理(包括索引) 负担,HBase提供了两种数据版本回收方式。 (1)保存数据的最后n个版本。当版本数量过多时,HBase会将过老的版本清除。 (2)保存最近一段时间(如最近7天)内的版本。 5.区域 HBase自动把表在纵向上分成若干区域,即HRegion,每个HRegion会保存表中的一 段连续的数据。刚开始表中只有一个HRegion。随着数据的不断插入,HRegion不断增 大,当达到某个阈值时,HRegion自动等分成两个新的HRegion。 当HBase表中的行不断增多时,就会有越来越多的HRegion,这样一张表就被保存在 多个HRegion中。HRegion是HBase中分布式存储和负载均衡的最小单位。最小单位的 含义是:不同的HRegion可以分布在不同的HRegionServer上,但是一个HRegion不会拆 分到多个HRegionServer上。 5.3.2HBase数据表物理视图 在逻辑视图层面,HBase表是由许多行组成的;但在物理存储层面,HBase表采用基于 列的存储方式,而不是像传统关系数据库那样采用基于行的存储方式,这也是HBase和传 统关系数据库的重要区别。可简单认为每个列族对应一张存储表,表中的行键、列族、列名 和时间戳只确定一条记录。HBase把同一列族里面的数据存储在同一目录下,由几个文件 保存。在物理层面上,表的数据是通过SFil每个SFil toree存储的, toree相当于一个可序列 化的映射,映射的键和值都是可解释型字符数组。 在实际的HDFS存储中,直接存储每个字段数据所对应的完整的键值对: {行键,列族,列名,时间戳}→值 例如,表5-3中ID2行Phone字段下t2时间戳的数值136××××××××在存储时 的完整键值对是 {tdnBscno,Phn2}→136×××××××× ID2,SuetaiIfoe,t 也就是说,对于HBase来说,它根本不认为存在行和列这样的概念,在实现时只认为存 在键值对这样的概念。键值对的存储是排序的,行概念是通过相邻的键值对比较而构建的, HBase在物理实现上并不存在传统数据库中的二维表概念。因此,二维表中字段值的空 值,对HBase来说在物理实现上是不存在的,而不是所谓的值为nul 。 HBase在4个维度(行键、列族、列名、时间戳)上以键值对的形式保存数据,其保存的数 据量会比较大,因为对于每个字段来说,需要把对应的多个键值对都保存下来,而不像传统 数据库以两个维度只需要保存一个值就可以。 也可使用多维映射理解表5-3的班级学生HBase数据表,如图5-4所示。 行键映射一个列族的列表,列族映射一个列名的列表,列名映射一个时间戳的列表,每 个时间戳映射一个值,也就是单元格中的数据。如果使用行键检索映射的数据,那么会得到 所有的列。如果检索特定列族的数据,则会得到此列族中所有的列。如果检索列名映射的 数据,则会得到所有的时间戳及对应的数据。HBase优化了返回数据,默认仅返回最新版 本的数据。行键和关系数据库中的主键有相同的作用,不能改变列的行键。换句话说,如果 表中已经插入数据,那么列族中的列名不能改变它所属的行键。 此外也可以使用键值对的方式理解,键就是行键,值就是列中的值,但是给定一个行键 1 10 Hadoop大数据技术原理与编程(微课版) 图5-4 班级学生HBase数据表多维映射 仅能确定一行数据。可以把行键、列族、列名和时间戳都看作键,而值就是单元格中的数据, 班级学生HBase数据表的键值对结构如下所示: ID2 → { StudentBasicInfo: { Name: { Timestamp1: WangLi }, Address: { Timestamp1: Building1}, Phone:{Timestamp2: 136××××××××}} StudentGradeInfo: {Chinese: {Timestamp1: 78}, Maths: {Timestamp1: 92}, English:{Timestamp2: 88}}} ID2, StudentBasicInfo → { Name: { Timestamp1: WangLi }, Address: { Timestamp1: Building1}, Phone:{Timestamp2: 136××××××××}} ID2, StudentBasicInfo: Phone→{{Timestamp2: 136××××××××}, {Timestamp1: 158×××××××× }} ID2, StudentBasicInfo: Phone, Timestamp2→{:136××××××××} 5.3.3 HBase数据表面向列的存储 在HBase中,HRegionServer对应集群中的一个节点,而一个HRegionServer负责管 理一系列HRegion对象。HBase根据行键将一张表划分成若干HRegion,一个HRegion 代表一张表的一部分数据,所以HBase的一张表可能需要存储为很多个HRegion。 HBase在管理HRegion的时候会给每个HRegion定义一个行键的范围,落在特定范 围内的数据将交给特定的HRegion。HRegion由多个HStore组成,每个HStore对应表中 的一个列族的存储。即HRegion中的每个列族各用一个HStore存储,一个HStore代表 HRegion的一个列族。另外,HBase会自动调节HRegion所处的位置,如果一个HRegionServer 变得繁忙(大量的请求落在这个HRegionServer管理的HRegion上),HBase就会把一部分 HRegion移动到相对空闲的节点上,以保证集群资源被充分利用。