Apache HBase

1.简介

首先是一个存储系统,是一个高可靠性,高性能,面向列,可伸缩的分布式存储系统。

文件系统数据处理协同服务(集群协调)
BigTableGFSMapReduceChubby
HBaseHDFSHadoop MapReduceZookeeper
  • HBase是一种“NoSQL”数据库,而不是主要以SQL为访问手段的R(Relational)DBMS。

    本地常见的NoSQL有BerkeleyDB。

  • 前面Mesos里讲过,HBase可以作为数据存储,因为HBase更像是数据存储而不像数据库,因为HBase缺乏关系数据库额外特性(列类型,第二索引,触发器,高级语言查询)

  • 支持线性化和模块化扩充,只需要添加RegionServer,就可以增加集群的空间和容量。

2.特性

  • 强一致性读写,不是最终一致性数据存储,,适合高速的聚类和计数工作。
  • 自动分片,HBase表通过region分布在集群中,region可以自动分割,重新分布。
  • RegionServer的故障自动转移。
  • Hadoop/HDFS集成,可以无缝集成HDFS。
  • 通过MapReduce实现大规模并发处理。
  • JAVA API
  • Thrift,REST API
  • Block Cache和Bloom filter,大规模查询的优化
  • JMX内置网页运维。

3.应用场景

  • 不依赖于关系数据库的额外特性(上面提到的)。
  • 数据足够多,防止节点闲置
  • 硬件足够多,5个节点以下基本体现不出优势。

4.优缺点

  • 优点
    • 列可以动态增加
    • 空列不存储数据,因为没有列类型,节约存储空间
    • 自动切分数据,使得数据可以水平扩展
    • 高并发读写操作
    • 结合MapReduce进行数据分析
    • 行级别原子性,PUT操作一定成功或失败
  • 缺点
    • 只能通过row key查询不能支持条件查询(没有第二索引)
    • 容易产生单点故障(HMaster数量只有1时)
    • 不支持事务
    • 不支持数据库级别的JOIN,需要通过MapReduce实现
    • 只能使用递增索引和排序
    • 无内置身份认证和权限

5.与Hadoop/HDFS的区别与关系

  • HDFS:分布式文件系统,存储打文件,但是并非普通用途的文件系统,不支持个别记录的快速查询。

  • HBase基于HDFS,但是可以提供大表记录的快速查询和更新

    数据存储
    存储
    HBase
    索引好的StoreFiles
    HDFS

6.HBase的基本概念

HBase的行和列与关系数据库表的行与列不是一个概念,更像是一个多维map结构

术语

  • table:还是以行为单位的,多个行组成的
  • rw:每个行代表一个数据对象,包括一个唯一标识的行健和多个列,设计row key时,相关的row存储的要近。例如,存储域名时,要将域名反转,确保类似的行在table中近。
  • column:由column family和column qualifier组成,形式为family:qualifier
  • column family(列族):一些有相同前缀的列的集合。
    • 比如course:Math和course:English都是course的成员
    • 区分格式为: 前缀:列名
    • column family必须在建表时声明,每个column family成员在文件系统上是存储在一起的。
    • 存储优化是针对column级别的,因此一个column范围内的所有对象都采用相同的方式访问。
  • column qualifier(列限定符):column family的数据通过qualifier进行映射。
    • column qualifier也没有特定的数据类型,采用二进制字节存储。
    • column qualifier是可变的,不同row的不同qualifier可能完全不同,但family相同。
    • 这就说明了HBase表的本质:一组有着相同属性前缀的数据的集合,相同前缀的属性放在一个列家族下。
  • cell(单元格),row+column family+column qualifier+TimeStamp,有版本
  • TimeStamp’每个值都有自己的时间戳,默认值为数据被写入RegionServer的时间。
    • 不指定:返回最新的
    • 指定:返回早于这个时间戳的
  • 核心数据结构:map
  • 排序方式:HBase和BigTable的map是严格按照字母顺序排序的,例如rowkey值为a的与b相距近而与z相距远。
  • 多维:多层map嵌套

7.概念视图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hNjM1P8c-1654241591908)(C:\Users\LXC\AppData\Roaming\Typora\typora-user-images\image-20220528172017332.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2LbfdNkZ-1654241591911)(C:\Users\LXC\AppData\Roaming\Typora\typora-user-images\image-20220528172033899.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nJkyEFAV-1654241591912)(C:\Users\LXC\AppData\Roaming\Typora\typora-user-images\image-20220528172149902.png)]

8.物理视图

概念上,表是row的集合,物理上,表是按column family存储的,在定义表的family之后,可以随时向已有的column family添加column qualifier

  • column family 例子

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OG7PoB50-1654058142457)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531204231657.png)]

  • 这两个列家族放在一个表中,一定会有空白的cell单元格,物理上是不存储的。例如获取t8时刻的contents:html,返回null。若不指明timestamp,则返回最新的。

  • 例如,请求获取行键“com.cnn.www”,返回t9,t8,t6三行数据(每个列qualifier返回最新的)

9.数据模型的主要操作

  • Get,返回指定row的属性值,Table.get

  • Put,向表添加或覆盖原来的row,分为Table.put(writeBuffer)和Table.batch(非writeBuffer)

  • Scan,允许多个行的某个属性值的更新

  • 一个table有“row1",“row2",“row3",”abc1“,”abc2“,”abc3“,下面实例返回row开头的row

    public static final byte[] CF = cf.getBytes();
        public static final byte[] ATTR = ATTR.getBytes();
    
        public static void main(String[] args) {
            Table myTable = new Table();//实例化一个HBase表
            Scan scan = new Scan();
            scan.addColumn(CF,ATTR);
            scan.setRowPrefixFilter(Bytes.toBytes("row"));
            ResultScanner rs = table.getScanner(scan);
            try{
                for(Result r = rs.next();r!=null;r = rs.next()){
                    //...
                }
            }finally {
                rs.close();
            }
        }
    
    
  • https://hbase.apache.org/apidocs/里面有API,通过InclusiveStopFilter来指定scan的停止点

  • Delete,Table.delete()来删除row。

  • HBase没有修改数据的方法,因此delete操作只是给这些行添加tombstones标志,这些标志和要删除的值会在major compaction的时候删除。

10.命名空间

对一组表进行管理而创建的一种逻辑分组,类比于RDBMS中的Database,一般根据table的业务划分。

这种话分便于实现多租户。

多租户

  • 探讨与实现如何于多用户的环境下共用相同的系统或程序组件,并且仍可确保各用户间数据的隔离性。

  • 一个支持多租户技术的系统需要在设计上对它的数据和配置进行虚拟分区,从而使系统的每个租户或称组织都能够使用一个单独的系统实例,并且每个租户都可以根据自己的需求对租用的系统实例进行个性化配置。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i7TLDgvM-1654058142460)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531211132939.png)]

  • 通过使用多租户技术可以保证系统共性的部分被共享,个性的部分被单独隔离。

  • 在租户之间共享应用程序的单个实例,可以实现当应用程序升级时,所有租户可以同时升级。

HBase的多租户基础功能

配额管理,限制namespace的资源使用(table,region)。

命名空间安全管理。

Region服务器组,可以指定namespace/table部署到指定的RegionServer子集上。

命名空间管理

namespace可以创建修改删除,table和namspace的隶属关系在建表时指定

//

:

create_namespace 'my_ns'
create 'my_ns:mytable','fam'//在namespace里建表
drop_namespace  'my_ns'
alter_namespace 'my_ns',{METHOR=>'set','PROPERTY_NAME'=>'PROPERTY_VALUE'}//有点像RPC

包含两个定义好的namespace,hbase包含系统内置表,default用于存放用户未指定的表

Apache HBase的架构

  • 物理上遵循master-slave架构,包含三类服务器:

    • Region Server负责数据的读写。客户端和RegionServer交互
    • HBase Master,负责Region的分配,DDL操作(table的创建和删除)
    • Zookeeper,维护集群状态

    关于数据存储

    • Hadoop DataNode存储RegionServer读写的数据,所有HBase数据存储在HDFS文件中
    • Region Server分配DataNode,使读写的数据可以存储在本地DataNode上。
    • HBase的输入是在本地,但是在Region 被删除,必须等到compaction数据才能恢复到本地
    • NameNode用于维护组成该文件的,所有数据块的,元数据

- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qwld1KVz-1654058142461)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531212945465.png)]

1.Region

  • HBase通过水平切割table形成Region,每个Region通过记录start key和end key来定位自己在table中的位置
  • table的row key是排序的,因此client可以通过HMaster快速找到每个row key在哪个table中。(这表明table之间的row key也是不会重复的)
  • Region由HMaster分配到集群节点相应的RegionServer中;在此之后就由分配的region server负责region的
    • 启动和管理
    • 与client通信
    • 数据的读写
      - [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3ZTfPeas-1654058142461)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531213431963.png)]

2.HMaster(线程)

  • 处理region的分配,DDL操作
    • 协调启动Region Server
    • 启动时完成region的分配,负载均衡,故障恢复时region的重新分配
    • 监听集群中RegionServer实例的状态,通过hearbeat和监听Zookeeper的状态来实现。
    • table管理,向client提供创建,删除,修改table的接口
      - [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nTVGrNdQ-1654058142462)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531213755821.png)]

3.Zookeeper

  • 为集群提供协调服务,

    • 管理RegionServer和HMaster状态(available,alive),在有机器宕机时发送给active的HMaster

      这使得active HMaster能实现

      • HMaster之间的failover以及
      • 宕机RegionServer的region的故障恢复
    • Zookeeper本身包含三到五个节点,节点之间通过一致性协议来确保节点状态一致性

- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N6Z57ep6-1654058142462)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531214136478.png)]

  • 分布式锁实现只有一个HMaster是active的

4.组件协作

  • 通过Zookeeper协调集群所有节点的共享信息。

  • 唯一的active HMaster和所有的RegionServer通过session连接到Zookeeper。

  • Zookeeper通过heartbeat机制维持这些瞬息节点的存活状态(ephemeral node),如果节点失效,就会发送通知给HMaster。

- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zXgV2JiM-1654058142462)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531214508933.png)]

  • 每个RegionServer创建一个ephemeral node,HMaster通过监听这些结点来判断Server是否故障和是否可用。

  • !多个HMaster会竞争一个ephemeral node,这就需要Zookeeper来实现唯一一个active HMaster是第一个获得临时节点信息的。

  • Zookeeper与HMaster通过heartbeat来维持通信,新加入的HMaster监听active master的状态

    当前的active HMaster发送失败会导致session超时,ephemeral 节点被删除,就会选举新的HMaster

HBase的第一次读写

  • 特殊的HBase catalog table :META table,他保存集群所有region的位置信息

  • 而Zookeeper保存META table的位置信息

  • 客户端第一次读写HBase时,

    • 1.客户端获取存储在Zookeeper META table 的RegionServer,获得某个META table的位置
    • 2.客户端查询.META.服务器,根据自己读写数据的row key获取对应的Region Server,缓存META table的位置信息。
    • 3.从查询的RegionServer中获取row
  • 对于后面的读写,直接通过缓存获取META table的位置,重复23,读取row

  • 随时间推移,客户缓存的位置信息越来越多,以至于不再需要查询META table,只有在未命中时更新缓存

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qJqGPAda-1654058142463)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531215624933.png)]

  • META table,保存所有region的表,类似于B树结构

    • key :Region的start key和end key
    • value :RegionServer
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7kobkjtp-1654058142464)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531215736800.png)]

RegionServer

  • RegionServer分配了DataNode,因此运行在HDFS的DataNode上,包括
    • WAL写前日志,WAL是分布式系统的一种文件,存储尚未保存到磁盘的数据,作用是故障恢复(通过WAL进行重现)
    • Block Cache :读缓存,数据预读到内存,提高读效率
    • Mem Store : 写缓存,保存未写入磁盘的数据,再写写入磁盘前会进行排序,每个region的每个column family会有一个写缓存。
    • HFile :持久化的,排序的,key-value形式的row的集合。
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WxYBWeGM-1654058142464)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531220226881.png)]

HBase写步骤

  • 当客户端发出PUT请求时
    • 1.数据写入WAL,更新信息加到末尾

    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9h9kUsti-1654058142465)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531220439681.png)]

    • 数据写入WAL,就等于数据存储在了Mem Store中,然后PUT请求返回确认信息给客户端。

    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W4LRpgth-1654058142465)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531220611746.png)]

Mem Store

  • 在内存中存储更新信息,根据key-value在column family的归属进行分类,这些信息会在后面的region flush中被写入到一个HFile中。
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aqFjuerA-1654058142466)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531220821214.png)]

Region flush

  • 当Mem Store存储了足够多的数据,会作为一个有序集合写入到HFile中。
    • 每个column family 的多个HFile包含实际存在的cell和key-value实例。
    • 每个column family包含一个Mem Store,因此family有数量限制。
  • 经过一定时间,Mem Store的HFile会被flush到磁盘,flush时可以存储最后的序列号,便于系统查询当前执行的内容。
    • 实现方式可以是在HFile中建立一个meta field字段,存储最高序列号,反应flush操作在哪里结束。
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uv3hyDEc-1654058142466)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531221841707.png)]

HFile

  • HBase数据因为是顺序存储在HFile中,在MemStore flush的过程中,不同MemStore的cell排序方式相同。

  • 因此flush是顺序写,性能高。

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qkYPp9d3-1654058142467)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531222907672.png)]

  • 一个HFile包含多层index来供HBase查找,避免了整个文件的读取。(类比B+树的索引)

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BYUjWXf9-1654058142467)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531223204223.png)]

    • 文件的key-value递增存储
    • 索引指向存储数据的64K数据块
    • 每个块有自己的leaf index
    • 每个块的最后一个key放置中间索引(intermediate index)
    • 根索引指向中间索引
  • trailer(挂钩)指向meta block(元块),在数据持久化时写入。trailer为查询提供了布隆过滤器和时间段等功能,可以跳过不包含指定row key的文件(bloom filter的特性),时间段可以选取指定范围的row。

    精确率你认为对的中,有多少确实是对的,所占的比率:
    P r e c i s i o n = T P T F + F P Precision = \frac{TP}{TF+FP} Precision=TF+FPTP
    召回率本来是对的中,你找回了多少对的,所占的比率 :

    P r e c i s i o n = T P T P + F N Precision = \frac{TP}{TP+FN} Precision=TP+FNTP

    F 1 = 2 ∗ P r e c i s i o n ∗ R e c a l l P r e c i s i o n + R e c a l l F1 = \frac{2*Precision*Recall}{Precision+Recall} F1=Precision+Recall2PrecisionRecall

    **F1值:**精确率越高越好,召回率越高越好。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qmeBAtIY-1654058142468)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220531224506159.png)]

11.HFile读合并

同一行的cell可能不存储在同一个地方

  • row cell存储在HFile
  • 最近更新的cell存储在Mem Store
  • 最近读的cell存储在Block cache

因此读取的时候需要进行合并,读取顺序是Block cache->Mem Store->HFile

  • 扫描Block cache,读取最近读过的读缓存(key-value)
  • 扫描Mem Store,这里是最近写的数据
  • 如果扫描过前两者,都没有找到row cell,则通过trailer的bloom filter和Block cache索引,把HFile文件加载到内存中,就一定包含目标文件的row cell

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RwC2FhUd-1654058142468)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220601103254092.png)]

Mem Store的每次flush都会生成一个HFile,通过compaction来减少文件数量

Compaction机制

minor compaction

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TOT8AD6F-1654058142468)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220601103448628.png)]

  • 一些小的HFile->更大的HFile
  • 不会处理deleted / expired cell

minor compaction

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mfDFn2YE-1654058142469)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220601104204224.png)]

  • 所有的HFile ->一个HFile
  • 丢弃deleted / expired cell
  • 提高读性能
  • 操作本身带来磁盘IO和网络负担问题,带来性能问题(写入放大)

写入放大

  • 实际写入的物理数据量是写入数据量的多倍。
  • 由于闪存在可重新写入数据前必须先擦除,而擦除操作的粒度与写入操作相比低得多,执行擦除操作就会多次移动(或改写)用户数据和元数据。
  • 要改写数据,就需要读取闪存某些已使用的部分,更新它们,并写入到新的位置,如果新位置在之前已被使用过,还需连同先擦除;由于闪存的这种工作方式,必须擦除改写的闪存部分比新数据实际需要的大得多。

12.Region

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cMeGDcfn-1654058142469)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220601104427814.png)]

  • 通过start key和end key确认范围的,有序的,连续的row集合,一个table包含多个

  • Table的region以RegionServer的形式服务客户端

  • 对于过大region的分割

    • 在同一个RegionServer下创建两个region
    • 数据划分完成后,两个新region向HMaster注册上线,父region下线
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g9KCgMRf-1654058142470)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220601104608451.png)]
  • region的负载均衡

    • 当一个region被移动到另一个RegionServer,当前RegionServer的部分数据也会移动到远端节点,直到下一次major compaction才会对原来的RegionServer可访问。
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kKRtsGxx-1654058142470)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220601104823344.png)]

13.HDFS复制

  • 所有的写入和读取操作都是读取主节点

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7vlWbufe-1654058142471)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220601104951559.png)]

  • HDFS会对HFile和WAL进行冗余复制

    • HFile的复制是自动进行的,WAL的复制发生在故障恢复的时候
    • 当HFile被写入HDFS,一个副本写入本地,然后依次复制到二级节点,三级节点

14.故障恢复

Region Server故障恢复

  • 当一台RegionServer不再发送心跳给Zookeeper,Zookeeper会通知HMaster
  • HMaster检测故障RegionServer的位置
    • 把故障RegionServer的Region分配到不同新的RegionServer上。
    • 同时把故障RegionServer的WAL拆分写入region对应的RegionServer上的
      • WAL目录
      • DataNode
  • 这些RegionServer就可以replay分配到的WAL来重建Mem Store
  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bqvDNknp-1654058142471)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220601105549270.png)]

数据恢复(WAL)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lcfOsDAN-1654058142472)(C:\Users\8208191402\AppData\Roaming\Typora\typora-user-images\image-20220601111142967.png)]

  • WAl文件结构

    • WAL文件包含一个编辑列表,记录用户的操作,一个编辑代表一条PUT或DELETE
    • 编辑按顺序写入,存储时可以方便的添加到磁盘的WAL文件的末尾
  • 故障恢复

    • 如果故障时数据已经存储在HFIle中,可以直接读取HFile的三个副本来恢复
    • 如果故障时数据还在内存中,此时WAL文件采取replay操作:读WAL,排序并添加WAL中的操作到MemStore,最后把重构的MemStore写入到HFile中。
  • 设计优点

    • 高一致性:HBase采用强一致模型,确保在一个写返回之后,所有的读能访问到相同的数据
    • 高可用性:通过region的自动合并和拆分实现自动扩展,同时利用HDFS的数据备份功能(HFIle)
    • 高性能:通过RegionServer分配在相同服务器上的DataNode来实现数据的本地化存储,提高读性能,减少网络压力。
    • 高可靠性:内建了RegionServer的故障恢复机制:通过WAL来复现未持久化存储的数据。
    • 无缝与Hadoop/MapReduce集成
  • 一致性模型

    • 常用的一致性模型有:强一致性, 弱一致性,最终一致性

      • 强一致性:系统中的某个数据被成功更新后,后续任何对该数据的读取操作都将得到更新后的值。

        在任意时刻,同一系统所有节点中的数据是一样的。

      • 弱一致性:系统中的某个数据被更新后,后续对该数据的读取操作可能得到更新后的值,也可能是更改前的值。

        但经过“不一致时间窗口”这段时间后,后续对该数据的读取都是更新后的值

      • 最终一致性:是弱一致性的特殊形式。

        存储系统保证,在没有新的更新的条件下,最终所有的访问都是最后更新的值。

  • 缺陷

    • WAL速度慢
    • 故障恢复慢
    • Major Compaction可能引起IO风暴

15.安装和使用

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;

import java.io.IOException;
public class Count {
    //创建连接
    private static Connection connection = null;

    static {
        //创建配置文件
        Configuration conf = HBaseConfiguration.create();
        //设置zookeeper参数和主机名称
        conf.set("hbase.zookeeper.quorum", "hdp444,hdp555,hdp666");
        //设置端口号
        conf.set("hbase.zookeeper.property.clientPort", "2181");
        try {
            connection = ConnectionFactory.createConnection(conf);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //添加表
    public static void start1(String tablename, String... familes) throws IOException {
        Admin admin = connection.getAdmin();
        HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf(tablename));
        try {
            for (String family : familes) {
                HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(family);
                hTableDescriptor.addFamily(hColumnDescriptor);
            }
            admin.createTable(hTableDescriptor);
        } finally {
            admin.close();
        }
    }

    //添加数据
    public static void start2(String tablename, String rowKey, String family, String column, String value, String family1, String column1, String value1) throws IOException {
        Admin admin = connection.getAdmin();

        try {
            if (!admin.tableExists(TableName.valueOf(tablename))) {
                System.out.println(tablename + "表不存在");
                return;
            }
            Table table = connection.getTable(TableName.valueOf(tablename));
            Put put = new Put(Bytes.toBytes(rowKey));
            put.addColumn(Bytes.toBytes(family), Bytes.toBytes(column), Bytes.toBytes(value));
            table.put(put);
            Put put1 = new Put(Bytes.toBytes(rowKey));
            put1.addColumn(Bytes.toBytes(family1), Bytes.toBytes(column1), Bytes.toBytes(value1));
            table.put(put1);
        } finally {
            admin.close();
        }
    }

    //获取数据
    public static void start3(String tablename, String startrow, String stoprow) throws IOException {
        //获取表
        Table table = connection.getTable(TableName.valueOf(tablename));
        Scan scan = new Scan(Bytes.toBytes(startrow), Bytes.toBytes(stoprow));
        //获取列
        ResultScanner scanner = table.getScanner(scan);
        for (Result result : scanner) {
            for (Cell cell : result.rawCells()) {
                //获取rowkey
                byte[] rowbys = CellUtil.cloneRow(cell);
                String rowpom = Bytes.toString(rowbys);
                //获取val
                String commstr = Bytes.toString(CellUtil.cloneQualifier(cell));
                String values = Bytes.toString(CellUtil.cloneValue(cell));
                System.out.println(rowpom + "----" + commstr + "---" + values);
            }
        }
        scanner.close();
        table.close();
    }

    //删除一行数据
    public static void start4(String tablename, String rowkey) throws IOException {
        Admin admin = connection.getAdmin();
        if (!admin.tableExists(TableName.valueOf(tablename))) {
            System.out.println(tablename + "表不存在");
            return;
        }
        Table table = connection.getTable(TableName.valueOf(tablename));
        try {
            Delete delete = new Delete(Bytes.toBytes(rowkey));
            table.delete(delete);
        } finally {
            admin.close();
        }
    }

    //删除表
    public static void start5(String tablename) throws IOException {
        //获取对象
        Admin admin = connection.getAdmin();
        try {
            if (!admin.tableExists(TableName.valueOf(tablename))) {
                System.out.println(tablename + "表不存在");
                return;
            }
            admin.disableTable(TableName.valueOf(tablename));
            admin.deleteTable(TableName.valueOf(tablename));
        } finally {
            admin.close();
        }
    }

    public static void main(String[] args) throws IOException {
        //创建表
        start1("company","info","data");
        //添加数据
        start2("company","info","001","name","baidu","data","city","xm");
        start2("company","info","002","name","huawei","data","city","xm");
        start2("company","info","003","name","ali","data","city","xm");
//查询数据
        start3("company","001","004");
//删除一行数据
        start4("company","002");
//删除表
        start5("company");
    }
}
public static void main(String[] args) throws IOException {
    //创建表
    start1("company","info","data");
    //添加数据
    start2("company","info","001","name","baidu","data","city","xm");
    start2("company","info","002","name","huawei","data","city","xm");
    start2("company","info","003","name","ali","data","city","xm");
    //查询数据
    start3("company","001","004");
    //删除一行数据
    start4("company","002");
    //删除表
    start5("company");
     }
     }
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星辰的野望

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值