Hbase多版本的读写(Shell&Java API版)
Hbase是基于HDFS的NOsql数据库,它很多地方跟数据库差不多,也有很多不同的地方。这里就不一一列举了,不过Hbase有个版本控制的特性,这个特性在很多场景下都会发挥很大的作用。本篇就介绍下基于
Shell
和Java API
的Hbase多版本的读写。
为了更好的理解多版本,我们可以把普通的数据存储理解成二维空间,提供了rowkey,列族,列几个存储的维度。那么版本则相当于二维空间升华到了三维空间,多了时间维度的概念。如果按照默认的操作,当前的时间戳就是版本号,每个数据都可以保留多个版本的数据。你可以只查询最新的数据,也可以查看历史版本。
这里课外引申一下:从一维到十维空间,有兴趣的可以看一下。 <-- 不要当真哈!从思维开始就已经扯淡了! 上个月在阅读《三体》的时候,也很感叹最后都是多维空间拯救了人类!
话题扯远了,回过来我们在看一下多版本如何进行读写
第一步,创建表并开启多版本
hbase(main):002:0> create_namespace 'xingoo'
0 row(s) in 0.0230 seconds
hbase(main):003:0> create 'xingoo:test_v','v'
0 row(s) in 4.5760 seconds
=> Hbase::Table - xingoo:test_v
创建Hbase表,并查看表结构:
hbase(main):004:0> describe 'xingoo:test_v'
Table xingoo:test_v is ENABLED
xingoo:test_v
COLUMN FAMILIES DESCRIPTION
{NAME => 'v', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TT
L => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
1 row(s) in 0.1040 seconds
需要关注的是VERSIONS字段,这个字段默认为1,即默认只保留一个版本的数据,如果不修改,无论你怎么写,都只能查到一个版本的数据。
更多参数信息,可以查看HColumnDescriptor的Java Doc
修改版本数
hbase(main):005:0> alter 'xingoo:test_v',NAME=>'v',VERSIONS=>5
Updating all regions with the new schema...
1/1 regions updated.
Done.
0 row(s) in 3.1590 seconds
hbase(main):006:0> describe 'xingoo:test_v'
Table xingoo:test_v is ENABLED
xingoo:test_v
COLUMN FAMILIES DESCRIPTION
{NAME => 'v', BLOOMFILTER => 'ROW', VERSIONS => '5', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TT
L => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
1 row(s) in 0.0150 seconds
再次查看下,就可以看到支持的版本多了。
基于Shell的读写
shell写入多个版本
hbase(main):007:0> put 'xingoo:test_v','1','v:c1','value1'
0 row(s) in 0.0870 seconds
hbase(main):008:0> put 'xingoo:test_v','1','v:c1','value2'
0 row(s) in 0.0050 seconds
hbase(main):009:0> put 'xingoo:test_v','1','v:c1','value3'
0 row(s) in 0.0040 seconds
hbase(main):010:0> put 'xingoo:test_v','1','v:c1','value4'
0 row(s) in 0.0040 seconds
hbase(main):011:0> put 'xingoo:test_v','1','v:c1','value5'
0 row(s) in 0.0040 seconds
hbase(main):012:0> put 'xingoo:test_v','1','v:c1','value6'
0 row(s) in 0.0030 seconds
hbase(main):013:0> put 'xingoo:test_v','1','v:c1','value7'
0 row(s) in 0.0040 seconds
shell读取多个版本的数据
注意:如果读取的版本大于Hbase存储的版本,那么只会读取最大VESIONS个记录。
hbase(main):015:0> get 'xingoo:test_v','1',{COLUMN => 'v:c1',VERSIONS=>5}
COLUMN CELL
v:c1 timestamp=1499088390024, value=value7
v:c1 timestamp=1499088387559, value=value6
v:c1 timestamp=1499088385347, value=value5
v:c1 timestamp=1499088383228, value=value4
v:c1 timestamp=1499088380943, value=value3
5 row(s) in 0.0070 seconds
hbase(main):016:0> get 'xingoo:test_v','1',{COLUMN => 'v:c1',VERSIONS=>6}
COLUMN CELL
v:c1 timestamp=1499088390024, value=value7
v:c1 timestamp=1499088387559, value=value6
v:c1 timestamp=1499088385347, value=value5
v:c1 timestamp=1499088383228, value=value4
v:c1 timestamp=1499088380943, value=value3
5 row(s) in 0.0050 seconds
hbase(main):017:0> get 'xingoo:test_v','1',{COLUMN => 'v:c1',VERSIONS=>2}
COLUMN CELL
v:c1 timestamp=1499088390024, value=value7
v:c1 timestamp=1499088387559, value=value6
2 row(s) in 0.0060 seconds
另外,还可以把版本字段当做一个时间字段来进行范围查询,如:
hbase> get 't1', 'r1', {COLUMN => 'c1', TIMERANGE => [ts1, ts2], VERSIONS => 4}
基于Java的读写
首先,需要创建工具类,包含连接的配置
public class HbaseClient {
public static final String TABLE = "xingoo:test_v";
private static Configuration conf = null;
private static Connection conn = null;
static {
try {
conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.property.clientPort", "2181");
conf.set("hbase.zookeeper.quorum", "zk1,zk2,zk3");
conn = ConnectionFactory.createConnection(conf);
} catch (IOException e) {
e.printStackTrace();
}
}
...
}
读操作
public void write(String phone,String listing_id) throws IOException {
HTable myTable = new HTable(conf, TableName.valueOf(TABLE));
myTable.setAutoFlush(false, false);
myTable.setWriteBufferSize(3 * 1024 * 1024);
Put p = new Put(Bytes.toBytes("row_key_1"));
//可以自己设置时间戳作为版本号,也可以使用默认时间
// p.addColumn(Bytes.toBytes("v"), Bytes.toBytes("c1"), System.currentTimeMillis(), Bytes.toBytes("test1"));
p.addColumn(Bytes.toBytes("v"), Bytes.toBytes("c1"), Bytes.toBytes("test2"));
System.out.println(System.currentTimeMillis());
myTable.put(p);
myTable.flushCommits();
myTable.close();
}
写操作
public List<String> read(String q) throws IOException {
Table table = HbaseClient.conn.getTable(TableName.valueOf(TABLE));
Scan scan = new Scan();
scan.addColumn("v".getBytes(),"c1".getBytes());
scan.setMaxVersions(3);//设置读取的最大的版本数
RowFilter rowFilter = new RowFilter(CompareFilter.CompareOp.EQUAL,new BinaryComparator(q.getBytes()));//基于过滤器设置查询条件
scan.setFilter(rowFilter);
ResultScanner r = table.getScanner(scan);
List<String> list = new ArrayList<>();
for(Result result : r) {
for (KeyValue kv : result.raw()) {
list.add(Bytes.toString(kv.getValue()));
}
}
System.out.println(list.size());
table.close();
return list;
}
参考
1 hbase教程:http://www.yiibai.com/hbase/ 2 hbase官方文档:http://hbase.apache.org/book.html#appendix_contributing_to_documentation 3 一维到十维空间:http://www.sohu.com/a/116444282_482877
- 检测到Loaderlock的问题
- 权威报告预测比特币在2018年“王位”不保
- Linux下FTP环境部署梳理(vsftpd和proftpd)
- Silverlight如何与JS相互调用
- Docker容器学习梳理--私有仓库Registry使用
- 从插件重构看如何提升测试质量与效率
- 巧用WinRAR+Javascript解决activeX的自动安装问题
- 在网页中实现QQ的屏幕截图功能
- Activity之间传递参数
- linux下rsync和tar增量备份梳理
- 重温Delphi之:面向对象
- Android新手之旅(15) Win7下配置遇到的问题
- 重温Delphi之:如何定义一个类
- Android新手之旅(2) 新手问题
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Cordova安装
- django-ckeditor本地图片上传功能
- ESP32 windows下编译环境搭建
- Android hex十六进制转String
- “Ajax请求后台,后台两次session不一致”问题解决
- Angularjs动态加载ECharts(一)
- NodeMCU连接wifi语句报错:“stdin:1: bad argument #1 to 'config' (config table not found!)”
- Angularjs动态加载ECharts(二)
- 【LeetCode】每日一题(8.3)
- LeetCode精选好题(四)
- 【Android 直播软件开发:音视频硬解码篇】
- 知更鸟主题修改CSS:让凌乱的标签变得整洁清爽
- 浅谈 Android Dex 文件
- Tcp连接建立与连接释放
- Python Django开发 异常及解决办法(三)