大数据-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 的版本信息.(相 ...
随机推荐
- Spring mvc拦截器防御CSRF攻击
CSRF(具体参考百度百科) CSRF(Cross-site request forgery跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSR ...
- KindEditor配置和使用
1下载kindeditor包,目前最新版本是kindeditor-3.5.5.下载地址:http://www.kindsoft.net/ 2.解压之后,解压目录kindeditor如下图所示. 3.开 ...
- zipfile-压缩解压
zipfile 压缩解压 import os import zipfile # 导入模块 # BASE_STATIC_CASE_RESULT:我Django static下面的某个路径 BASE = ...
- JS实现登录页密码的显示和隐藏功能
在登录页经常会用到通过点击文本框的类似小眼睛图片来实现隐藏显示密码的功能,其实实现原理很简单,通过点击事件来改变input的type类型,具体过程看代码: 在没给大家分享实现代码之前,先给大家展示下效 ...
- GitKraken 快速配置 SSH Key
快速使用 GitKraken 配置SSH keys git是现在最流行的版本管理工具,应用范围非常广泛,推荐一款git的可视化工具,这款 工具特别方便 它的官方如下https://www.gitkra ...
- vue 学习3
在 2.5.0 及以上版本中,如果你使用了单文件组件 $children,$slots,$attrs .... $attrs 可以透传props 注意.模板标签上有:属性="a", ...
- 手动部署:在eclipse导入web项目并更新包到本地部署
一.eclipse导入java web项目 1.file-import-git-next-clone URL-填写git上面的URL,然后一直next,完成后等待即可 二.导入多个版本项目 1.fil ...
- 统一操作系统 UOS 回应质疑 (独立思考)
统一操作系统 UOS 回应质疑 自从统一操作系统UOS正式版面向合作伙伴发布之后,小编就关注到网上对统一操作系统UOS众说纷纭.留意了近期网友们发表的评论: “又多了一个骗钱的国产操作系统” “从UO ...
- 使用FDATOOL生成xilinx中FIR滤波器IP核的系数
1.在MATLAB命令窗口输入fdatool后回车,打开“Filter Designer & Analysis Tool”工具界面: 2.点击左下角的Set quantization para ...
- C#中怎样在ToolStripMenuItem下再添加子级菜单
场景 在右键菜单ContextMenuStrip下添加子菜单选项可以通过 ContextMenuStrip menuStrip ToolStripMenuItem mnuChartOption = n ...