Hbase发展历史

要说清楚HBase的来龙去脉,还得从Google当年风靡一时的“三篇论文”——GFS、MapReduce、BigTable说起。2003年Google在SOSP会议上发表了大数据历史上第一篇公认的革命性论文——《 GFS: The Google File System 》

之所以称其为“革命性”是有多方面原因的:首先,Google在该论文中第一次揭示了如何在大量廉价机器基础上存储海量数据,这让人们第一次意识到海量数据可以在不需要任何高端设备的前提下实现存储,换句话说,任何一家公司都有技术实力存储海量数据,这为之后流行的海量数据处理奠定了坚实的基础。

其次,GFS体现了非常超前的设计思想,以至于十几年之后的今天依然指导着大量的分布式系统设计,可以说,任何从事分布式系统开发的人都有必要反复阅读这篇经典论文。

2004年,Google又发表了另一篇非常重要的论文—— 《 MapReduce: Simplefied Data Processing on Large Clusters 》,这篇论文论述了两个方面的内容,其中之一是MapReduce的编程模型,在后来的很多讨论中,人们对该模型褒贬不一,该编程模型在之后的技术发展中接受了大量的架构性改进,演变成了很多其他的编程模型,例如DAG模型等。

2006年,Google发布了第三篇重要论文——《 BigTable: A DistributedStorage System for Structured Data 》,用于解决Google内部海量结构化数据的存储以及高效读写问题。

这三篇论文在大数据历史上,甚至整个IT界的发展历史上都具有革命性意义。但真正让大数据“飞入寻常百姓家”,是另一个科技巨头——Yahoo。Google的三篇论文论证了在大量廉价机器上存储、处理海量数据(结构化数据、非结构化数据)是可行的,然而并没有给出开源方案。

2004年,Doug Cutting和Mike Cafarella在为他们的搜索引擎爬虫(Nutch)实现分布式架构的时候看到了Google的GFS论文以及MapReduce论文。他们在之后的几个月里按照论文实现出一个简易版的HDFS和MapReduce,这也就是Hadoop的最早起源。而Hadoop那个著名的大象Logo据说是DougCutting儿子的一个玩具。

最初这个简易系统确实可以稳定地运行在几十台机器上,但是没有经过大规模使用的系统谈不上完美。所幸他们收到了Yahoo的橄榄枝。在Yahoo,Doug领导的团队不断地对系统进行改进,促成了Hadoop从几十台到几百台再到几千台机器规模的演变,直到这个时候,大数据才真正在普通公司实现落地。

至于BigTable,没有在Yahoo内得到实现,原因不明。一家叫做Powerset的公司,为了高效处理自然语言搜索产生的海量数据实现了BigTable的开源版本——HBase,并在发展了2年之后被Apache收录为顶级项目,正式入驻Hadoop生态系统。HBase成为Apache顶级项目之后发展非常迅速,各大公司纷纷开始使用HBase,HBase社区的高度活跃性让HBase这个系统发展得更有活力。有意思的是,Google在将BigTable作为云服务对外开放的时候,决定提供兼容HBase的API。

HBase架构原理

HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统

HBase是典型的master-worker模式,主要组件有:Hbase是由Client、Zookeeper、Master、HRegionServer、HDFS等几个组件组成。

  • Client

    Client包含了访问Hbase的接口,另外Client还维护了对应的cache来加速Hbase的访问,比如cache的.META.元数据的信息。

  • Zookeeper

    HBase通过Zookeeper来做master的高可用、RegionServer的监控、元数据的入口以及集群配置的维护等工作。具体工作如下:

    通过Zoopkeeper来保证集群中只有1个master在运行,如果master异常,会通过竞争机制产生新的master提供服务

    通过Zoopkeeper来监控RegionServer的状态,当RegionSevrer有异常的时候,通过回调的形式通知Master RegionServer上下线的信息

    通过Zoopkeeper存储元数据的统一入口地址。

  • Hmaster

    master节点的主要职责如下:
    为RegionServer分配Region
    维护整个集群的负载均衡
    维护集群的元数据信息
    发现失效的Region,并将失效的Region分配到正常的RegionServer上
    当RegionSever失效的时候,协调对应Hlog的拆分

  • HregionServer

    HregionServer直接对接用户的读写请求,是真正的“干活”的节点。它的功能概括如下:
    管理master为其分配的Region
    处理来自客户端的读写请求
    负责和底层HDFS的交互,存储数据到HDFS
    负责Region变大以后的拆分
    负责Storefile的合并工作

  • HDFS

    HDFS为Hbase提供最终的底层数据存储服务,同时为HBase提供高可用(Hlog存储在HDFS)的支持,具体功能概括如下:
    提供元数据和表数据的底层分布式存储服务
    数据多副本,保证的高可靠和高可用性

HBase基于HDFS ,我们可以做个类比,方便理解HBase和HDFS的关系,那就是MySQL等我们熟悉的数据库。

MySQL中存储的数据最终是存在操作系统的文件系统中,以一个文件的形式存在,MySQL中有数据库、表、行等概念,数据是按照行存储,即数据在内存中的形态是按照一行一行放入内存区域,查询时,会取出整行数据。

Hbase也是一个数据库,只是这时它的数据最终是存在HDFS上,HDFS这里扮演的就是文件系统的概念呢。HBase中有命名空间(namespace), 命名空间中有表,表里有行另外还有列族概念。这里命名空间就类似MySQL的数据库,用来做隔离,表中的数据是按照列组织存放在内存中,列族就是多个列的逻辑分组,列族中可以有多个列。有了列族的概念,就可以实现表字段的动态扩展。

正是因为是按照列存储,所以对于一些统计分析,非常高效。比如存放的学生信息,其中有分数一列,如果是Mysql统计学生的平均分,那需要查出每一行数据,取出其中分数 的值相加后计算。而Hbase中,因为分数这列数据都存在一起,那直接将分数读出后计算即可,而不用读取不需要的数据。

安装部署

hbase下载地址:

https://archive.apache.org/dist/hbase/

  • 安装Zookeeper

  • 安装Hbase:

    #解压安装包
    tar -zxvf hbase-1.3.1-bin.tar.gz -C /opt/module
    

    修改配置hbase-env.sh修改内容:

    export JAVA_HOME=/opt/module/jdk1.8.0_144
    export HBASE_MANAGES_ZK=false
    JDK1.8需要注释
    #export HBASE_MASTER_OPTS。。。。
    #export HBASE_REGIONSERVER_OPTS。。。
    

    hbase-site.xml修改内容:

    <configuration>
    <property>     
        <name>hbase.rootdir</name>     
        <value>hdfs://hadoop102:9000/hbase</value>   
    </property>
    
    <property>   
        <name>hbase.cluster.distributed</name>
        <value>true</value>
    </property>
    
     <!-- 0.98后的新变动,之前版本没有.port,默认端口为60000 -->
    <property>
        <name>hbase.master.port</name>
        <value>16000</value>
    </property>
    
    <property>   
        <name>hbase.zookeeper.quorum</name>
         <value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value>
    </property>
    
    <property>   
        <name>hbase.zookeeper.property.dataDir</name>
         <value>/opt/module/zookeeper-3.4.10/zkData</value>
    </property>
    </configuration>
    

    regionservers:

    hadoop102
    hadoop103
    hadoop104
    

    软连接hadoop配置文件到hbase:

    ln -s /opt/module/hadoop-2.7.2/etc/hadoop/core-site.xml /opt/module/hbase/conf/core-site.xml
    ln -s /opt/module/hadoop-2.7.2/etc/hadoop/hdfs-site.xml /opt/module/hbase/conf/hdfs-site.xml
    

    分发到集群中:

    xsync hbase/ 
    
  • 启动
    #方式一:单独启动
    bin/hbase-daemon.sh start master
    bin/hbase-daemon.sh start regionserver
    
    #方式二:一次性启动
    bin/start-hbase.sh
    bin/stop-hbase.sh
    

    提示:如果集群之间的节点时间不同步,会导致regionserver无法启动,抛出ClockOutOfSyncException异常。

  • 查看页面
    http://hadoop102:16010

shell常用命令

HBase的命令帮助文档比较详细

./bin/hbase shell  #进入hbase 命令交互窗口

通过help命令查看帮助:

hbase(main):001:0> help
HBase Shell, version 1.3.1, r930b9a55528fe45d8edce7af42fef2d35e77677a, Thu Apr  6 19:36:54 PDT 2017
Type 'help "COMMAND"', (e.g. 'help "get"' -- the quotes are necessary) for help on a specific command.
Commands are grouped. Type 'help "COMMAND_GROUP"', (e.g. 'help "general"') for help on a command group.

COMMAND GROUPS:
  Group name: general
  Commands: status, table_help, version, whoami

  Group name: ddl
  Commands: alter, alter_async, alter_status, create, describe, disable, disable_all, drop, drop_all, enable, enable_all, exists, get_table, is_disabled, is_enabled, list, locate_region, show_filters

  Group name: namespace
  Commands: alter_namespace, create_namespace, describe_namespace, drop_namespace, list_namespace, list_namespace_tables

  Group name: dml
  Commands: append, count, delete, deleteall, get, get_counter, get_splits, incr, put, scan, truncate, truncate_preserve

  Group name: tools
  Commands: assign, balance_switch, balancer, balancer_enabled, catalogjanitor_enabled, catalogjanitor_run, catalogjanitor_switch, close_region, compact, compact_rs, flush, major_compact, merge_region, move, normalize, normalizer_enabled, normalizer_switch, split, splitormerge_enabled, splitormerge_switch, trace, unassign, wal_roll, zk_dump

  Group name: replication
  Commands: add_peer, append_peer_tableCFs, disable_peer, disable_table_replication, enable_peer, enable_table_replication, get_peer_config, list_peer_configs, list_peers, list_replicated_tables, remove_peer, remove_peer_tableCFs, set_peer_tableCFs, show_peer_tableCFs

  Group name: snapshots
  Commands: clone_snapshot, delete_all_snapshot, delete_snapshot, delete_table_snapshots, list_snapshots, list_table_snapshots, restore_snapshot, snapshot

  Group name: configuration
  Commands: update_all_config, update_config

  Group name: quotas
  Commands: list_quotas, set_quota

  Group name: security
  Commands: grant, list_security_capabilities, revoke, user_permission

  Group name: procedures
  Commands: abort_procedure, list_procedures

  Group name: visibility labels
  Commands: add_labels, clear_auths, get_auths, list_labels, set_auths, set_visibility



可以看到命令分为不同的组,如果想查看某个具体指令用法可以进一步通过 指令名+help的方式查看帮助

这里我想看看create建表相关语法: create help 可以看到建表的示例。比如简化写法,如何指定命名空间以及字段属性等等,非常详细。

Here is some help for this command:
Creates a table. Pass a table name, and a set of column family
specifications (at least one), and, optionally, table configuration.
Column specification can be a simple string (name), or a dictionary
(dictionaries are described below in main help output), necessarily
including NAME attribute.
Examples:

Create a table with namespace=ns1 and table qualifier=t1
  hbase> create 'ns1:t1', {NAME => 'f1', VERSIONS => 5}

Create a table with namespace=default and table qualifier=t1
  hbase> create 't1', {NAME => 'f1'}, {NAME => 'f2'}, {NAME => 'f3'}
  hbase> # The above in shorthand would be the following:
  hbase> create 't1', 'f1', 'f2', 'f3'
  hbase> create 't1', {NAME => 'f1', VERSIONS => 1, TTL => 2592000, BLOCKCACHE => true}
  hbase> create 't1', {NAME => 'f1', CONFIGURATION => {'hbase.hstore.blockingStoreFiles' => '10'}}

Table configuration options can be put at the end.
Examples:

  hbase> create 'ns1:t1', 'f1', SPLITS => ['10', '20', '30', '40']
  hbase> create 't1', 'f1', SPLITS => ['10', '20', '30', '40']
  hbase> create 't1', 'f1', SPLITS_FILE => 'splits.txt', OWNER => 'johndoe'
  hbase> create 't1', {NAME => 'f1', VERSIONS => 5}, METADATA => { 'mykey' => 'myvalue' }
  hbase> # Optionally pre-split the table into NUMREGIONS, using
  hbase> # SPLITALGO ("HexStringSplit", "UniformSplit" or classname)
  hbase> create 't1', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}
  hbase> create 't1', 'f1', {NUMREGIONS => 15, SPLITALGO => 'HexStringSplit', REGION_REPLICATION => 2, CONFIGURATION => {'hbase.hregion.scan.loadColumnFamiliesOnDemand' => 'true'}}
  hbase> create 't1', {NAME => 'f1', DFS_REPLICATION => 1}

You can also keep around a reference to the created table:

  hbase> t1 = create 't1', 'f1'

Which gives you a reference to the table named 't1', on which you can then
call methods.


hbase(main):003:0>

常用命令示例:

#查看命名空间列表:默认建表都是在default命名空间
list_namespace
#查看default命名空间中的表
list
#查看某个命名空间下的表有哪些,default命名空间,可以用list直接查看
list_namespace_tables 'default'

#创建表:创建一个student表,该表有两个列族分别是stu_info 用来
#保存基本信息,和ext_info 用来保存用户的扩展信息
#1-1.简化写法,
create 'student','stu_info','ext_info'

#1-2.设置一些属性,比如版本数,分区数等等..
create 'student',{NAME=>'stu_info',VERSIONS=>3},{NAME=>'ext_info',VERSIONS=>2}


#查看表定义
describe 'student'

#插入数据:一次只允许插入一列数据
#这里的1001就是row-key,stu_info是列族,name是列名,后边是列的值.列族在创建表时就已经确定.而列名可以自定义,并且
#可以添加一个或多个不做限制。
put 'student','1001','stu_info:name','zhangsan'
put 'student','1001','stu_info:age','22'
put 'student','1001','ext_info:email','11@qq.com'


#查看表数据
scan 'student'
scan 'student',{STARTROW => '1001', STOPROW  => '1001'}

#查看某列数据
get 'student','1001','stu_info:name'
#查看某列的多个版本:可以保存的版本数不会超过列族设置的VERSIONS值
get 'student','1001',{COLUMN => 'stu_info:name',VERSIONS => 5}


#统计表行数
count 'student'

#删除表:删除表要在表不可用时才可删除.
disable 'student' #禁用
drop 'student'    #删除


#修改列族属性:
alter 'student', {NAME => 'stu_info', VERSIONS => 3}
alter 'student', NAME => 'stu_info', VERSIONS => 5  
#增加列族:
alter 'student', 'hobby'
#删除列族:
alter 'student', 'delete' => 'hobby'

版本数含义:

一个列,当多次put操作到同一个个row-key的列上,会保存历史版本(如果列族设置了VERSIONS属性,默认只保存一个版本,即会覆该)。

shell客户端长时间连接时,可能会出现一些问题, 需要重启hbase。

小结

本文介绍了HBase 的发展历史以及HBase架构中各个组件的作用,并将常用的shell脚本做了记录。实际使用时,更多的是通过编程调用API的方式来访问HBase,

而具体HBase读写数据的原理,以及为何HBase的写性能如此强劲?我们后续再聊。

发表回复

您的电子邮箱地址不会被公开。