HBase

HBase(Hadoop Database)基于Google的BigTable论文,依赖HDFS进行存储。适合存储大体量数据。HBase是高可靠性(数据安全)、高性能(存取效率)、面向列、可扩展的分布式存储系统,实现利用廉价设备搭建大规模集群。

HBase是面向列的存储系统。适用于存放半结构化或者非结构化的数据。

  • 结构化:每条记录具备相同的数据结构,类似于类和对象关系

  • 非结构化的数据:数据之间不需要保持相同的属性,可以自行定义属性(KV)

  • 半结构化的数据:介于两者之间

HBase数据结构

一个表中使用四个维度定义一个数据

  • RowKey

    • 一条记录的ID,用来唯一标明对应列族的数据

    • RowKey默认为64K长度,长度可动态分配

    • RowKey默认按照字典序进行排序(例如:10 ,111,12)

  • Column Family

    • 列的集合体,通过列族能够找到对应的子列

    • 一个RowKey一般少于3个列族,提高HRegion的查询效率

    • 建表时必须定义好列族

  • Qualifier

    • 子列/属性,相当于数据的key

    • 隶属于对应的列族,列可以动态添加

    • 查询时,通过rowkey找到列族,通过列族在查找子列

    • 在一个列族内可以维护大量的KV数据存储(基于版本与合并)

  • Timestamp

    • 事件戳 、数据版本

    • 不同列族具备不同的时间版本

    • 时间戳默认为系统的毫秒数

    • hbase能够默认存储若干版本的数据

      • 每条数据都具备对应的时间戳

      • 数据以时间戳为标准降序排列,使得最新的数据优先查出

      • 可自定义version存储版本数目

      • 可以自定义Timestamp的格式,需要注意防止重复版本

    • 原理:DFS不支持数据修改,数据修改实际执行添加操作,导致每个数据都存在若干以时间戳来区分的历史数据版本

    • 触发数据清除:超过版本数(修改次数),超过存储的时间(数据有效期)

  • Cell

    • 四个维度最终定位到的数据

    • 存储在HBase中的数据无类型,均为字节数组,通过偏移量定位

HBase系统架构

  • Client

    • 访问方式:shell,java,MR

    • 向HBase服务器发送命令

      DDL 数据库定义语言——向HMaster发送

      DML 数据库管理语言——向ZK发送

      DQL 数据库查询语言——向ZK发送

    • 保留查询结果作为缓存数据,待以后相同查询时调用

  • Zookeeper

    • Zookeeper是一个集群,监控HMaster状态并控制HMaster的主从切换,任何时候只有一个主HMaster

    • 存放表结构信息,在表创建时就记录下来

      • 避免HMaster故障丢失数据

      • 表结构信息共享给主从HMaster

    • 监听HRegionServer上/下线

    • 保存每个Region的地址

    • Zookeeper用于辅助client执行DML与DQL

      使用表结构与Region地址数据,提高数据访问效率

  • HMaster

    • 监控HRegionServer

      • 负载均衡

      • 表创建

      • Region分裂时,分配不同的HRegionServer

      • HRegionServer故障时,任务切换

    • 处理DDL请求,调度空闲(内存,空间)HRegionServer执行DDL

  • HRegionServer

    • 管理节点中的所有Region

    • 监控HRegion状态与大小

      • 单个HRegion大小达到阈值(10G)后拆分

      • 采用相对等分切分HRegion,标准切分后两侧数据完整

      • 新分出的Region交给HMaster分配给其他HRegionServer

    • 直接处理客户端的IO请求

  • HLog

    • HLog基于write ahead log(提前写入日志)模型

    • 每个HRegionServer都对应一个HRegionServer,内部的HRegion共享这个HLog

    • 检查点:触发执行内存转硬盘(dfs)后,HLog会记录检查点,新存入的数据都在检查点之后。

    • 若HRegion宕机,HRegionServer将硬盘数据交给其他HRS节点管理,新节点执行检查点后的日志,实现故障切换

  • HRegion

    • 一个表对应多HRegion——每个HRegion只对应一个表

      • 默认表创建时只分配一个HRegion

      • HRegion到达10G后自动切分,使得多个HRegion对应一个表

      • 可以在建表时自定义多个HRegion,避免反复切分操作和热点操作

    • HRegion内部是有序的

      • 按照 Rowkey 字典序排列

      • 切分HRegion时,两个HRegion有序,HRegion内部也有序

  • Store

    • 一个HRegion由多个Store构成

    • 一个Store对应一个列族——一个列族可能有多个Store

    • 通过Store的维护能够实现自动维护列族内大量的KV数据

    • 每个Store由 1个MemStore(内存)+n个StoreFile(硬盘文件)构成

    • 数据存储过程为:

      • 数据写入前先写日志,再将数据存入内存

      • 内存占用或日志条数达到阈值后,触发内存写出到硬盘

      • 写出前修改日志中该数据的状态,后将数据转存到硬盘中

      • 每次转存触发都会生成一个StoreFile文件,并在日志中生成检查点

      • 上述的两次日志都是基于HLog实现

    • MemStore 基于内存的数据存储,提高数据的插入速度

    • StoreFile 基于硬盘的数据存储

    • 对于Store中数据的增删改,都默认作为添加数据处理,对原数据只是加了标识,新旧数据都存放在Store中

    • StoreFile的合并

      • 随之MemStore写出增多,StoreFile文件变多,需要进行合并

        • MinorCompaction小合并,10个相邻的StoreFile相互合并

        • MajorCompaction大合并

          • 合并Store中所有StoreFile,并将失效数据剔除

          • 失效数据包括:删除的数据,查过有效期,查过版本的数据

          • 占用大量系统资源,需要手动触发

HBase数据存取流程

DDL 定义表

  • client向HMaster发送任务

  • HMaster

    • 检查创建表的权限,名称,表空间等信息

    • 寻找合适的HRegionServer执行创建操作

  • HRegionServer执行完成后,Zookeeper保存如下内容

    • 表结构信息

    • Region与HRegionServer的对应关系

DQL 查询

  1. 客户端发送请求查询数据到KZ集群

  2. KZ根据-root-数据找到.meta.表,meta根据查询请求找到所需要的Region及其在所在的RegionServer,建立与RegionServer的链接

  3. Region内部数据有序(基于rowkey)采用二分查找直接找到数据所有的store(store对应列族)

  4. 最终在列族的子列与时间戳定位到cell

    注:为了效率尽量将相近属性的列放在一个列族中便于查找

HBase快速的定位到Region与HRegionServer的方案:

.meta.

存放的都是table与region与regionserver的对应关系;能够切分,降低访问压力

  • rowkey 表,起始rowkey值,时间戳

  • info:regioninfo 起始rowkey值,结束rowkey值,列族

  • info:server 对应的HRegionServer

region info:regioninfo info:server
student,10,163057 s:10 e:19 family list regionserver111
student,20,163056 s:20 e:29 family list regionserver222
student,30,163054 s:30 e:39 family list regionserver888

-root-

存储.meta.各切片的位置,大小可控,直接存放子ZK中

DML 增删改

数据通过HRegion存入到HFile中作为增加数据,在HFile合并时才对数据进行真实处理

DML-快速插入数据

依据HFile的文件格式将数据存储到HDFS上,直接生成Hlog,将Hlog存到Hbase中进行管理。

直接跳过HRegion的存储操作建立HFile

HFile分为六个部分:

  • Trailer段 其长度恒定,记录下面每个段的偏移量,找到下面各段的位置

  • Data Block 段 保存表中的数据,这部分可以被压缩;

  • Meta Block 段 用户自定义的kv对,可以被压缩。

  • Data Block Index 段 Data Block的索引,每条索引的key是被索引的block的第一条记录的key。

  • Meta Block Index段 Meta Block的索引

  • File Info 段 Hfile的元信息,不被压缩,用户也可以在这一部分添加自己的元信息

HFile使用三级索引结构:首先读取Trailer来获取Data Block Index位置,将Data Block Index读取到内存中,检索DBI的key来找到目标数据的索引,再通过索引找到Data Block中的具体数据。

环境搭建

  • 前提

    • Hadoop环境健康

    • Zookeeper集群正常

  • 上传解压HBase压缩包

    • tar -zxvf hbase-0.98.12.1-hadoop2-bin.tar.gz

    • mv hbase-0.98.12.1-hadoop2 /opt/sxt/

    • mv hbase-0.98.12.1-hadoop2 hbase-0.98

  • 开始修改配置文件

    • 配置RegionServer

      • vim regionservers

        • node1

        • node2

        • node3

    • 配置备用节点

      • backup-masters不要和主节点在一起

        • vim backup-masters

        • node2

    • 配置Hbase环境

      • vim hbase-env.sh

        • exprot JAVA_HOME=/usr/java/jdk1.7.0_67

        • export HBASE_MANAGES_ZK=false

    • 配置Hbase的核心配置文件

      • vim hbase-site.xml

        注:hbase.rootdir的值与hdfs的集群名一致

        hdfs://集群名/hbase

        该路径也就是Hbase中dfs中的存放路径

          <property>
         <name>hbase.rootdir</name>
         <value>hdfs://shsxt/hbase</value>
         </property>
         <property>
         <name>hbase.cluster.distributed</name>
         <value>true</value>
         </property>
         <property>
        <name>hbase.zookeeper.quorum</name>
         <value>node1:2181,node2:2181,node3:2181</value>
        </property>
    • 拷贝hdfs-site.xml到habse的配置目录下

      • cp /opt/sxt/hadoop-2.6.5/etc/hadoop/hdfs-site.xml /opt/sxt/hbase-0.98/conf/

  • 拷贝Hbase到其他主机

    • scp -r /opt/sxt/hbase-0.98/ root@node2:/opt/sxt/

      • scp -r /opt/sxt/hbase-0.98/ root@node3:/opt/sxt/

    • 修改环境变量

      • vim /etc/profile

      • export HBASE_HOME=/opt/sxt/hbase-0.98

        • 将HBASE_HOME/bin载入PATH

    • scp /etc/profile root@node2:/etc/profile

      • scp /etc/profile root@node3:/etc/profile

      • [123] source /etc/profile

  • 启动集群

    • zkServer.sh start

      • start-all.sh

    • [3] yarn-daemon.sh start resourcemanager

  • 启动HBase

    • [1] start-hbase.sh

    • 网络访问

    • 集群关闭

      [1] stop-hbase.sh

      [1] stop-all.sh

      [3] yarn-daemon.sh stop resourcemanager

      [1-3] zkServer.sh stop

  • 拍摄快照

HBase的shell

参考https://cloud.tencent.com/developer/article/1336648

系统相关

help '命令' 查看某个命令的帮助文档

进入系统:hbase shell

退出系统:quit ,exit

HBase中删除需要按住ctrl键

涉及字符串注意用单引号

表的使用:'命名空间:表' 若无命名空间名则默认default

命名空间及表

  • 查看命名空间 list_namespace

  • 创建命名空间 create_namespace 'jay'

  • 删除命名空间 drop_namespace 'sxt'

  • 查看表指定命名空间的表 list_namespace_tables 'shsxt'

  • 创建表

    • create 'jay:java', 'teacher',{NAME => 'room', VERSIONS => 3}

      在jay命名空间下创建java表,列族包括teacher和room,room版本为3

    • create 'grade','clazz', {SPLITS => ['g','n']}

      在默认命名空间下创建grade表,列族clazz,预先基于g,n分隔3个HRegion

  • 查看表状态:desc 'jay:java' jay空间下的java表

  • 禁用 disable 'jay:java' 启用 enable 'jay:java'

  • 删除表 drop 'jay:java' 需要预先禁用表才能删除表

以下默认省略命名空间

  • 扫描

    scan '表' {COLUMNS=> '列族',STARTROW => '起始rowkey',STOPROW => '结束rowkey',LIMIT=>显示几条, VERSIONS=>显示几个版本}

    scan '表', {COLUMNS => ['列族1:子列', '列族2']} 查询出指定的列族和列

    scan '表', 'rowkey', {FILTER => "ValueFilter(=, 'binary:值')"} 查看值为指定值的列

    scan '表', FILTER=>"PrefixFilter('xxx')" 指定表的列族前缀为xxx

    scan '表', FILTER=>"ColumnPrefixFilter('xxx') " 指定表的列前缀为xxx

    scan '表', {COLUMNS => '列族', RAW => true} 将删除数据也显示出来

    scan '表', FILTER=>"ColumnPrefixFilter('yyy') AND ValueFilter(=,'substring:xxx')" 包含xxx字符串的类

    { }与" "可以替换使用

  • 指定查找

    get '表', 'keyrow'

    get '表', 'keyrow', '列族:列'

    get 'person', '0001', {COLUMNS => 'name:firstname', VERSIONS => 3}

    指定查3个版本

    get 'person', '0001', {COLUMN => 'name:first', VERSIONS => 3, TIMERANGE => [1392368783980, 1392380169184]}

    限定在某些时间戳内

增删改

插入数据: put '命名空间:表', 'rowkey', '列族:子列', '值'

删除数据: delete '命名空间:表', 'rowkey', '列族:子列' 可以只写前面一部分来扩大删除范围

清空表 truncate '命名空间:表' 截断不可逆

HBase的表设计

基于rowkey有序性,使得数据的主键key变为有序

基于HBase对列族的维护,在列族内存储大量键值对

通话记录

数据需求:

拉取某个号码某一段事件的所有记录

主叫号码 被叫号码 通话日期 通话时长 类型
18001128266(电信) 18081293926(移动) 1568961597025 36 1
18001128266 18081293927 1568962597025 66 2
18001128266 18081293928 1568963597025 88 1
18001128265 18081293929 1568963397025 12 1

存储方案

rowkey:本机号码+通话日期+随机标识位 其余通过列族存储

原理:基于rowkey实现快速定位

微博相互关注

亿级数据x亿级数据

  • rowkey:用户ID

  • 列族:info 用户相关信息

  • 列族:关注人 子列的key为关注人ID,value为null

  • 列族:被关注人 子列的key为被关注人ID,value为null

处理关注和取关:根据ID快速定位用户,级联修改 关注用户的(列族:关注人)、被关注用户的(列族:被关注人)

原理:基于列族的维护,在列族内存储巨量键值对。

微博信息

微博:发送人,文本,多媒体,时间,发送端

  • rowkey 发送人_发送时间

  • 列族: info

  • 列族: 点赞

  • 列族: 转发

  • 列族:多媒体 。。。列族

拆分为多个表,避免列族过多影响查询效率

weibo-people表

  • rowkey:发送人ID_发送毫秒数+标识位

  • 列族:文本info

  • 列族:多媒体info

weibo-点赞表

  • rowkey:发送人ID_发送毫秒数+标识位

  • 列族:点赞人

  • 列族:转发人 key为用户ID ,value为转发文本

原理:创建多个表,将列族分配到不同的表中,表具备相同的keyrow。

HBase优化

表设计优化

  1. Pre-Creating Regions预分区

    • 问题:hbase在创建一个表时默认值创建一个Region分区,待regin到达阈值后切分,导致该表的所有请求都会集中到一个RegionServer中,降低性能。

    • 方案:在创建表时建立多个Region分区,分区按照指定key划分,之后rowkey根据key存入不同分区,实现负载均衡。

    • 系统自动对n个key排序,分配(n+1)个区,第一个区范围为(-∞,最小key],中间(key1,key2],最后一个分区为(最大key,+∞)

    • 命令方式:create '表','列族', {SPLITS => ['g','n']} 按照g和n分为3个分区

    • 代码方式:二维数组方式,具体见代码实现部分

  2. Rowkey

    • Rowkey是以byte数组存储的部定长字符串,最大长度64K。

    • Rowkey是按字典序排列的,一般将其设置为定长的,将时间戳作为Rowkey的一部分,便于将相邻时间的数据一起查出。

    • 优化规则

      越短越好(每条记录中都存了rowkey的值,大量冗余)

      根据业务需求设置rowkey,以提高查询效率为考虑准则

      对于存在访问过于集中的rowkey端,为了避免热点产生,需要对rowkey散列处理:取反方式,hash方式

    • 基于Rowkey的查找方式

      通过单个rowkey的get查找,直接定位单个rowkey

      通过指定rowkey范围的scan扫描,设置startRowKey和endRowKey

      全表scan扫描,效率低

  3. Column Family

    一张表中不要设置超过3个列族

    原因包括:

    1 当一个列族的数据flush时(men写出到storefile时),相邻的列族也会被关联触发,HRS同时执行多个IO操作,导致效率降低

    2 执行查找时,rowkey对应过多的列族,导致查找时必须遍历所有列族的storefile,storefile过多查询缓慢

  4. Compact & Split (StoreFile/Hfile的合并与切分)

    • 合并

      • 问题:StoreFile为memony写出的硬盘中的数据,每次写出的StoreFile内部都是有序的,而StoreFile文件之间无顺序。因此在查询数据时需要遍历每个StoreFile,存在效率问题。

      • 合并方式

        minor compact 相邻若干StoreFile合并,可以指定数量

        major compact HR中的所有StoreFile合并,同时处理标记数据(删除的数据,version过期数据,有效期过期数据),这种方式占用资源较大一般需要手动触发

      • 效果:

        能够获取到有序的大数据量的StoreFile,降低IO压力,数据占用空间压缩。

    • 切分

      • StoreFile大于阈值后,StoreFile将被切分

    • 切分和合并的阈值可以手动设置,使得系统中的StoreFile大小均衡且合并切分次数较小

  5. In Memory

    在RS中设置内存共享区域,创建表时将表存入memory中,增加缓存的命中率

  6. 关于数据失效

    Max Version:设置表的最大版本数

    Time To Live:设置表中数据的有效时间

数据写入优化

  • 打开多个表链接增加写入速度

    为了减小创建链接开销,使用pool技术

  • auto flush 批处理时用一个事务完成所有操作,HTable.setAutoFlush(false)

  • wal Flag 不写日志存储,适用于不重要的数据,提升存储速度牺牲数据安全性

  • writeBuffer 设置客户端刷出缓存,当buffer的数据量超过设定值client将数据flush到服务端,减少服务端重复IO

  • 单线程批量插入数据,HTable.put(List<Put>),通过list批量插入

  • 多线程批量插入数据,HTable线程不安全,需要多个htable连接才能使用多线程

参考:https://www.cnblogs.com/panfeng412/archive/2012/03/08/hbase-performance-tuning-section2.html

数据读取优化

  • 创建多个htable,增加数据的吞吐量,为了减小创建链接开销,使用pool技术,与写入过程类似

  • 单线程批量读取数据,通过list批量读取

  • 多线程批量读取数据,HTable线程不安全,需要多个htable连接才能使用多线程

  • Blockcache

    • 读缓存,设置在每个HRS中,HRS内的所有HR共享

    • Blockcache设置了类似于LRU的算法,将不常用的数据清理出缓存,保证数据不断更新,提高Blockcache的命中率

  • MemStore

    • 每个HR对应一个MemStore与多个FileStore

    • 数据存入HR时,先存入MemStore,在MemStore达到阈值后Flush到FileStore中。

    • 阈值一般设置为:单MemStore占用满128M;全局内存占用超过90%,全局MemStore刷出

    • 数据存入HR中直接加快的数据的写入速度,也增加了(flush前)写入数据的读取速度

  • MemStore与Blockcache分配

    • 在HRS节点中内存存在物理限制,需要分配Blockcache与MemStore的占用比

    • 默认Blockcache * 1+memstore * n < heapsize * 0.8

    • 要求相应速度快,增加Blockcache占比

    • 要求写入速度快,增加MemStore占比

  • 数据查询过程说明

    1. 从每个Region的memstore查询数据

    2. 若memstore无对应数据,查询Blockcache数据

    3. 若Blockcache无对应数据,查询DFS的数据

    4. 若从DFS找到数据,将数据存入Blockcache,并将数据返回Client

HBase代码实现

jdbc实现

将HBase115个jar与测试jar导入

初始化init与关闭

//初始化主要过程
//创建配置文件
Configuration conf=new Configuration();
//设置zookeeper集群及rpc地址(地址在hadoop的core-site.xml的配置中)
conf.set("hbase.zookeeper.quorum","node1:2181,node2:2181,node3:2181");
//获取数据库连接
HBaseAdmin hBaseAdmin=new HBaseAdmin(conf);
//获取表连接
Htable htable=new Htable(conf,"table_name");
//关闭代码
hBaseAdmin.close();
hTable.close();

关于扫描查询

  1. 设置扫描器

    Scan scan =new Scan();

    • 对于过滤查询,设置过滤器,一般使用行过滤器

      RowFilter filter1=new RowFilter (CompareFilter.CompareOp.比较类型常量,比较对象);(RowFilter实现自Filter,可以使用Filter的多态)

      上述比较对象包括:

      new BinaryComparator("rowkey".getBytes()) 行主键比较对象

      new RegexStringComparator(".*aaa") 正则比较对象(获取结尾为aaa的行)

      new SubstringComparator("xxx") 包含有xxx子串的row的比较对象

      new BinaryPrefixComparator("xxx".getBytes()) 开头为xxx的行的比较对象

    • 对于全表查询,直接设置全表查询范围

      • scan.setStartRow(Bytes.toBytes("start_rowkey"));

      • scan.setStopRow(Bytes.toBytes("stop_rowkey"));

  2. 将过滤器设置到扫描器中

    scan.setFilter(filter1);

  3. 执行查询,并遍历获取结果

    • 将扫描器设置到表连接中,以获取查询结果ResultScanner

    • 通过增强for遍历ResultScanner获取每个ResultRow

    • 遍历ResultRow,得到每一个cell元素

    • 通过CellUtil从cell中解析出值,列,列族,rowkey

    //载入扫描器,执行查询,并获取结果
    ResultScanner rowResults= hTable.getScanner(scan);
    for(Result result: rowResults){
       //从行数据中直接获取cells
    List<Cell> cells=result.listCells();
       for (Cell cell : cells) {
           //CellUtil从cell中解析出:值,列,列族,rowkey
           Bytes.toString(CellUtil.cloneValue(cell));
           Bytes.toString(CellUtil.cloneQualifier(cell));
           Bytes.toString(CellUtil.cloneFamily(cell))
           Bytes.toString(CellUtil.cloneRow(cell));
      }
    }

关于get查询数据

  • 创建get对象

    Get get=new Get("rowkey".getBytes());

  • 指定列族和列

    get.addColumn("family".getBytes(),"qualifier".getBytes());

  • 执行查询

    Result result=hTable.get(get);

  • 通过CellUtil解析result

关于单条插入

  • 创建Put对象,通过rowkey构造

    Put put=new Put("rowkey".getBytes());

  • 置入列族,列,值(一次插入,可以同时置入多个cell)

    put.add("family".getBytes(),"qualifier1".getBytes(),"value1".getBytes());

    put.add("family".getBytes(),"qualifier2".getBytes(),"value2".getBytes());

  • 通过表连接执行插入

    hTable.put(put)

关于批量插入

设置Put对象的list容器,根据插入的数据创若干Put对象,存入list中,将list容器置入表连接

List< Put> puts = new ArrayList();
......
hTable.put(puts);

关于表创建

创建表对象,列族对象,通过数据库连接创建表

//创建表对象
HTableDescriptor htd= new HTableDescriptor(TableName.valueOf("table_name"));
//创建列族对象
HColumnDescriptor c1=new HColumnDescriptor("column_famliy");
HColumnDescriptor c2=new HColumnDescriptor("column_famliy2");
//设置列族属性(最大保留版本数)
c1.setMaxVersion(2);
//将列族对象载入表对象
htd.addFamily(c1);
htd.addFamily(c2);
//通过hbase数据库,执行创建
hBaseAdmin.createTable(htd);

设置预分区表

需要说明的是,若指定n个key,则划分了n+1个分区。由于字典序通过选择省略第一个key(最小值)执行分区

HTableDescriptor htd= new HTableDescriptor(TableName.valueOf("table_name"));
HColumnDescriptor c=new HColumnDescriptor("column_famliy");
htd.addFamily(c);
//设置与分区数组,由于只接受byte数据,需要将分区节点转为字节数组,存入二维数组中。
String[] keys = "11,13,115".split(",");
byte[][] range=new byte[keys.length - 1][];
for(int i;i<keys.length;i++){
   range[i-1]=keys[i].getByte;
}
//将分区信息与表数据存入其中
hBaseAdmin.createTable(htd,range);

HBase与MR

  • 将HBase115个jar与Hadoop121个jar导入

  • 在conf资源文件夹中导入Hadoop4个xml配置

  • 在job类,将MR置入配置对象中载入hbase配置,,配置具体数据在hbase的hbase-site.xml文件中

    conf.set("hbase.zookeeper.quorum", "node1:2181,node2:2181,node3:2181")

HBase作为源数据

  • job类

    • 设置scan对象,将scan结果作为map的输入

    • TableMapReduceUtil对象设置map,(org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil)

      //设置扫描器
      Scan scan = new Scan();
      scan.setStartRow("A".getBytes());
      scan.setStopRow("ZZ".getBytes());
      //设置reduce,参数为:job名,扫描器,map类,map输出key类型,map输出value类型,job对象
      TableMapReduceUtil.initTableMapperJob("job_name",scan,WyMapper.class,Text.class, Text.class, job);
  • map类

    • 继承TableMapper类(org.apache.hadoop.hbase.mapreduce.TableMapper)范型给出输出KV的类型

    • 重写map,内部通过result获取cells(reuslt表示一个rowkey中所取出的数据)

      也可以通过指定列族和列直接获取值

      //继承TableMapper类
      public class MyMapper extends TableMapper<Text, Text> {
      //重写map方法
      @Override
      protected void map(ImmutableBytesWritable key, Result value, Mapper<ImmutableBytesWritable, Result, Text, Text>.Context context) throws IOException, InterruptedException {
      //通过value获取所有Cell,再通过cell取出(rowkey,列族,列,值)
      List<Cell> list = value.listCells();
      for (Cell cell : list) {
      String rowkey = Bytes.toString(CellUtil.cloneRow(cell));
      String family = Bytes.toString(CellUtil.cloneFamily(cell));
      String qualifier = Bytes.toString(CellUtil.cloneQualifier(cell));
      String value = Bytes.toString(CellUtil.cloneValue(cell));
      //写出数据
      context.write(new Text(qualifier), new Text(value));
      }
      }
      }

HBase作为结果存放

  • Job类中,通过TableMapReduceUtil设置reduce,使得reduce结果输出到hbase中

    TableMapReduceUtil.initTableReducerJob("job_name",MyRedce.class,job)

  • 在Reduce类中

    • reduce继承TableReducer(org.apache.hadoop.hbase.mapreduce.TableReducer),重写reduce方法

    • 通过put对象存入写出数据,再通过上下文写出,key置为null

      //继承TableReducer类,指定reduce输入数据类型以及reduce输出类型
      public class MyReducer extends TableReducer<Text,IntWritable,ImmutableBytesWritable>{
      //重写reduce方法
      @Override
      protected void reduce(Text key, Iterable<IntWritable> values, Reducer<Text, IntWritable, ImmutableBytesWritable, Mutation>.Context context) throws IOException, InterruptedException {
      //执行普通reduce操作
      int count = 0;
      Iterator<IntWritable> iterator = values.iterator();
      while (iterator.hasNext()) {
      count += iterator.next().get();
      }
      //使用put插入数据
      Put put=new Put("Harry".getBytes());
      put.add("info".getBytes(),key.getBytes(),String.valueOf(count).getBytes());
      //通过上下文写出,执行put操作,注意key为null
      context.write(null,put);
      }
      }

Protobuf的安装与使用

Protocol Buffers 是一种轻便高效的结构化数据存储格式,用于对hbase 的Hfile进行压缩,压缩过程是将文件的高频词使用特定字符引用替换,减小文件的硬盘占用。

注意:压缩后的数据只能整个文件一次性读取,无法基于Hbase快速定位单个数据在文件中的位置,需要解码遍历文件内容。

安装

  • 解压 tar -zxvf protobuf-2.5.0.tar.gz

  • 添加依赖 yum install gcc-c++ -y

  • 进入解压文件执行配置安装 ./configure --prefix=/opt/sxt/protobuf/

  • 编译安装 make && make install

使用

  • 编写proto文件 xxx.proto

    package com.shsxt.util; 
    
    //创建一个消息对象
    message PhoneRecord
    {
    required string otherphone = 1;
    optional int32 time = 2;
    optional int64 date = 3;
    optional string type = 4;
    } message PhoneRecordDay
    {
    repeated PhoneRecord phoneRecord=1;
    } message PhoneRecordMonth
    {
    repeated PhoneRecordDay phoneRecordDay=1;
    }
  • 将proto文件编译成java类

    文件存入liunx,执行命令 ./protoc --java_out=/root/ Xxx.proto

    文件名就是编译后的java类名

  • 将编译后的文件加入java项目中

大数据-HBase的更多相关文章

  1. 第五章:大数据 の HBase 进阶

    本课主题 HBase 读写数据的流程 HBase 性能优化和最住实践 HBase 管理和集群操作 HBase 备份和复制 引言 前一篇 HBase 基础 (HBase 基础) 简单介绍了NoSQL是什 ...

  2. 第四章:大数据 の HBase 基础

    本课主题 NoSQL 数据库介绍 HBase 基本操作 HBase 集群架构与设计介紹 HBase 与HDFS的关系 HBase 数据拆分和紧缩 引言 介绍什么是 NoSQL,NoSQL 和 RDBM ...

  3. 大数据hbase分布式安装及其部署。

    大数据hbase分布式安装及其部署. 首先要启动Hadoop以及zookeeper,可以参考前面发布的文章. 将hbase的包上传至master节点 这里我使用的是1.3.6的版本,具体的根据自己的版 ...

  4. 大白话详解大数据HBase核心知识点,老刘真的很用心(2)

    前言:老刘目前为明年校招而努力,写文章主要是想用大白话把自己复习的大数据知识点详细解释出来,拒绝资料上的生搬硬套,做到有自己的理解! 01 HBase知识点 第6点:HRegionServer架构 为 ...

  5. 大白话详解大数据HBase核心知识点,老刘真的很用心(3)

    老刘目前为明年校招而努力,写文章主要是想用大白话把自己复习的大数据知识点详细解释出来,拒绝资料上的生搬硬套,做到有自己的理解! 01 HBase知识点(3) 第13点:HBase表的热点问题 什么是热 ...

  6. 用大白话讲大数据HBase,老刘真的很用心(1)

    老刘今天复习HBase知识发现很多资料都没有把概念说清楚,有很多专业名词一笔带过没有解释.比如这个框架高性能.高可用,那什么是高性能高可用?怎么实现的高性能高可用?没说! 如果面试官听了你说的,会有什 ...

  7. 入门大数据---Hbase是什么?

    一.Hbase是什么? Hbase属于NoSql的一种. NoSql数据库分为如下几类: Key-Value类型数据库 这类数据库主要会使用到一个哈希表,这个表有一个特定的键和一个指针指向特定的数据. ...

  8. 大数据——hbase

    进入hbase hbase shell 部分命令清单 查询服务器状态   status 查询hbase版本   version 1. 创建一个表 create 'table1', 'tab1_id', ...

  9. 大数据Hbase相关运维题

    1.启动先电大数据平台的 Hbase 数据库,其中要求使用 master 节点的RegionServer.在 Linux Shell 中启动 Hbase shell,查看 HBase 的版本信息.(相 ...

随机推荐

  1. Pr常用的键盘操作

    Pr常用的键盘操作 Shift选中切开的小段 Alt复制效果

  2. 硬核干货 | C++后台开发学习路线

    2020秋招提前批 C/C++相关开发 拿到腾讯.华为等offer 学习路线及时间安排 推荐时间为4个月,包括四部分:语言,计算机基础知识,项目基础知识,项目实践. 语言 推荐学习1个月 学习方针:视 ...

  3. ES6基础与解构赋值(高颜值弹框小案例!)

    let只作用在当前块级作用域内使用let或者const声明的变量,不能再被重新声明let不存在`变量提升` console.log(dad); var dad = '我是爸爸!';//预定义undef ...

  4. 剑指offer-面试题15-二进制中1的个数-位运算

    /* 题目: 二进制中1的个数,例如9为1001,有2位1. */ /* 思路: 算法2: 左移unsigned类型flag=1,和n做&运算,当flag移动中1的位置与n对应位置也为1时,则 ...

  5. Cenos7下指定ftp用户限制在特定目录下(亲身实践)

    好了,废话不多说.上头下来个需求,让我给别人开个ftp账户,只能访问项目的目录,不能访问项目外的目录,就算cd切换目录也不行. 开始: 第一步;安装ftp,我用的是centos7,只需敲入命令 yum ...

  6. web端常见测试

    一.登录注册功能 1.页面调转 2.tab键与enter键 3.密码加密显示,是否支持复制粘贴 4.账号密码校验 5.刷新页面,更新验证码 二.界面测试 1.样式.颜色.整体布局风格 2.最大化.最小 ...

  7. 题解【AcWing1090】绿色通道

    题面 题目要求出最长的空题段最短的长度,显然可以二分答案. 考虑如何 check. 设二分到的值是 \(x\),即最长的空题段长度至少为 \(x\). 其实整个 check 的过程可以看作一个 DP, ...

  8. Selenium3+python自动化016-Selenium Grid

    一.Selenium Grid介绍 1.概念 Selenium Grid组件专门用于远程分布式测试或并发测试,通过并发执行测试用例的方式可以提高测试用例的执行速度和效率,解决界面自动化测试执行速度过慢 ...

  9. HTML与W3C

    HTML:超文本标记语言 超文本包括:文字.图片.音频.视频.动画等 流程:写好HTML代码后通过浏览器(自动编译HTML代码)展现出效果 HTML优点: 世界知名浏览器厂商对HTML5的支持 微软 ...

  10. Spark学习之路 (三)Spark之RDD[转]

    RDD的概述 什么是RDD? RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素可并行计算的 ...