第一部分:搭建
一、伪分布式:
- 1.依赖java环境,所以jdk必须先安装
- 2.conf先的hbase-env.sh 下的java_home的路径需要修改
- 3.修改hbase-site.xml
<configuration>
<property>
<name>hbase.rootdir</name>
<value>file:///home/testuser/hbase</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/home/testuser/zookeeper</value> //hbase 自带有zookeeper。
</property>
</configuration>
开启:start-hbase.sh 关闭:stop-hbase.sh
- 1.文本页测试访问:http://node01:60010
- 2.启动命令行:hbase shell
- 3.查看表:list
- 4.创建表:create ‘chen’,’cf1’
- 5.放数据:
put 'table01','111','cf1:age','22'
获取信息的方式:
- 1.全盘扫描:scan ‘table01’ (生产环境慎重)
- 2.可用:get ‘table01’,’111’,’cf1:name’
hbase shell 客户端基本用法:
建完表放完数据后,需要刷写才可以到磁盘。flush ‘table’
备注:
如果想同时放多个列簇到表中是不可以的。一个一个放入。
命令通过help 提示操作即可。
二、完全分布式:
搭建计划:
node01作为Hmaster node02作为backupMaster
其中node02,node03,node04作为region Server 。
步骤:
1.检查 hosts jdk iptables
2.免密钥
3.上传/解压
4.配置相关配置文件
a.配置JAVA_HOME 到 hbase-env.hs
b.配置:hbase-site.xml
c.配置:regionserver
d.配置:back-master
e:复制:hdfs-site.xml 到hbase的conf下
具体操作:
4.hbase-site.xml 配置如下:
<property>
25 <name>hbase.rootdir</name>
26 <value>hdfs://mycluster/hbase</value> // hdfs 的连接逻辑入口
27 </property>
28 <property>
29 <name>hbase.cluster.distributed</name>
30 <value>true</value> // 设置可分区
31 </property>
32 <property>
33 <name>hbase.zookeeper.quorum</name>
34 <value>node02,node03,node04</value> // zk的位置
35 </property>
修改:hbase-env.sh
export JAVA_HOME=/usr/java/jdk1.7.0_79/ //jdk的实际路径
export HBASE_MANAGES_ZK=false // 设置支持多节点zookeeper
修改:regionservers 表示自己的regionserver在哪儿。
1 node02
2 node03
3 node04
修改: backup-masters(若无则新建) 备master的位置
node02
测试:启动集群,先启动hadoop。启动前需要先启动zookeeper,
对node02,node03,node04进行:zkServer.sh start
然后对node01启动start-all.sh 启动整个集群。
最后单独启动yarn。对node03和node04进行,yarn-deamon.sh start resourcemanager
最后启动hbase。start-hbase.sh
检查端口使用情况,ss -nal 的端口。其中node01 必须包含2181(hbase自带的zk的),以及60010,hbase提供的webUI的端口。
测试:访问http://node01:60010
备注:几个集群时间需要同步。如果不同步会出现看不到regionserver的情况。
第二部分:HBase的使用:
一.基本的用法
- 1.创建表
create 'table01', 'cf1','cf2' // 表名 列簇1 列簇2
- 2.删除表
删除前设置表为disable
1.disable 'table01'
2.drop 'table01'
3.查看表属性
desc 'table01'
4.强制分区
split 'tab'
分析:
- BLOCKSIZE => ‘65536’, IN_MEMORY => ‘false’, BLOCKCACHE => ‘true’
BLOCKCACHE 为读缓存 IN_MEMORY:是否放入缓存 - TTL => ‘FOREVER’ 含义:time to alived 有效期设置
4.放入数据
put 'table01', '121','cf1:name','chenx'
注意:只可以一个列簇一个列簇的放
5.对生成的文件分析
对伪分布式搭建完成后创建的hbase下的目录下文件进行分析:
cd /home/testuser/hbase/data/default/table01
发现有文件:5dfa5a1b17160b22ec60ad078f0f7a62
此文件就是region 再跟进去就会发现cf1 列簇。或者在webUI上看。
再进入列簇后如果刷写了,可发现hfile文件(如果未满128M,手动刷写:flush ‘table’),刷写后打开hfile文件的方式:hbase hfile -p -f ‘fileName’
第三部分:HBase的介绍及设计思想:
一.HBase 简介
1.Hadoop Database,是一个高可靠性、高性能、面向列、可伸缩、实时读写的分布式数据库
2.利用Hadoop HDFS作为其文件存储系统,利用Hadoop MapReduce来处理HBase中的海量数据,利用Zookeeper作为其分布式协同服务
3.主要用来存储非结构化和半结构化的松散数据(列存 NoSQL 数据库)
二.HBase的数据模型:
具体分析:
ROW KEY
- 1.决定一行数据
- 2.按照字典顺序排序的。
- 3.Row key只能存储64k的字节数据
Timestamp时间戳
1.在HBase每个cell存储单元对同一份数据有多个版本,根据唯一的时间戳来区分每个版本之间的差异,不同版本的数据按照时间倒序排序,最新的数据版本排在最前面。超过版本书后再次插入新数据,最下面的数据就会别标记为失效。后期被处理掉。多版本类似:update 操作。
2.时间戳的类型是 64位整型。
3.时间戳可以由HBase(在数据写入时自动)赋值,此时时间戳是精确到毫秒的当前系统时间。
4.时间戳也可以由客户显式赋值,如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳。
Column Family列族 & qualifier列
1.HBase表中的每个列都归属于某个列族,列族必须作为表模式(schema)定义的一部分预先给出。如 create ‘test’, ‘course’;
2.列名以列族作为前缀,每个“列族”都可以有多个列成员(column);如course:math, course:english, 新的列族成员(列)可以随后按需、动态加入;
3.权限控制、存储以及调优都是在列族层面进行的;
4.HBase把同一列族里面的数据存储在同一目录下,由几个文件保存。
Cell单元格
1.由行和列的坐标交叉决定;
2.单元格是有版本的;
3.单元格的内容是未解析的字节数组;
由{row key, column( = +), version} 唯一确定的单元。
cell中的数据是没有类型的,全部是字节码形式存贮。
HLog(WAL log)
HBase 里只有2种文件,日志文件和数据文件。日志文件为了提高数据可靠性。
如果写操作,日志文件如果完成了,说明写操作无误。
1.HLog文件就是一个普通的Hadoop Sequence File,Sequence File 的Key是HLogKey对象,HLogKey中记录了写入数据的归属信息,除了table和region名字外,同时还包括 sequence number和timestamp,timestamp是” 写入时间”,sequence number的起始值为0,或者是最近一次存入文件系统中sequence number。
2.HLog SequeceFile的Value是HBase的KeyValue对象,即对应HFile中的KeyValue。
HBase 架构
整体分析: 主节点:Hmaster (对regionServer做负载均衡)
Client
包含访问HBase的接口并维护cache来加快对HBase的访问
Zookeeper
- 1.保证任何时候,集群中只有一个master
- 2.存贮所有Region的寻址入口。
- 3.实时监控Region server的上线和下线信息。并实时通知Master
存储HBase的schema和table元数据
Master
- 1.为Region server分配region
- 2.负责Region server的负载均衡(5min/次)
- 3.发现失效的Region server并重新分配其上的region
- 4.管理用户对table的增删改操作
RegionServer
- 1.Region server维护region,处理对这些region的IO请求
- 2.Region server负责切分在运行过程中变得过大的region
Region
1.HBase自动把表水平划分成多个区域(region),每个region会保存一个表里面某段连续的数据
2.每个表一开始只有一个region,随着数据不断插入表,region不断增大,当增大到一个阀值的时候,region就会等分会两个新的region(裂变)
3.table中的行不断增多,就会有越来越多的region。这样一张完整的表被保存在多个Regionserver 上。
Memstore 与 storefile
1.一个region由多个store组成,一个store对应一个CF(列族)
store包括位于内存中的memstore和位于磁盘的storefile写操作先写入memstore,当memstore中的数据达到某个阈值,hregionserver会启动flashcache进程写入storefile,每次写入形成单独的一个storefile2.当storefile文件的数量增长到一定阈值后,系统会进行合并(minor、major compaction),在合并过程中会进行版本合并和删除工作(majar),形成更大的storefile
3.当一个region所有storefile的大小和数量超过一定阈值后,会把当前的region分割为两个,并由hmaster分配到相应的regionserver服务器,实现负载均衡
客户端检索数据,先在memstore找,找不到再找storefile
Hfile文件:
由索引+数据,先加载索引数据到内存,再根据索引去查。把索引器交给hdfs客户端去查。
备注:
0.客户端通过zookeeper访问Master分配其到具体的哪个regionserver上。(从zookeeper里的一个.mete的文件里查)zookeeper里存放客户端请求时到达的位置信息。当到达regionserver上的region的时候,会先记录下Hlog上,然后直接将Hlog落地到HDFS上,然后再把数据写到memstore内存缓冲区上。
1.当bigtable的数据达到10G(可设置)后会自动拆分成多个region。
- 2.当zookeeper检测到regionSever和Hmaster断开连接1.5分钟的时候会告诉Hmaster启动其他regionserver,并通过日志文件恢复。
- 3.memstore满128M的时候会溢写然后落地磁盘。每个列簇里超过3个文件就会进行一次小合并。7天进行一次大合并,把集群里的所有的列簇进行合并。
4.对HLog文件而言,有进程检测其如果已经被刷写到磁盘上了,就会把它放在一个较old的文件夹里。再此检查被刷写的文件超过10分钟后自动删除它。
5.一个stroefile对应着HDFS上一个文件。
6.memstore作为写缓存操作。其实也有一部分作为读缓存,比如,当memstore里的数据达到一定阈值的时候,就会溢写,在溢写完缓存区还有一部分缓存,客户端访问会先访问memstore的缓存里读取,如果没有再去storefile文件里读。但是memstore主要就是做写缓存的操作。读缓存有专门的部分去做(blockcache),一般先从memcache写缓存里找,没有再去读缓存里找。最后落实到hdfs上。
第四部分:Protobuf工具:
一、简介
- 1.Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。
- 2.Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。
二、安装
整体的安装步骤:
1.tar -xzf protobuf-2.1.0.tar.gz
2.cd protobuf-2.1.0
3. ./configure --prefix=$INSTALL_DIR
4.make
5.make check
6.make install
对第三步,的configure会检查软硬件环境并生成相应的文件。编译需要工具。如下
编译环境准备yum groupinstall -y Development tools
三、使用
检查protoc的位置。whereis protoc
/usr/local/bin/protoc
1 package com.jw.hbase;
2 message phoneDetil{
3 required string dum=1;
4 required string date=2;
5 required string type=3;
6 }
9 message dayPhoneDetils{
10 repeated phoneDetil phonoeDetils=1;
11 }
运行:/usr/local/bin/protoc phone.proto --java_out=./
在当前目录下会看到对应的,com/jw/hbase的文件夹里的文件。
第五部分:案例代码分析:
以下为对hbase基本的ddl以及dml等操作。
public class HBaseDemoTest {
Configuration conf = null;
HBaseAdmin admin = null;
String cx = "chenshixingkong";
HTable tab = null;
Random r = new Random();
@Before
public void before() throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
conf = new Configuration();
conf.set("hbase.zookeeper.quorum", "node02,node03,node04");
admin = new HBaseAdmin(conf);
tab = new HTable(conf, cx.getBytes());
}
@After
public void end() throws IOException {
if (admin != null) {
admin.close();
}
}
/**
* 创建表
*
* @throws IOException
*/
@Test
public void createTable() throws IOException {
HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(cx.getBytes()));
HColumnDescriptor cf = new HColumnDescriptor("cf".getBytes());
cf.setInMemory(true); // 放入内存
desc.addFamily(cf);
admin.createTable(desc);
}
/**
* 插入数据 如果插入多条,创建多个put对象即可。
*
* @throws InterruptedIOException
* @throws RetriesExhaustedWithDetailsException
*/
@Test
public void put() throws RetriesExhaustedWithDetailsException, InterruptedIOException {
Put put = new Put("001".getBytes()); // 添加表名
put.add("cf".getBytes(), "name".getBytes(), "chenxiao".getBytes()); // 添加列簇、列簇key和value
tab.put(put);
}
/**
* get 查询
*
* @throws IOExceptio
*/
@Test
public void getDB() throws IOException {
Get get = new Get("001".getBytes());
get.addFamily("cf".getBytes());
Result result = tab.get(get);
Cell cell = result.getColumnLatestCell("cf".getBytes(), "name".getBytes()); // 获取最新版本
byte[] clone = CellUtil.cloneValue(cell); // 将单元格转换成字节数组
System.out.println(new String(clone));
}
/**
* 生成数据操作:10个用户,每个用户100条
*
* @throws ParseException
* @throws InterruptedIOException
* @throws RetriesExhaustedWithDetailsException
*/
@Test
public void insertDB() throws ParseException, RetriesExhaustedWithDetailsException, InterruptedIOException {
List<Put> list = new ArrayList();
for (int i = 0; i < 10; i++) {
String pNum = getPhoneNum("186");
for (int j = 0; j < 100; j++) {
/** ===================rowkey等属性的准备Begin=================== **/
// 对方手机号
String dNum = getPhoneNum("177");
// 通话日期
String dateStr = getDate("2017");
// 主被叫类型
String type = r.nextInt(2) + "";
// rowkey
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String rowkey = pNum + "_" + (Long.MAX_VALUE - format.parse(dateStr).getTime());
/** ===================rowkey等属性的准备End=================== **/
/** ---1:处理rowkey,将rowkey放入put中--- **/
Put put = new Put(rowkey.getBytes());
/** ---2:处理列簇--- **/
put.add("cf".getBytes(), "dNum".getBytes(), dNum.getBytes());
put.add("cf".getBytes(), "type".getBytes(), type.getBytes());
put.add("cf".getBytes(), "date".getBytes(), dateStr.getBytes());
/** ---3:put对象放入list集合中--- **/
list.add(put);
}
}
/** ---4:集合放入表中--- **/
tab.put(list);
}
/**
* 根据手机号查询某个月的通话记录 按rowkey的开始和结束查找
*
* @throws IOException
* @throws ParseException
*/
@Test
public void scan() throws IOException, ParseException {
/** 1.设置起始点 **/
Scan scan = new Scan();
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String startRow = "18610663898" + "_" + (Long.MAX_VALUE - format.parse("20170301000000").getTime());
String stopRow = "18610663898" + "_" + (Long.MAX_VALUE - format.parse("20170201000000").getTime());
scan.setStartRow(startRow.getBytes());
scan.setStopRow(stopRow.getBytes());
/** 2.查询 **/
ResultScanner scanner = tab.getScanner(scan);
/** 2.遍历查询的结果 **/
for (Result r : scanner) {
System.out
.print(new String(CellUtil.cloneValue(r.getColumnLatestCell("cf".getBytes(), "date".getBytes()))));
System.out.print(
" - " + new String(CellUtil.cloneValue(r.getColumnLatestCell("cf".getBytes(), "dNum".getBytes()))));
System.out.println(
" - " + new String(CellUtil.cloneValue(r.getColumnLatestCell("cf".getBytes(), "type".getBytes()))));
}
}
/**
* 某个用户 所有主叫通话记录 过滤器的使用
*
* @throws IOException
*/
@Test
public void scan2() throws IOException {
Scan scan = new Scan();
FilterList list = new FilterList(Operator.MUST_PASS_ALL);
PrefixFilter prefixFilter = new PrefixFilter("18699440769".getBytes());
SingleColumnValueFilter filter = new SingleColumnValueFilter("cf".getBytes(), "type".getBytes(),
CompareOp.EQUAL, "1".getBytes());
list.addFilter(prefixFilter);
list.addFilter(filter);
scan.setFilter(list);
ResultScanner scanner = tab.getScanner(scan);
for (Result r : scanner) {
System.out.print(new String(CellUtil.cloneRow(r.getColumnLatestCell("cf".getBytes(), "date".getBytes()))));
System.out.print(
"-" + new String(CellUtil.cloneValue(r.getColumnLatestCell("cf".getBytes(), "date".getBytes()))));
System.out.print(
" - " + new String(CellUtil.cloneValue(r.getColumnLatestCell("cf".getBytes(), "dNum".getBytes()))));
System.out.println(
" - " + new String(CellUtil.cloneValue(r.getColumnLatestCell("cf".getBytes(), "type".getBytes()))));
}
}
/**
* 获取电话号码
*
* @param prefix
* @return
*/
public String getPhoneNum(String prefix) {
return prefix + String.format("%08d", r.nextInt(99999999));
}
/**
* 获取日期
*
* @param year
* @return
*/
public String getDate(String year) {
return year + String.format("%02d%02d%02d%02d%02d",
new Object[] { r.nextInt(12) + 1, r.nextInt(28) + 1, r.nextInt(24), r.nextInt(60), r.nextInt(60) });
}
}
序列化和反序列化操作:
public class HBasedemo_new {
String TN = "phone";
HBaseAdmin admin;
HTable htable;
@Before
public void before() throws Exception {
Configuration conf = new Configuration();
// 完全分布式HBase集群 指定ZooKeeper集群地址
// 伪分布式 单独指定那一台HBase节点
conf.set("hbase.zookeeper.quorum", "node02,node03,node04");
admin = new HBaseAdmin(conf);
htable = new HTable(conf, TN);
}
@After
public void end() throws Exception {
if (admin != null) {
admin.close();
}
if (htable != null) {
htable.close();
}
}
@Test
public void createTable() throws Exception {
if (admin.tableExists(TN)) {
admin.disableTable(TN);
admin.deleteTable(TN);
}
HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(TN));
HColumnDescriptor cf = new HColumnDescriptor("cf".getBytes());
cf.setInMemory(true);
cf.setMaxVersions(1);
desc.addFamily(cf);
admin.createTable(desc);
}
/**
* 添加数据
*
* @throws Exception
*/
@Test
public void put() throws Exception {
Put put = new Put("1111".getBytes());
put.add("cf".getBytes(), "name".getBytes(), "xiaoming".getBytes());
put.add("cf".getBytes(), "age".getBytes(), "31".getBytes());
htable.put(put);
}
/**
* 读取数据 get方式
*
* @throws Exception
*/
@Test
public void getData() throws Exception {
Get get = new Get("1111".getBytes());
get.addColumn("cf".getBytes(), "name".getBytes());
Result rs = htable.get(get);
Cell cell = rs.getColumnLatestCell("cf".getBytes(), "name".getBytes());
System.out.println(new String(CellUtil.cloneValue(cell)));
}
/**
* 十个用户, 每个产生一百条通话记录
*/
@Test
public void insertDB1() throws Exception {
List<Put> puts = new ArrayList<Put>();
for (int i = 0; i < 10; i++) {
// 自己、用户的手机号码
String pNum = getPhoneNum("186");
for (int j = 0; j < 100; j++) {
// 对方手机号
String dNum = getPhoneNum("177");
// 通话时间
String dateStr = getDate("2017");
// 主叫、被叫类型
String type = r.nextInt(2) + "";
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
// rowkey: 手机号_(大数-时间戳)
String rowkey = pNum + "_" + (Long.MAX_VALUE - sdf.parse(dateStr).getTime());
Put put = new Put(rowkey.getBytes());
put.add("cf".getBytes(), "dnum".getBytes(), dNum.getBytes());
put.add("cf".getBytes(), "date".getBytes(), dateStr.getBytes());
put.add("cf".getBytes(), "type".getBytes(), type.getBytes());
puts.add(put);
}
}
htable.put(puts);
}
/**
* 十个用户, 每个用户 当天产生了 一百条通话记录
*/
@Test
public void insertDB2() throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
List<Put> puts = new ArrayList<Put>();
for (int i = 0; i < 10; i++) {
// 自己、用户的手机号码
String pNum = getPhoneNum("186");
String dateStr = "20170818000000";
String rowkey = pNum + "_" + (Long.MAX_VALUE - sdf.parse(dateStr).getTime());
// 每个用户一个大盒子
Phone.dayPhoneDetail.Builder dayPhone = Phone.dayPhoneDetail.newBuilder();
for (int j = 0; j < 100; j++) {
// 对方手机号
String dNum = getPhoneNum("177");
// 通话时间
String date = getDate2("20170818");
// 主叫、被叫类型
String type = r.nextInt(2) + "";
// 当天一条通话记录
Phone.phoneDetail.Builder phone = Phone.phoneDetail.newBuilder();
phone.setDate(date);
phone.setDnum(dNum);
phone.setType(type);
dayPhone.addPhoneDetails(phone);
}
Put put = new Put(rowkey.getBytes());
put.add("cf".getBytes(), "dayPhone".getBytes(), dayPhone.build().toByteArray());
puts.add(put);
}
htable.put(puts);
}
/**
* 查询 18693457181 该用户 这一天产生 的所有通话记录
*
* @throws Exception
*/
@Test
public void getDB2() throws Exception {
Get get = new Get("18698524438_9223370533869175807".getBytes());
get.addColumn("cf".getBytes(), "dayPhone".getBytes());
Result rs = htable.get(get);
Cell cell = rs.getColumnLatestCell("cf".getBytes(), "dayPhone".getBytes());
// 反序列化 CellUtil.cloneValue(cell) 对象->二进制序列 二进制序列 -> 对象 一天一个集合
Phone.dayPhoneDetail dayPhone = Phone.dayPhoneDetail.parseFrom(CellUtil.cloneValue(cell));
for (Phone.phoneDetail phone : dayPhone.getPhoneDetailsList()) {
System.out.println(phone.getDate() + " - " + phone.getDnum() + " - " + phone.getType());
}
}
/**
* 查询某个用户 某月 产生的所有通话记录
*
* 18678525661 一月份
*/
@Test
public void scanDB2() throws Exception {
Scan scan = new Scan();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String startRow = "18678525661_" + (Long.MAX_VALUE - sdf.parse("20170201000000").getTime());
String stopRow = "18678525661_" + (Long.MAX_VALUE - sdf.parse("20170101000000").getTime());
scan.setStartRow(startRow.getBytes());
scan.setStopRow(stopRow.getBytes());
ResultScanner rs = htable.getScanner(scan);
for (Result result : rs) {
System.out.print(
new String(CellUtil.cloneValue(result.getColumnLatestCell("cf".getBytes(), "dnum".getBytes()))));
System.out.print(" - "
+ new String(CellUtil.cloneValue(result.getColumnLatestCell("cf".getBytes(), "date".getBytes()))));
System.out.println(" - "
+ new String(CellUtil.cloneValue(result.getColumnLatestCell("cf".getBytes(), "type".getBytes()))));
}
}
/**
* 查询某个用户 所有主叫被叫 通话记录 过滤器
*
* @throws Exception
*/
@Test
public void scanDB3() throws Exception {
Scan scan = new Scan();
FilterList list = new FilterList(FilterList.Operator.MUST_PASS_ALL);
// 前缀过滤器
PrefixFilter filter1 = new PrefixFilter("18678525661".getBytes());
list.addFilter(filter1);
// 值过滤器 找到 所有的type=0 主叫的 通话记录
SingleColumnValueFilter filter2 = new SingleColumnValueFilter("cf".getBytes(), "type".getBytes(),
CompareOp.EQUAL, "0".getBytes());
list.addFilter(filter2);
scan.setFilter(list);
ResultScanner rs = htable.getScanner(scan);
for (Result result : rs) {
System.out.print(
new String(CellUtil.cloneValue(result.getColumnLatestCell("cf".getBytes(), "dnum".getBytes()))));
System.out.print(" - "
+ new String(CellUtil.cloneValue(result.getColumnLatestCell("cf".getBytes(), "date".getBytes()))));
System.out.println(" - "
+ new String(CellUtil.cloneValue(result.getColumnLatestCell("cf".getBytes(), "type".getBytes()))));
}
}
// 练习: 实现 删除某个Cell
Random r = new Random();
/**
* 随机生成测试手机号码 prefix: 手机号码前缀 eq:186
*/
public String getPhoneNum(String prefix) {
return prefix + String.format("%08d", r.nextInt(99999999));
}
/**
* 随机生成时间
*
* @param year年
* @return 时间 格式:yyyyMMddHHmmss
*/
public String getDate(String year) {
return year + String.format("%02d%02d%02d%02d%02d",
new Object[] { r.nextInt(12) + 1, r.nextInt(28) + 1, r.nextInt(24), r.nextInt(60), r.nextInt(60) });
}
/**
* 随机生成时间
*
* @param prefix年月日
* 2017-8-1
* @return 时间 格式:yyyyMMddHHmmss
*/
public String getDate2(String prefix) {
return prefix + String.format("%02d%02d%02d", new Object[] { r.nextInt(24), r.nextInt(60), r.nextInt(60) });
}
附录:
描述:负载均衡器启动周期 5分钟
<property>
<name>hbase.balancer.period
</name>
<value>300000</value>
</property>
描述:region拆分阈值 10g
<property>
<name>hbase.hregion.max.filesize</name>
<value>10737418240</value>
</property>
描述:memstore溢写阈值 128M
<property>
<name>hbase.hregion.memstore.flush.size</name>
<value>134217728</value>
</property>
描述:溢写检查线程检查间隔 10秒
<property>
<name>hbase.server.thread.wakefrequency</name>
<value>10000</value>
</property>
描述:minor合并的最大文件数 10个
<property>
<name>hbase.hstore.compaction.max</name>
<value>10</value>
</property>
描述:触发mionr合并的阈值(hsotrefile文件个数)3个
<property>
<name>hbase.hstore.compactionThreshold</name>
<value>3</value>
</property>
描述:major的合并周期 7天
<property>
<name>hbase.hregion.majorcompaction</name>
<value>604800000</value>
</property>
描述:hlog文件在old目录中最长的生命周期 10分钟
<property>
<name>hbase.master.logcleaner.ttl</name>
<value>600000</value>
</property>