海量列式非关系数据库HBase 架构,shell与API

wangheng1409 2021-09-15 07:40:07
数据库 关系 海量 列式 系数


HBase的特点:

  • 海量存储: 底层基于HDFS存储海量数据
  • 列式存储:HBase表的数据是基于列族进行存储的,一个列族包含若干列
  • 极易扩展:底层依赖HDFS,当磁盘空间不足的时候,只需要动态增加DataNode服务节点就可以
  • 高并发:支持高并发的读写请求
  • 稀疏:稀疏主要是针对HBase列的灵活性,在列族中,你可以指定任意多的列,在列数据为空的情 况下,是不会占用存储空间的。
  • 数据的多版本:HBase表中的数据可以有多个版本值,默认情况下是根据版本号去区分,版本号就 是插入数据的时间戳
  • 数据类型单一:所有的数据在HBase中是以字节数组进行存储

HBase的应用场景:

HBase适合海量明细数据的存储,并且后期需要有很好的查询性能(单表超千万、上亿, 且并发要求高)

HBase数据模型:

 

HBase整体架构:

 

 

 Zookeeper

  • 实现了HMaster的高可用
  • 保存了HBase的元数据信息,是所有HBase表的寻址入口
  • 对HMaster和HRegionServer实现了监控

HMaster(Master)

  • 为HRegionServer分配Region 维护整个集群的负载均衡
  • 维护集群的元数据信息
  • 发现失效的Region,并将失效的Region分配到正常的HRegionServer上

HRegionServer(RegionServer)

  • 负责管理Region 接受客户端的读写数据请求
  • 切分在运行过程中变大的Region

Region

  • 每个HRegion由多个Store构成, 每个Store保存一个列族(Columns Family),表有几个列族,则有几个Store,
  • 每个Store由一个MemStore和多个StoreFile组成,MemStore是Store在内存中的内容,写到文件 后就是StoreFile。
  • StoreFile底层是以HFile的格式保存

HBase shell 基本操作:

入口:hbase shell

hbase(main):001:0> create 'lagou', 'base_info', 'extra_info'
或者(Hbase建表必须指定列族信息)
create 'lagou', {NAME => 'base_info', VERSIONS => '3'},{NAME =>
'extra_info',VERSIONS => '3'}
VERSIONS 是指此单元格内的数据可以保留最近的 3 个版本

添加数据操作:

向lagou表中插入信息,row key为 rk1,列族base_info中添加name列标示符,值为wang
put 'lagou', 'rk1', 'base_info:name', 'wang'
向lagou表中插入信息,row key为rk1,列族base_info中添加age列标示符,值为30
put 'lagou', 'rk1', 'base_info:age', 30
向lagou表中插入信息,row key为rk1,列族extra_info中添加address列标示符,值为shanghai put 'lagou', 'rk1', 'extra_info:address', 'shanghai'

查询,更新,删除:

获取表中row key为rk1的所有信息
get 'lagou', 'rk1'
获取lagou表中row key为rk1,base_info列族的所有信息
get 'lagou', 'rk1', 'base_info'
获取表中row key为rk1,base_info列族的name、age列标示符的信息
get 'lagou', 'rk1', 'base_info:name', 'base_info:age'
获取lagou表中row key为rk1,base_info、extra_info列族的信息
hbase(main):010:0> get 'lagou', 'rk1', 'base_info', 'extra_info'
或者
hbase(main):011:0> get 'lagou', 'rk1', {COLUMN => ['base_info', 'extra_info']}
或者
hbase(main):012:0> get 'lagou', 'rk1', {COLUMN => ['base_info:name',
'extra_info:address']}
获取表中row key为rk1,cell的值为wang的信息
get 'lagou', 'rk1', {FILTER => "ValueFilter(=,
'binary:wang')"}
获取表中row key为rk1,列标示符中含有a的信息
get 'lagou', 'rk1', {FILTER => "
(QualifierFilter(=,'substring:a'))"}
查询lagou表中的所有信息:
scan 'lagou'
查询表中列族为 base_info 的信息:
hbase(main):001:0> scan 'lagou', {COLUMNS => 'base_info'}
hbase(main):002:0> scan 'lagou', {COLUMNS => 'base_info', RAW => true, VERSIONS
=> 3}
## Scan时可以设置是否开启Raw模式,开启Raw模式会返回包括已添加删除标记但是未实际删除的数据
## VERSIONS指定查询的最大版本数
指定多个列族与按照数据值模糊查询:
查询lagou表中列族为 base_info 和 extra_info且列标示符中含有a字符的信息
hbase(main):001:0> scan 'lagou', {COLUMNS => ['base_info', 'extra_info'], FILTER
=> "(QualifierFilter(=,'substring:a'))"}
rowkey的范围值查询(非常重要)
查询lagou表中列族为base_info,rk范围是[rk1, rk3)的数据(rowkey底层存储是字典序)
按rowkey顺序存储。
scan 'lagou', {COLUMNS => 'base_info', STARTROW => 'rk1',
ENDROW => 'rk3'}
查询lagou表中row key以rk字符开头的
hbase(main):001:0> scan 'lagou',{FILTER=>"PrefixFilter('rk')"}
更新数据值:
把lagou表中rowkey为rk1的base_info列族下的列name修改为liang
put 'lagou', 'rk1', 'base_info:name', 'liang'
删除数据和表:
删除lagou表row key为rk1,列标示符为 base_info:name 的数据
> delete 'lagou', 'rk1', 'base_info:name'
指定rowkey,列名以及时间戳信息进行删除
删除lagou表row key为rk1,列标示符为base_info:name的数据
delete 'lagou', 'rk1', 'base_info:name',1600660619655
删除 base_info 列族
alter 'lagou', 'delete' => 'base_info'
删除lagou表数据
truncate 'lagou'
删除lagou表
#先disable 再drop
hbase(main):036:0> disable 'lagou'
hbase(main):037:0> drop 'lagou'
#如果不进行disable,直接drop会报错
ERROR: Table user is enabled. Disable it first.

HBase JAVA  API:

<dependencies>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.3</version>
<scope>test</scope>
</dependency>
</dependencies>

创建连接:

package com.lagou.hbase.client;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
public class HbaseClientDemo {
Configuration conf = null;
Connection conn = null;
@Before
public void init() throws IOException {
//获取一个配置文件对象
conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "linux121,linux122");
conf.set("hbase.zookeeper.property.clientPort", "2181");
//通过conf获取到hbase集群的连接
conn = ConnectionFactory.createConnection(conf);
}
//释放连接
 @After
public void realse() {
if (conn != null) {
try {
conn.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

 

 

创建表:

 //创建一张hbase表
 @Test
public void createTable() throws IOException {
//获取HbaseAdmin对象用来创建表
HBaseAdmin admin = (HBaseAdmin) conn.getAdmin();
//创建Htabledesc描述器,表描述器
final HTableDescriptor worker = new HTableDescriptor(TableName.valueOf("worker"));
//指定列族
worker.addFamily(new HColumnDescriptor("info"));
admin.createTable(worker);
System.out.println("worker表创建成功!!");
}

 

插入数据:

 //插入一条数据
 @Test
public void putData() throws IOException {
//需要获取一个table对象
final Table worker = conn.getTable(TableName.valueOf("worker"));
//准备put对象
final Put put = new Put(Bytes.toBytes("110"));//指定rowkey

put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("addr"), Bytes.toBytes("beijing"));
//插入数据,参数类型是put
 worker.put(put);
//准备list<puts>,可以执行批量插入
//关闭table对象
 worker.close();
System.out.println("插入数据到worker表成功!!");
}

 

查询数据:

//查询数据
 @Test
public void getData() throws IOException {
//准备table对象
final Table worker = conn.getTable(TableName.valueOf("worker"));
//准备get对象
final Get get = new Get(Bytes.toBytes("110"));
//指定查询某个列族或者列
get.addFamily(Bytes.toBytes("info"));
//执行查询
final Result result = worker.get(get);
//获取到result中所有cell对象
final Cell[] cells = result.rawCells();
//遍历打印
for (Cell cell : cells) {
final String rowkey = Bytes.toString(CellUtil.cloneRow(cell));
final String f = Bytes.toString(CellUtil.cloneFamily(cell));
final String column = Bytes.toString(CellUtil.cloneQualifier(cell));
final String value = Bytes.toString(CellUtil.cloneValue(cell));
System.out.println("rowkey-->" + rowkey + "--;cf-->" + f + "---;column--->" + column + "--;value-->" + value);
}
worker.close();
}

删除数据:

 //删除一条数据
 @Test
public void deleteData() throws IOException {
//需要获取一个table对象
final Table worker = conn.getTable(TableName.valueOf("worker"));
//准备delete对象
final Delete delete = new Delete(Bytes.toBytes("110"));
//执行删除
 worker.delete(delete);
//关闭table对象
 worker.close();
System.out.println("删除数据成功!!");
}

 

 

通过Scan全表扫描:

/**
* 全表扫描
*/
@Test
public void scanAllData() throws IOException {
HTable teacher = (HTable) conn.getTable(TableName.valueOf("teacher"));
Scan scan = new Scan();
ResultScanner resultScanner = teacher.getScanner(scan);
for (Result result : resultScanner) {
Cell[] cells = result.rawCells();//获取改行的所有cell对象
for (Cell cell : cells) {
//通过cell获取rowkey,cf,column,value
String cf = Bytes.toString(CellUtil.cloneFamily(cell));
String column = Bytes.toString(CellUtil.cloneQualifier(cell));
String value = Bytes.toString(CellUtil.cloneValue(cell));
String rowkey = Bytes.toString(CellUtil.cloneRow(cell));
System.out.println(rowkey + "----" + cf + "--" + column + "---"
+ value);
}
}
teacher.close();
}

通过startRowKey和endRowKey进行扫描:

//指定scan 开始rowkey和结束rowkey,这种查询方式建议使用,指定开始和结束rowkey区间避免全表扫描
@Test
public void scanStartEndData() throws IOException {
//准备table对象
final Table worker = conn.getTable(TableName.valueOf("worker"));
//准备scan对象
final Scan scan = new Scan();
//指定查询的rowkey区间,rowkey在hbase中是以字典序排序
scan.setStartRow(Bytes.toBytes("001"));
scan.setStopRow(Bytes.toBytes("004"));
//执行扫描
final ResultScanner resultScanner = worker.getScanner(scan);
for (Result result : resultScanner) {
//获取到result中所有cell对象
final Cell[] cells = result.rawCells();
//遍历打印
for (Cell cell : cells) {
final String rowkey = Bytes.toString(CellUtil.cloneRow(cell));
final String f = Bytes.toString(CellUtil.cloneFamily(cell));
final String column = Bytes.toString(CellUtil.cloneQualifier(cell));
final String value = Bytes.toString(CellUtil.cloneValue(cell));
System.out.println("rowkey-->" + rowkey + "--;cf-->" + f + ";column--->" + column + "--;value-->" + value);
}
}
worker.close();
}

 

版权声明
本文为[wangheng1409]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/wanghzh/p/15270164.html

  1. 国内一线互联网公司面试题汇总,2021年大厂Java岗面试必问,
  2. 啃完吃透保你涨薪5K,熬夜整理小米Java面试题,
  3. 和字节跳动大佬的技术面谈,Redis成神之路电子版教程已问世,
  4. Le terme professionnel le plus complet de l'histoire des micro - services interview 50 questions, Byte Jumping Java post Classic interview vrai problème,
  5. After using mybatisplus, I haven't written SQL for a long time
  6. [springboot2 starts from 0] how to write a springboot application?
  7. Huawei cloud guassdb (for redis) released a new version, and the two core features were officially unveiled
  8. 和字節跳動大佬的技術面談,Redis成神之路電子版教程已問世,
  9. 啃完吃透保你漲薪5K,熬夜整理小米Java面試題,
  10. Avec l'interview technique du gigolo, le tutoriel électronique redis est sorti.
  11. Après avoir mangé, assurez - vous d'augmenter votre salaire de 5K et de rester debout tard pour trier les questions d'entrevue Java de millet.
  12. Résumé des questions d'entrevue pour les entreprises Internet nationales de première ligne, qui doivent être posées lors de l'entrevue d'emploi Java de la grande usine en 2021,
  13. Le tri des crachats de sang, la force de l'équipe Tencent pour créer le tutoriel d'introduction au printemps,
  14. Java and scala concurrency Fundamentals
  15. Analysis of java thread source code based on Hotspot
  16. 國內一線互聯網公司面試題匯總,2021年大廠Java崗面試必問,
  17. Introduction au module de contrôle de Connexion MySQL
  18. 大厂高级测试面试题,Java面试基础技能罗列,
  19. Comprendre l'architecture sous - jacente d'InnoDB en exécutant une instruction
  20. Chargeur de classe 1 Tomcat
  21. 小白也能看懂的dubbo3应用级服务发现详解
  22. SpringBoot异步使用@Async原理及线程池配置
  23. Questions d'entrevue de test avancé de Dachang, liste des compétences de base de l'entrevue Java,
  24. SpringBoot异步使用@Async原理及線程池配置
  25. Springboot utilise asynchrone le principe @ async et la configuration du pool de threads
  26. Détails de la découverte du Service d'application Dubbo 3 que Xiaobai peut également comprendre
  27. Springboot utilise asynchrone le principe @ async et la configuration du pool de threads
  28. 如何强大且优雅的搞定Linux文件系统,算法题 JVM,
  29. 太牛了,阿里P7架构师带你看透maven的来龙去脉,
  30. Oracle central et Oracle décentralisé
  31. java JavaBean
  32. Java wrapper type
  33. Java super keyword
  34. Java static keyword
  35. Java this keyword
  36. Java interface
  37. 太牛了,阿裏P7架構師帶你看透maven的來龍去脈,
  38. C'est génial, l'architecte Ali p7 vous montre à travers Maven.
  39. Comment traiter le système de fichiers Linux avec puissance et élégance, algorithme JVM,
  40. Java + SSM Social Insurance Pension System for Computer Graduation Design
  41. Usage of Java scanner
  42. Java inheritance
  43. Java method review
  44. java JVM
  45. Java Basics
  46. Java file operation object IO stream
  47. Java console reads multi character input and output
  48. Java simple array sorting
  49. In addition to MySQL master-slave, you have another choice, Galera
  50. Configuration standard dockerfile et docker-composer.yml
  51. 字节大神强推千页PDF学习笔记,2021Java开发学习路线,
  52. 字节大牛耗时八个月又一力作,靠这份Java知识点PDF成功跳槽,
  53. 字节大牛教你手撕Java学习,最新大厂程序员进阶宝典,
  54. Comment l'automne est - il beau?Ces 24 ensembles de modèles d'automne et d'hiver sont grands, minces et vieillissants
  55. 字節大牛教你手撕Java學習,最新大廠程序員進階寶典,
  56. 字節大牛耗時八個月又一力作,靠這份Java知識點PDF成功跳槽,
  57. Byte Bull vous apprend à déchiqueter Java à la main, le dernier dictionnaire avancé des programmeurs de grandes usines,
  58. Byte Bull a pris huit mois à travailler dur et a réussi à changer d'emploi avec ce PDF Java Knowledge point.
  59. Byte God Push 1000 pages PDF Learning notes, 2021 Java Development Learning route,
  60. Five minutes to understand MySQL index push down