大数据-HBase
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 查询
客户端发送请求查询数据到KZ集群
KZ根据-root-数据找到.meta.表,meta根据查询请求找到所需要的Region及其在所在的RegionServer,建立与RegionServer的链接
Region内部数据有序(基于rowkey)采用二分查找直接找到数据所有的store(store对应列族)
最终在列族的子列与时间戳定位到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优化
表设计优化
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个分区
代码方式:二维数组方式,具体见代码实现部分
Rowkey
Rowkey是以byte数组存储的部定长字符串,最大长度64K。
Rowkey是按字典序排列的,一般将其设置为定长的,将时间戳作为Rowkey的一部分,便于将相邻时间的数据一起查出。
优化规则
越短越好(每条记录中都存了rowkey的值,大量冗余)
根据业务需求设置rowkey,以提高查询效率为考虑准则
对于存在访问过于集中的rowkey端,为了避免热点产生,需要对rowkey散列处理:取反方式,hash方式
基于Rowkey的查找方式
通过单个rowkey的get查找,直接定位单个rowkey
通过指定rowkey范围的scan扫描,设置startRowKey和endRowKey
全表scan扫描,效率低
Column Family
一张表中不要设置超过3个列族
原因包括:
1 当一个列族的数据flush时(men写出到storefile时),相邻的列族也会被关联触发,HRS同时执行多个IO操作,导致效率降低
2 执行查找时,rowkey对应过多的列族,导致查找时必须遍历所有列族的storefile,storefile过多查询缓慢
Compact & Split (StoreFile/Hfile的合并与切分)
合并
问题:StoreFile为memony写出的硬盘中的数据,每次写出的StoreFile内部都是有序的,而StoreFile文件之间无顺序。因此在查询数据时需要遍历每个StoreFile,存在效率问题。
合并方式
minor compact 相邻若干StoreFile合并,可以指定数量
major compact HR中的所有StoreFile合并,同时处理标记数据(删除的数据,version过期数据,有效期过期数据),这种方式占用资源较大一般需要手动触发
效果:
能够获取到有序的大数据量的StoreFile,降低IO压力,数据占用空间压缩。
切分
StoreFile大于阈值后,StoreFile将被切分
切分和合并的阈值可以手动设置,使得系统中的StoreFile大小均衡且合并切分次数较小
In Memory
在RS中设置内存共享区域,创建表时将表存入memory中,增加缓存的命中率
关于数据失效
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占比
数据查询过程说明
从每个Region的memstore查询数据
若memstore无对应数据,查询Blockcache数据
若Blockcache无对应数据,查询DFS的数据
若从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();
关于扫描查询
设置扫描器
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"));
将过滤器设置到扫描器中
scan.setFilter(filter1);
执行查询,并遍历获取结果
将扫描器设置到表连接中,以获取查询结果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的更多相关文章
- 第五章:大数据 の HBase 进阶
本课主题 HBase 读写数据的流程 HBase 性能优化和最住实践 HBase 管理和集群操作 HBase 备份和复制 引言 前一篇 HBase 基础 (HBase 基础) 简单介绍了NoSQL是什 ...
- 第四章:大数据 の HBase 基础
本课主题 NoSQL 数据库介绍 HBase 基本操作 HBase 集群架构与设计介紹 HBase 与HDFS的关系 HBase 数据拆分和紧缩 引言 介绍什么是 NoSQL,NoSQL 和 RDBM ...
- 大数据hbase分布式安装及其部署。
大数据hbase分布式安装及其部署. 首先要启动Hadoop以及zookeeper,可以参考前面发布的文章. 将hbase的包上传至master节点 这里我使用的是1.3.6的版本,具体的根据自己的版 ...
- 大白话详解大数据HBase核心知识点,老刘真的很用心(2)
前言:老刘目前为明年校招而努力,写文章主要是想用大白话把自己复习的大数据知识点详细解释出来,拒绝资料上的生搬硬套,做到有自己的理解! 01 HBase知识点 第6点:HRegionServer架构 为 ...
- 大白话详解大数据HBase核心知识点,老刘真的很用心(3)
老刘目前为明年校招而努力,写文章主要是想用大白话把自己复习的大数据知识点详细解释出来,拒绝资料上的生搬硬套,做到有自己的理解! 01 HBase知识点(3) 第13点:HBase表的热点问题 什么是热 ...
- 用大白话讲大数据HBase,老刘真的很用心(1)
老刘今天复习HBase知识发现很多资料都没有把概念说清楚,有很多专业名词一笔带过没有解释.比如这个框架高性能.高可用,那什么是高性能高可用?怎么实现的高性能高可用?没说! 如果面试官听了你说的,会有什 ...
- 入门大数据---Hbase是什么?
一.Hbase是什么? Hbase属于NoSql的一种. NoSql数据库分为如下几类: Key-Value类型数据库 这类数据库主要会使用到一个哈希表,这个表有一个特定的键和一个指针指向特定的数据. ...
- 大数据——hbase
进入hbase hbase shell 部分命令清单 查询服务器状态 status 查询hbase版本 version 1. 创建一个表 create 'table1', 'tab1_id', ...
- 大数据Hbase相关运维题
1.启动先电大数据平台的 Hbase 数据库,其中要求使用 master 节点的RegionServer.在 Linux Shell 中启动 Hbase shell,查看 HBase 的版本信息.(相 ...
随机推荐
- SURF特征检测
SERF(speed up robust feature )特征的关键特性: 特征检测 尺度空间:缩放到不同的大小或分辨率仍能检测 选择不变性:光照不变,旋转不变 特征向量:描述为一个特征向量 DDN ...
- NODEJS 中使用二维码 qr-image
https://www.npmjs.com/package/qr-image npm install qr-image var qr = require('qr-image'); var code = ...
- linux查看防火墙状态和对外开放的端口状态
1.查看防火墙状态 查看防火墙状态 systemctl status firewalld 开启防火墙 systemctl start firewalld ...
- gulp常用插件之gulp-beautify使用
更多gulp常用插件使用请访问:gulp常用插件汇总 gulp-beautify这是一款使用js-beautify进行资产美化插件. 更多使用文档请点击访问gulp-beautify工具官网. 安装 ...
- Codeforces Round #617 (Div. 3) 补题记录
1296A - Array with Odd Sum 题意:可以改变数组中的一个数的值成另外一个数组中的数,问能不能使数组的和是个奇数 思路:签到,如果本来数组的和就是个奇数,那就OK 如果不是,就需 ...
- (一)Python模块化编程简介
1 引言 众所周知,模块化编程具备很多优点,尤其在复杂项目上体现更为明显.Python模块化编程有助于开发者统筹兼顾和分工协作,并提升代码灵活性和可维护性,是编程开发者不可或缺的一项重要工具. 2 P ...
- aws申请ec2实例后如何用root用户登录
ec2默认禁用root用户登录,我们创建ec2实例后如何知道使用什么用户登录,有两种方法? 方法一:根据我们选择的镜像来判断用什么用户登录:镜像:centos 用户centos镜像:aws 用户:ec ...
- css动画 transition
比如输入框触交渐变 在原来的属性添加 : .form-control{-webkit-transition: all .3s; transition: all .3s;} .form-control: ...
- CTF中压缩文件的常见解法
此篇记录两篇记录的比较好的关于压缩文件破解的总结 链接:https://blog.csdn.net/xuqi7/article/details/71437882 https://blog.csdn.n ...
- 简单scrapy爬虫实例
简单scrapy爬虫实例 流程分析 抓取内容:网站课程 页面:https://edu.hellobi.com 数据:课程名.课程链接及学习人数 观察页面url变化规律以及页面源代码帮助我们获取所有数据 ...