01 Hadoop生态系统的主要大数据工具整合应用
一、NoSQL数据库HBase
NoSQL是“Not Only SQL”的缩写,泛指用来解决大数据相关问题而创建的数据库技术,NoSQL技术不会完全替代关系型数据库,而是关系型数据的一种补充。
HBase是建立在Hadoop文件系统之上的分布式面向列的NoSQL数据库。它是一个开源项目,可横向扩展。
HBase的数据模型,类似于谷歌的BigTable设计,可以快速随机访问海量半结构化数据,并利用了Hadoop的文件系统HDFS提供的容错能力。
涉及的主要知识点如下。
- HBase原理:HBase概述、HBase核心概念、HBase的关键流程。
- HBase安装:解压并配置环境变量、配置HBase参数、验证HBase。
- HBase Shell:学会使用HBase Shell命令来操作HBase数据。
二、HBase
1. 原理
HBase是NoSQL数据库的一种,与传统关系型数据库有很多区别,既可以存储结构化数据,也可以存储非结构化数据或半结构化数据。
结构化数据,即行数据,存储在数据库里,可以用二维表结构来逻辑表达实现的数据;
不方便用数据库二维逻辑表来表现的数据即称为非结构化数据,包括所有格式的办公文档、文本、图片、XML、HTML、各类报表、图像和音频/视频信息等等;
半结构化数据,就是介于完全结构化数据(如关系型数据库、面向对象数据库中的数据)和完全无结构的数据(如声音、图像文件等)之间的数据,HTML文档就属于半结构化数据。它一般是自描述的,数据的结构和内容混在一起,没有明显的区分。
HBase是一个在HDFS上开发的面向列的分布式数据库
HBase并不是关系型数据库,它不支持SQL。但在特定的问题空间里,它能够做RDBMS不能做的事:在廉价硬件构成的集群上管理超大规模的稀疏表。
在许多应用中,表似乎是最自然的一种选择,但有时出于对空间的考虑,就有可能放弃这种选择。当只用表的一小部分时尤其如此,这种类型的表称为稀疏表(sparse table),因为表中只是稀疏地放置了一些数据,它的大部分单元都是空的。此时可以用链表代替表。
与NoSQL数据库一样,row key是用来检索记录的主键。访问HBase表中的行,只有3种方式。
(1)通过单个row key访问单条记录。
(2)通过row key的range指定检索范围。
(3)全表扫描。
各个角色的功能如下。
(1)Region:表中一部分数据组成的子集,当Region内的数据过多时能够自动分裂,过少时会合并。
(2)RegionServer:维护Master分配给它的Region,处理对这些Region的IO请求,负责切分在运行过程中变得过大的Region。
(3)Master:为RegionServer分配Region,负责RegionServer的负载均衡,发现失效的RegionServer并重新分配其上的Region,执行HDFS上的垃圾文件回收。
(4)ZooKeeper:保证任何时候集群中只有一个Master存储所有Region的寻址入口。实时监控RegionServer的状态,将RegionServer的上线和下线信息实时通知给Master。存储HBase的Schema,包括有哪些table、每个table有哪些column family,处理Region和Master的失效。
2. 关键流程
HBase客户端会将查询过的HRegion的位置信息进行缓存,如果客户端没有缓存一个HRegion的位置或者位置信息是不正确的,客户端会重新获取位置信息。如果客户端的缓存全部失效,则需要进行多次网络访问才能定位到正确的位置。
(1)Region的分配任何时刻,一个Region只能分配给一个RegionServer。Master跟踪当前有哪些可用的RegionServer,以及当前哪些Region分配给了哪些RegionServer,哪些Region还没有分配。当存在未分配的Region且有一个RegionServer上有可用空间时,Master就给这个RegionServer发送一个装载请求,把Region分配给这个RegionServer。RegionServer得到请求后,就开始对此Region提供服务。
(2)RegionServer上线Master使用ZooKeeper来跟踪RegionServer状态。当某个RegionServer启动时,会首先在ZooKeeper上的rs目录下建立代表自己的文件,并获得该文件的独占锁。由于Master订阅了rs目录上的变更消息,当rs目录下的文件出现新增或删除操作时,Master可以得到来自ZooKeeper的实时通知。因此一旦RegionServer上线,Master能马上得到消息。
(3)RegionServer下线当RegionServer下线时,它和ZooKeeper的会话断开,ZooKeeper会自动释放代表这台Server的文件上的独占锁,而Master不断轮询rs目录下文件的锁状态。如果Master发现某个RegionServer丢失了它自己的独占锁,Master就会尝试去获取代表这个RegionServer的读写锁,一旦获取成功,就可以确定:
- RegionServer和ZooKeeper之间的网络断开了;
- RegionServer失效了。
只要这两种情况中的一种情况发生了,无论哪种情况,RegionServer都无法继续为它的Region提供服务,此时Master会删除Server目录下代表这台RegionServer的文件,并将这台RegionServer的Region分配给其他还“活着”的机器。如果网络短暂出现问题导致RegionServer丢失了它的锁,那么RegionServer重新连接到ZooKeeper之后,只要代表它的文件还在,它就会不断尝试获取这个文件上的锁,一旦获取到了,就可以继续提供服务。
(4) Master上线Master启动上线包括以下步骤。
- 从ZooKeeper上获取唯一代表Master的锁,用来阻止其他节点成为Master。
- 扫描ZooKeeper上的Server目录,获得当前可用的RegionServer列表。
- 与每个RegionServer通信,获得当前已分配的Region和RegionServer的对应关系。
- 扫描.META.region的集合,计算得到当前还未分配的Region,将它们放入待分配Region列表。
(5)Master下线由于Master只维护表和Region的元数据,而不参与表数据IO的过程,所以Master下线仅导致所有元数据的修改被冻结。此时无法创建、删除表,无法修改表的schema,无法进行Region的负载均衡,无法处理Region上下线,无法进行Region的合并,唯一例外的是Region的split可以正常进行,因为只有RegionServer参与,表的数据读写还可以正常进行。因此Master下线短时间内对整个HBase集群没有影响。
从上线过程可以看到,Master保存的信息全是冗余信息,都可以从系统其他地方收集或者计算出来。因此,一般HBase集群中总是有一个Master在提供服务,还有一个以上的“Master”在等待时机抢占它的位置。
当客户端要修改HBase的数据时,首先创建一个action(比如put、delete、incr等操作),这些action都会被包装成Key-Value对象,然后通过RPC将其传输到HRegionServer上。HRegionServer将其分配给相应的HRegion,HRegion先将数据写入Hlog中,然后将其写入MemStore。MemStore中的数据是排序的,当MemStore累计到一定阈值时,就会创建一个新的MemStore,并且将老的MemStore添加到flush队列,由单独的线程flush到磁盘上,成为一个StoreFile。与此同时,系统会在ZooKeeper中记录一个redo point,表示这个时刻之前的变更已经持久化了。当系统出现意外时,可能导致内存(MemStore)中的数据丢失,此时使用Log(WAL log)来恢复redo point之后的数据。
StoreFile是只读的,一旦创建后就不可以再修改,因此HBase的更新其实是不断追加的操作。当一个Store中的StoreFile达到一定的阈值后,就会进行一次合并,将对同一个key的修改合并到一起,形成一个大的StoreFile。
由于对表的更新是不断追加的,处理读请求时,需要访问Store中全部的StoreFile和MemStore,将它们的数据按照row key进行合并,由于StoreFile和MemStore都是经过排序的,并且StoreFile带有内存中索引,所以合并的过程还是比较快的。
(6) 写请求处理过程写清楚处理过程如下。
- Client向RegionServer提交写请求。
- RegionServer找到目标Region。
- Region检查数据是否与schema一致。
- 如果客户端没有指定版本,则获取当前系统时间作为数据版本。
- 将更新写入WAL log。
- 将更新写入Memstore。
- 判断Memstore的数据是否需要flush为Store文件。
3. 安装HBase
前提条件:启动Hadoop,jps验证五个进程启动成功

- 解压并配置环境变量、HBase参数
tar -zxvf hbase-1.4.10-bin.tar.gz# 重命名文件夹mv hbase 1.4.10 hbase# 修改环境变量vim /etc/profile# 加入变量export HBASE_HOME=/usr/local/habse# 在 PATH后加入:$HBASE_HOME/bin# 使环境变量立即生效source /etc/profile# 切换目录cd /usr/local/hbase/conf# 修改 hbase-env.shvim hbase-env.sh# 位于27行更改为export JAVA_HOME=/usr/local/jdk/# 位于128行注释解开export HBASE_MANAGES_ZK=true# 配置hbase-site.xml
# /etc/profileexport JAVA_HOME=/usr/local/jdkexport HADOOP_HOME=/usr/local/hadoopexport HBASE_HOME=/usr/local/hbaseexport PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$HBASE_HOME/binexport HDFS_NAMENODE_USER=rootexport HDFS_DATANODE_USER=rootexport HDFS_SECONDARYNAMENODE_USER=rootexport YARN_RESOURCEMANAGER_USER=rootexport YARN_NODEMANAGER_USER=root
# hbase-env.sh# The java implementation to use. Java 1.7+ required.export JAVA_HOME=/usr/local/jdk# Tell HBase whether it should manage it's own instance of Zookeeper or not.export HBASE_MANAGES_ZK=true
# hbase-site.xml<?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="configuration.xsl"?><configuration><property><name>hbase.rootdir</name><value>hdfs://hadoop0:9000/hbase</value></property><property><name>hbase.cluster.distributed</name><value>true</value></property><property><name>hbase.zookeeper.quorum</name><value>hadoop0</value></property></configuration>
- 验证HBase
# 启动/bin/start-hbase.sh

# 启动hbase shell命令行hbase shell# 显示所有的表list

- 浏览器验证
http://hadoop0:16010

- 查看HDFS文件系统
hadoop fs -ls /# HBase自动在HDFS根目录下创建了一个hbase文件夹

- 查看HBase进程
jps# 后台启动了3个H开头的HBase进程

三、HBase Shell
HBase允许使用类似Shell命令的方式来操作HBase数据
常用的HBase Shell命令
| 名称 | 命令表达式 |
|---|---|
| 创建表 | create ‘表名称’,’列族名称1’,’列族名称2’,’列族名称N’ |
| 添加记录 | put’表名称’,’行键’,’列名称:’,’值’ |
| 查看记录 | get ‘表名称’,’行键‘ |
| 查看表中的记录总数 | count ‘表名称’ |
| 删除记录 | delete ‘表名’,行键’,’列名称’ |
| 删除一张表 | 先要屏蔽该表,才能对该表进行删除,第一步disable ‘表名称’,第二步 drop’表名称’ |
| 查看所有记录 | scan ‘表名称’ |
| 查看某个表某个列中的所有数据 | scan ‘表名称’,{COLUMNS=>’列族名称:列名称’} |
| 更新记录 | 重写一遍进行覆盖 |
案例
学生成绩表

列族:course
- Chinese
- Math
- English
命令
version
status
create
# 创建一个具有3个列族(name,grad,course)的表scorescreate 'scores','name','grad','course'

list
describe(可以简写desc)

put
使用put命令向表中插入数据,参数分别为表名、行名、列名和值,其中列名前需要列族作为前缀,时间戳由系统自动生成。
格式:put表名,行键,列名([列族:列名]),值。put 'scores','xiaopi','course:Chinese','97'put 'scores','xiaopi','course:Math','128'put 'scores','xiaopi','course:English','85'put 'scores','xiaoxue','course:Chinese','99'put 'scores','xiaoxue','course:Math','118'put 'scores','xiaoxue','course:English','88'

- get
get 'scores','xiaopi'get 'scores','xiaopi','course:Math'get 'scores','xiaopi',{COLUMN=>'course:Math'}get 'scores','xiaopi',{COLUMNS=>'course:Math'}# COLUMN和COLUMNS必须大写

- scan
scan ’scores'# grad未赋值scan 'scores',{COLUMN=>'grad'}scan 'scores',{COLUMN=>'course:Math'}scan 'scores',{COLUMNS=>'course'}scan 'scores',{COLUMNS=>'course:English'}

count:统计记录条数
exits:判断表是否存在
修改表结构
disable 'scores'alter 'scores',{NAME=>'course',VERSIONS=>3}enable 'scores'
HBase默认只保存一份历史副本,以上命令可以将HBase的scores表course列族改为保存3份历史副本
- delete
delete 'scores','xiapi','course:Math'scan 'scores'delete all 'scores'
- truncate
清空表中的数据,但保留表结构truncate 'scores'
- disable、drop
通过disable和drop命令删除scores表
要彻底删除表数据和表结构,必须先disable,再dropdisable 'scores'drop 'scores'
