您的位置:首页 > 其它

HBase基本原理,集群搭建和简单操作

2018-10-09 22:28 387 查看

相关概念

简介

基于Google BigTable模型开发,典型key/value系统
建立在hdfs之上
提供高可靠性、高性能、列存储、可伸缩、实时读写nosql的数据库系统
主要用于海量结构化和半结构化数据存储
它介于nosql和RDBMS之间,仅能通过主键(row key)和主键的range来检索数据,仅支持单行事务(可通过hive支持来实现多表join等复杂操作)
与hadoop一样,Hbase主要依靠横向扩展,通过不断增加服务器,来增加计算和存储能力

系统架构

  • Client:
    包含访问hbase的接口,client维护着一些cache来加快对hbase的访问,比如region的位置信息
  • Master:
    1.为Region server分配region
    2.负责region server的负载均衡
    3.发现失效的region server并重新分配其上的region
    4.HDFS上的垃圾文件回收
    5.处理schema更新请求
  • Region Server
    1.Region server维护Master分配给它的region,处理对这些region的IO请求
    2.Region server负责切分在运行过程中变得过大的region

client访问hbase上数据的过程并不需要master参与(寻址访问zookeeper和region server,数据读写访问regione server),master仅仅维护者table和region的元数据信息,负载很低

物理储存

结构

  • 表中所有行都按照row key的字典序排列
  • Table 在行的方向上分割为多个Hregion
  • region按大小分割的(默认10G),每个表一开始只有一个region,随着数据不断插入表,region不断增大,当增大到一个阀值的时候,Hregion就会等分会两个新的Hregion。当table中的行不断增多,就会有越来越多的Hregion
  • Hregion是Hbase中分布式存储和负载均衡的最小单元。最小单元就表示不同的Hregion可以分布在不同的HRegion server上。但一个Hregion是不会拆分到多个regionserver上的
  • HRegion虽然是负载均衡的最小单元,但并不是物理存储的最小单元。
    事实上,HRegion由一个或者多个Store组成,每个store保存一个column family。每个Strore又由一个memStore和0至多个StoreFile组成
存储的核心: Memstore与storefile
  • 一个region由多个store组成,每个store包含一个列族的所有数据。
  • Store包括位于内存的memstore和位于硬盘的storefile
  • 负载均衡
    写操作先写入memstore,当memstore中的数据量达到某个阈值,Hregionserver启动flashcache进程写入storefile,每次写入形成单独一个storefile,当storefile的个数超过一定阈值后(默认参数hbase.hstore.blockingStoreFiles=10),多个storeFile会进行合并,当该region的所有store的storefile大小之和,即所有store的大小超过hbase.hregion.max.filesize=10G时,这个region会被拆分会把当前的region分割成两个,并由Hmaster分配给相应的region服务器,实现负载均衡
  • 客户端检索数据时,先在memstore找,找不到再找storefile
数据恢复: HLog(WAL log)

每个HRegionServer中都有一个实现Write Ahead Log的类的 HLog对象,Hlog记录数据的所有变更,一旦数据修改,就可以从log中进行恢复
每次用户操作写入MemStore的同时,也会写一份数据到HLog文件中,HLog文件定期会滚动出新的,并删除旧的文件(已持久化到StoreFile中的数据)
当HMaster通过Zookeeper感知HRegionServer的意外终止
HMaster首先会处理遗留的 HLog文件,将其中不同Region的Log数据进行拆分,分别放到相应region的目录下
然后再将失效的region重新分配,领取到这些region的HRegionServer在Load Region的过程中,会发现有历史HLog需要处理,因此会Replay HLog中的数据到MemStore中,然后flush到StoreFiles,完成数据恢复

查询路由

两张特殊的表:

  • .META.:记录了用户表的Region信息,.META.可以有多个regoin。

  • -ROOT-:记录了.META.表的Region信息,-ROOT-只有一个region。Zookeeper中记录了-ROOT-表的location。

    Client访问用户数据之前需要首先访问zookeeper,然后访问-ROOT-表,接着访问.META.表,最后才能找到用户数据的位置去访问

读写过程
  1. 读取数据
    1)客户端通过zookeeper以及root表和meta表找到目标数据所在的regionserver
    2)联系regionserver查询目标数据
    3)regionserver定位到目标数据所在的region,发出查询请求
    4)region先在memstore中查找,命中则返回
    5)如果在memstore中找不到,则在storefile中扫描(可能会扫描到很多的storefile----bloomfilter)

  2. 写入数据
    1)client向region server提交写请求
    2)region server找到目标region
    3)region检查数据是否与schema一致
    4)如果客户端没有指定版本,则获取当前系统时间作为数据版本
    5)将更新写入WAL log
    6)将更新写入Memstore
    7)判断Memstore的是否需要flush为Store文件

细节:
hbase使用MemStore和StoreFile存储对表的更新。
数据在更新时首先写入Log(WAL log)和内存(MemStore)中,MemStore中的数据是排序的,当MemStore累计到一定阈值时,就会创建一个新的MemStore,并且将老的MemStore添加到flush队列,由单独的线程flush到磁盘上,成为一个StoreFile。于此同时,系统会在zookeeper中记录一个redo point,表示这个时刻之前的变更已经持久化了。
当系统出现意外时,可能导致内存(MemStore)中的数据丢失,此时使用Log(WAL log)来恢复checkpoint之后的数据。

StoreFile是只读的,一旦创建后就不可以再修改。因此Hbase的更新其实是不断追加的操作。当一个Store中的StoreFile达到一定的阈值后,就会进行一次合并(minor_compact, major_compact),将对同一个key的修改合并到一起,形成一个大的StoreFile,当StoreFile的大小达到一定阈值后,又会对 StoreFile进行split,等分为两个StoreFile。
由于对表的更新是不断追加的,compact时,需要访问Store中全部的 StoreFile和MemStore,将他们按row key进行合并,由于StoreFile和MemStore都是经过排序的,并且StoreFile带有内存中索引,合并的过程还是比较快。

Region管理
  1. region分配
    任何时刻,一个region只能分配给一个region server。master记录了当前有哪些可用的region server。以及当前哪些region分配给了哪些region server,哪些region还没有分配。当需要分配的新的region,并且有一个region server上有可用空间时,master就给这个region server发送一个装载请求,把region分配给这个region server。region server得到请求后,就开始对此region提供服务

  2. region server上线
    master使用zookeeper来跟踪region server状态。当某个region server启动时,会首先在zookeeper上的server目录下建立代表自己的znode。由于master订阅了server目录上的变更消息,当server目录下的文件出现新增或删除操作时,master可以得到来自zookeeper的实时通知。因此一旦region server上线,master能马上得到消息

  3. region server下线
    当region server下线时,它和zookeeper的会话断开,zookeeper而自动释放代表这台server的文 1d25c 件上的独占锁。master就可以确定:
    1)region server和zookeeper之间的网络断开了。
    2)region server挂了。
    无论哪种情况,region server都无法继续为它的region提供服务了,此时master会删除server目录下代表这台region server的znode数据,并将这台region server的region分配给其它还活着的region server

Master工作机制
  1. master上线
    1)从zookeeper上获取唯一一个代表active master的锁,用来阻止其它master成为master。
    2)扫描zookeeper上的server父节点,获得当前可用的region server列表。
    3)和每个region server通信,获得当前已分配的region和region server的对应关系。
    4)扫描.META.region的集合,计算得到当前还未分配的region,将他们放入待分配region列表

  2. master下线
    由于master只维护表和region的元数据,而不参与表数据IO的过程,master下线仅导致所有元数据的修改被冻结(无法创建删除表,无法修改表的schema,无法进行region的负载均衡,无法处理region 上下线,无法进行region的合并,唯一例外的是region的split可以正常进行,因为只有region server参与),表的数据读写还可以正常进行。因此master下线短时间内对整个hbase集群没有影响。

从上线过程可以看到,master保存的信息全是可以冗余信息(都可以从系统其它地方收集到或者计算出来)
因此,一般hbase集群中总是有一个master在提供服务,还有一个以上的‘master’在等待时机抢占它的位置

容错性

Master容错:

  • Zookeeper重新选择一个新的Master
  • 无Master过程中,数据读取仍照常进行;
  • 无Master过程中,region切分、负载均衡等无法进行;

RegionServer容错:

  • 定时向Zookeeper汇报心跳,如果一旦时间内未出现心跳,Master将该RegionServer上的Region重新分配到其他RegionServer上,失效服务器上“预写”日志由主服务器进行分割并派送给新的RegionServer

  • 表(table):用于存储管理数据,具有稀疏的、面向列的特点。HBase中的每一张表,就是所谓的大表(Bigtable),可以有上亿行,上百万列。对于为值为空的列,并不占用存储空间,因此表可以设计的非常稀疏。
  • 行键(RowKey):类似于MySQL中的主键,HBase根据行键来快速检索数据,一个行键对应一条记录。与MySQL主键不同的是,HBase的行键是天然固有的,每一行数据都存在行键。
  • 列族(ColumnFamily):是列的集合。列族在表定义时需要指定,而列在插入数据时动态指定。列中的数据都是以二进制形式存在,没有数据类型。在物理存储结构上,每个表中的每个列族单独以一个文件存储(参见图1.2)。一个表可以有多个列簇。
  • 时间戳(TimeStamp):是列的一个属性,是一个64位整数。由行键和列确定的单元格,可以存储多个数据,每个数据含有时间戳属性,数据具有版本特性。可根据版本(VERSIONS)或时间戳来指定查询历史版本数据,如果都不指定,则默认返回最新版本的数据。
  • 区域(Region):HBase自动把表水平划分成的多个区域,划分的区域随着数据的增大而增多。

HBase中表表特点:

  • 大:一个表可以有上十亿行,上百万列
  • 无模式:每行都有一个可排序的主键和任意多的列,列可以根据需要动态的增加,同一张表中不同的行可以有截然不同的列
  • 面向列:面向列(族)的存储和权限控制,列(族)独立检索
  • 稀疏:对于为空(null)的列,并不占用存储空间
  • 数据多版本:每个单元中的数据可以有多个版本,默认情况下版本号自动分配,是单元格插入时的时间戳
  • 数据类型单一:Hbase中的数据都是字节数组 byte[]
RowKey 设计原则
  • Rowkey长度原则
    数据的持久化文件HFile中是按照KeyValue存储的,如果rowkey过长就要占用较大的空间,这样会极大影响HFile的存储效率
    内存的有效利用率就会降低,系统不能缓存更多的数据,这样会降低检索效率
    目前操作系统都是64位系统,内存8字节对齐,控制在16个字节,8字节的整数倍利用了操作系统的最佳特性
    所以,建议rowkey越短越好,不要超过16个字节
  • Rowkey 散列原则
    如果rowkey首字段直接是时间信息,所有的数据都会集中在一个RegionServer上,这样在数据检索的时候负载会集中在个别的RegionServer上,造成热点问题,会降低查询效率
    建议将rowkey的高位作为散列字段,由程序随机生成,低位放时间字段,这样将提高数据均衡分布在每个RegionServer,以实现负载均衡的几率
  • Rowkey唯一原则
    必须在设计上保证其唯一性,rowkey是按照字典顺序排序存储的,因此,设计rowkey的时候,要充分利用这个排序的特点,将经常读取的数据存储到一块,将最近可能会被访问的数据放到一块
避免热点

糟糕的rowkey设计是热点的源头
热点发生在大量的client直接访问集群的一个或极少数个节点(访问可能是读,写或者其他操作)
大量访问会使热点region所在的单个机器超出自身承受能力,引起性能下降甚至region不可用,这也会影响同一个RegionServer上的其他region
为了避免写热点,设计rowkey使得不同行在同一个region,但是在更多数据情况下,数据应该被写入集群的多个region,而不是一个

  • 加盐
    在rowkey的前面增加随机数
    加盐之后的rowkey就会根据随机生成的前缀分散到各个region上,以避免热点
  • 哈希
    哈希会使同一行永远用一个前缀加盐。哈希也可以使负载分散到整个集群,但是读却是可以预测的。使用确定的哈希可以让客户端重构完整的rowkey,可以使用get操作准确获取某一个行数据
  • 反转
    如果固定长度或者数字格式的rowkey前面部分相似, 就可以反转rowkey
    这样可以使得rowkey中经常改变的部分(没有意义的部分)放在前面。这样可以有效的随机rowkey,但是牺牲了rowkey的有序性

集群搭建

下载地址: http://hbase.apache.org/downloads.html

安装

  1. 上传并解压

    tar zxvf ./hbase-1.3.1-bin.tar.gz

    重命名为hbase

  2. 进入conf目录修改配置文件
    1)修改regionservers文件

    node1
    node2
    node3

    (也可以配置一个master的备用节点: 创建文件

    backuo-masters
    , 内容为:
    node2
    )
    2)修改hbase-site.xml文件

    <configuration>
    <!-- 指定hbase在HDFS上存储的路径(这里的Hadoop集群是高可用模式,如果不是高可用模式:hdfs://node1:9000/hbase) -->
    <property>
    <name>hbase.rootdir</name>
    <value>hdfs://cluster1/hbase</value>
    </property>
    <!-- 指定hbase是集群模式 -->
    <property>
    <name>hbase.cluster.distributed</name>
    <value>true</value>
    </property>
    <!-- hbase master端口号 -->
    <property>
    <name>hbase.master.port</name>
    <value>16000</value>
    </property>
    <!-- 指定hbase在zookeeper上存储的路径 -->
    <property>
    <name>hbase.zookeeper.property.dataDir</name>
    <value>/export/data/zkdata</value>
    </property>
    <!-- 指定zk的地址,多个用“,”分割 -->
    <property>
    <name>hbase.zookeeper.quorum</name>
    <value>node1,node2,node3</value>
    </property>
    <property>
    <name>hbase.zookeeper.property.clientPort</name>
    <value>2181</value>
    </property>
    </configuration>

    3)修改hbase-env.sh文件

    # 禁用hbase自带的zookeeper(使用外部的zk)
    export HBASE_MANAGES_ZK=false
    # 指定JAVA_HOME
    export JAVA_HOME=/export/server/jdk1.8.0_181/

    4)拷贝Hadoop的配置文件hdfs-site.xml到hbase(里面有关于dfs.nameservices的定义)

    cp /export/server/hadoop-2.7.4/etc/hadoop/hdfs-site.xml /export/server/hbase/conf/

    如果Hadoop不是高可用模式需要拷贝core-site.xml文件

  3. 将修改好的hbase分发给其余Linux

    scp -r /export/server/hbase/ root@node2:/export/server/
    scp -r /export/server/hbase/ root@node3:/export/server/

启动

  1. 启动前先同步一下时间:ntpdate ntp6.aliyun.com

  2. 启动zookeeper集群和Hadoop集群
    (有可能需要在hdfs根路径下创建hbase)

  3. 启动/停止HBase集群

    cd /export/server/hbase/bin

    启动:

    ./start-hbase.sh

    停止:

    ./stop-hbase.sh

  4. 查看web UI界面
    浏览器访问 http://node1:16010

(节点的单独启动:

hbase-daemon.sh start master
hbase-daemon.sh start regionserver
; 停止
hbase-daemon.sh stop master
hbase-daemon.sh stop regionserver
)

查看进程
>jps

node1:
HRegionServer
HMaster

node2和node3:
HRegionServer

启动成功

shell操作

官网文档: http://hbase.apache.org/book.html

  • 启动shell客户端

    hbase shell

  • 查看所有表

    list

  • 创建表(简单的命令)

    create ‘t1’, ‘f1’

    t1:表名, f1:列族; 例:

    create ‘test’,‘base_info’

  • 向表中写入数据

    put ‘t1’, ‘r1’, ‘c1’, ‘value’

    t1:表, r1:行键rowkey, c1:属性, value:值; 例:

    put ‘test’,‘rowkey_1’,‘base_info:testname’,‘张三’
    put ‘test’,‘rowkey_1’,‘base_info:birthday’,‘1998-01-10’
    put ‘test’,‘rowkey_1’,‘base_info:sex’,‘1’
    put ‘test’,‘rowkey_1’,‘base_info:address’,‘北京’

  • 查看表内容

    scan ‘t1’

  • 查看某个行键rowkey下的内容

    get ‘t1’,‘r1’

    例:

    get ‘test’,‘rowkey_1’

  • 查询某个列内容

    get ‘t1’,‘r1’,‘f1:c1’

    例:

    get ‘test’,‘rowkey_1’,‘base_info:testname’

  • 查看多个列的内容

    get 't1,‘r1’,{COLUMN => [‘f1:c1’,‘f1:c2’]}

    例:

    get ‘test’,‘rowkey_1’,{COLUMN => [‘base_info:testname’,‘base_info:sex’]}

  • 删除某条数据

    delete ‘t1’,‘r1’,‘f1:c1’

    例:

    delete ‘test’,‘rowkey_2’,‘base_info:testname’

  • 清空表数据

    truncate ‘t1’

  • 查看表信息

    describe ‘t1’

  • 列族操作
    添加列族

    alter ‘t1’, NAME => ‘f2’

    删除列族

    alter ‘t1’, ‘delete’ => ‘f2’

Java api 操作

官方文档: http://hbase.apache.org/apidocs/index.html

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: