文档章节

hbase shell命令扩展

Zero零_度
 Zero零_度
发布于 2017/06/10 10:38
字数 1289
阅读 75
收藏 0

也许你还不清楚我在说什么,看一下下面的截图你就明白了:

 

 

好吧,如果您感兴趣,可以继续看下去了。

 

Hbase是以字节数组的形式存储数据的,当你直接用API或通过hbase 自带的shell端去查询数据时,实际显示的是二进制数据的byteString的形式,就像这样:\xE5\x94\xAE\xE5\x90\x8E,当然,这肯定不是你想看到的结果。不过没办法,因为rowkey和value是用户自己定义的,包括类型,长度等,又因为存的是二进制数据,所以hbase自身api不可能解析出真实的数据,因为它不知道存取的规则。

我们要做的,就是要制定这种数据存储的规则,比如:rowkey由几个字段构成,每一个的类型,value的类型。值得一提的是几种数值型一旦类型一定,长度就定了,但string类型比较特殊,长度不是固定的。这里先使用一个字节存储长度,再紧跟着具体string串,当然这只是一种方式。value使用一个columfamily,因为官方也不建议使用太多。

以上的规则作为元数据放在xml配置文件里再好不过了,以后增加了hbase表,只需修改配置文件。

根据上面的规则写几个包含处理逻辑的类是必须的,包括读元数据,类型之间的转换方法等等。有了这些方法,就能在任何地方输出想要的数据,比如web前端。下面是以scan为例的hbase shell客户端具体实现思路:

 

1. 首先要在ruby/shell/commands下增加一个命令,姑且叫做superscan吧,直接对应一个JRuby脚本,定义一个Superscan类继承自Command,接收结果集并格式化输出。

内容如下:

[ruby] view plain copy

 print?

  1. module Shell  
  2.   module Commands  
  3.     class Superscan < Command  
  4.       def help  
  5.         return <<-EOF  
  6. 此处省略若干打印的帮助信息  

[ruby] view plain copy

 print?

  1.         EOF  
  2.       end  
  3.   
  4.       def command(table, args = {})  
  5.         now = Time.now  
  6.         formatter.header(["READABLE_ROW", "READABLE(COLUMN+CELL)"])  
  7.   
  8.         count = table(table).superscan(args) do |row, cells|  
  9.           formatter.row([ row, cells ])  
  10.         end  
  11.   
  12.         formatter.footer(now, count)  
  13.       end  
  14.     end  
  15.   end  
  16. end  


 

2.shell.rb脚本中的dml命令组里要添加上面定义的命令。

3.下面主要是对ruby/hbase/table.rb脚本的修改,添加相应的方法:

因为我的api里用到了表的名字,所以要在初始化方法里加个tablename变量:

 

[ruby] view plain copy

 print?

  1. def initialize(configuration, table_name, formatter)  
  2.       @table = org.apache.hadoop.hbase.client.HTable.new(configuration, table_name)  
  3.       @tableName = table_name  
  4.     end  

 

 

superscan方法:

 

 

[ruby] view plain copy

 print?

  1. #----------------------------------------------------------------------------------------------  
  2.     # superScans whole table or a range of keys and returns rows matching specific criterias  
  3.     def superscan(args = {})  
  4.       unless args.kind_of?(Hash)  
  5.         raise ArgumentError, "Arguments should be a hash. Failed to parse #{args.inspect}, #{args.class}"  
  6.       end  
  7.   
  8.       limit = args.delete("LIMIT") || -1  
  9.       maxlength = args.delete("MAXLENGTH") || -1  
  10.   
  11.       if args.any?  
  12.         filter = args["FILTER"]  
  13.         startrow = args["STARTROW"] || ''  
  14.         stoprow = args["STOPROW"]  
  15.         timestamp = args["TIMESTAMP"]  
  16.         columns = args["COLUMNS"] || args["COLUMN"] || get_all_columns  
  17.         cache = args["CACHE_BLOCKS"] || true  
  18.         versions = args["VERSIONS"] || 1  
  19.         timerange = args[TIMERANGE]  
  20.   
  21.         # Normalize column names  
  22.         columns = [columns] if columns.class == String  
  23.         unless columns.kind_of?(Array)  
  24.           raise ArgumentError.new("COLUMNS must be specified as a String or an Array")  
  25.         end  
  26.   
  27.         scan = if stoprow  
  28.           org.apache.hadoop.hbase.client.Scan.new(startrow.to_java_bytes, stoprow.to_java_bytes)  
  29.         else  
  30.           org.apache.hadoop.hbase.client.Scan.new(startrow.to_java_bytes)  
  31.         end  
  32.   
  33.         columns.each do |c|   
  34.           family, qualifier = parse_column_name(c.to_s)  
  35.           if qualifier  
  36.             scan.addColumn(family, qualifier)  
  37.           else  
  38.             scan.addFamily(family)  
  39.           end  
  40.         end  
  41.   
  42.         unless filter.class == String  
  43.           scan.setFilter(filter)  
  44.         else  
  45.           scan.setFilter(org.apache.hadoop.hbase.filter.ParseFilter.new.parseFilterString(filter))  
  46.         end  
  47.   
  48.         scan.setTimeStamp(timestamp) if timestamp  
  49.         scan.setCacheBlocks(cache)  
  50.         scan.setMaxVersions(versions) if versions > 1  
  51.         scan.setTimeRange(timerange[0], timerange[1]) if timerange  
  52.       else  
  53.         scan = org.apache.hadoop.hbase.client.Scan.new  
  54.       end  
  55.   
  56.       # Start the scanner  
  57.       scanner = @table.getScanner(scan)  
  58.       count = 0  
  59.       res = {}  
  60.       iter = scanner.iterator  
  61.   
  62.       # Iterate results  
  63.       while iter.hasNext  
  64.         if limit > 0 && count >= limit  
  65.           break  
  66.         end  
  67.   
  68.         row = iter.next  
  69.         key = org.apache.hadoop.hbase.util.Bytes::toStringBinary(row.getRow)   #\00\x01这种形式  
  70.         byteKey = row.getRow  
  71.         #add  
  72.         rowType = com.cuirong.bi.data.hbase.reader.MetaConfig::getRowKeyType(@tableName)  
  73.   
  74.         stringKey = com.cuirong.bi.data.hbase.inf.CommonUtil::bytes2String(byteKey,rowType)   
  75.   
  76.         #endadd  
  77.           
  78.         row.list.each do |kv|  
  79.           family = String.from_java_bytes(kv.getFamily) #字节数组转string  
  80.           qualifier = org.apache.hadoop.hbase.util.Bytes::toStringBinary(kv.getQualifier)   
  81.   
  82.           column = "#{family}:#{qualifier}"  
  83.           cell = to_strings(column, kv, byteKey, maxlength)  
  84.   
  85.           if block_given?  
  86.             yield(stringKey, "column=#{column}, #{cell}")  
  87.           else  
  88.             res[stringKey] ||= {}  
  89.             res[stringKey][column] = cell  
  90.           end  
  91.         end  
  92.   
  93.         # One more row processed  
  94.         count += 1  
  95.       end  
  96.   
  97.       return ((block_given?) ? count : res)  
  98.     end  


上面的方法用到了to_strings方法:

 

 

 

[ruby] view plain copy

 print?

  1. # Make a String of the passed kv  
  2.     # Intercept cells whose format we know such as the info:regioninfo in .META.  
  3.     def to_strings(column, kv, byteKey, maxlength = -1)  
  4.       if is_meta_table?  
  5.         if column == 'info:regioninfo' or column == 'info:splitA' or column == 'info:splitB'  
  6.           hri = org.apache.hadoop.hbase.util.Writables.getHRegionInfoOrNull(kv.getValue)  
  7.           return "timestamp=%d, value=%s" % [kv.getTimestamp, hri.toString]  
  8.         end  
  9.         if column == 'info:serverstartcode'  
  10.           if kv.getValue.length > 0  
  11.             str_val = org.apache.hadoop.hbase.util.Bytes.toLong(kv.getValue)  
  12.           else  
  13.             str_val = org.apache.hadoop.hbase.util.Bytes.toStringBinary(kv.getValue)   
  14.           end  
  15.           return "timestamp=%d, value=%s" % [kv.getTimestamp, str_val]  
  16.         end  
  17.       end  
  18.         #add  
  19.   
  20.         reader = com.cuirong.bi.data.hbase.reader.HBaseReader.new(@tableName)  
  21.         row = reader.getRow(byteKey)  
  22.           
  23.         #endadd  
  24.       #val = "timestamp=#{kv.getTimestamp}, value=#{org.apache.hadoop.hbase.util.Bytes::toStringBinary(kv.getValue)}"  
  25.       val = "timestamp=#{kv.getTimestamp}, value=#{row.getColumn(column)}"  
  26.       (maxlength != -1) ? val[0, maxlength] : val  
  27.     end  

 

上面代码中有几个java类是自己定义的,跟据名字应该能猜出做了哪些工作。

 

 

可能有些人还不清楚hbase,ruby,JRuby,Java之间的关系,下面简单介绍下:

hbase当然是用java实现的开源数据库

我们常说的ruby是一门Matz(此人跟苍老师同一国籍)设计的C语言实现解释器的语言,ruby on rails,可以用于web开发。

JRuby是一个用纯java实现了ruby语法解释器的语言,表面上在写ruby脚本,实际运行的还是在jvm上运行字节码文件。JRuby API里面有一个org.jruby.Main 类,作为ruby脚本的入口。

在hbase中, bin/hirb.rb就是入口脚本,它会加载其它ruby脚本,被JRuby API编译成符合jvm规范的字节码文件执行。也许很多工作很久的java工程师都不太清楚的一点:java语言和jvm虚拟机是两个不同的规范,概念。

所谓的Jython,groove都跟JRuby是类似的。

本文转载自:http://blog.csdn.net/cuirong1986/article/details/7986900

Zero零_度
粉丝 69
博文 1258
码字总数 257684
作品 0
程序员
私信 提问
hbase 数据库简介安装与常用命令的使用

一:hbase 简介与架构功能 二:hbase 安装与配置 三:hbase 常见shell 命令操作 一:hbase 简介与架构功能 1.1 为什么要使用hbase 数据库 1.2 hbase 简介: 1.3 HBase与Hadoop的对比 1.4 HB...

flyfish225
2018/04/12
0
0
HBase0.96.x开发使用(二) -- hbase shell命令

hbase shell命令 1、进入hbase shell环境: [hbase@hadoop230 ~]$ ./hbase shell HBase Shell; enter 'help<RETURN>' for list of supported commands. Type "exit<RETURN>" to leave the HB......

whatlly
2013/12/31
0
0
hbase shell中disable 和drop无法执行

1 通过hbase的web监控页面查询工作状态发现Regions in Transition区域有长时间未执行的任务,此时需要关闭hbase-master并重启,再这个问题处理过程中我直接使用/etc/init.d/hbase-master re...

CARYFLASH
2018/06/04
0
0
HBase shell的基本用法

hbase提供了一个shell的终端给用户交互。使用命令hbaseshell进入命令界面。通过执行 help可以看到命令的帮助信息。 以网上的一个学生成绩表的例子来演示hbase的用法。 name grad course mat...

超人学院
2015/05/27
0
0
2018-08-12期 Hbase本地模式安装部署

说明: Hbase部署模式有以下三种 (1)本地模式:本地模式不依赖于HDFS存储,将文件存储到操作系统本地目录,好处是我们不需要搭建HDFS集群,即可学些HBase相关命令及客户端操作。 (2)伪分...

JackmaSong
2018/08/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

一篇文章彻底搞懂Java虚拟机

概念: 虚拟机:指以软件的方式模拟具有完整硬件系统功能、运行在一个完全隔离环境中的完整计算机系统 ,是物理机的软件实现。常用的虚拟机有VMWare,Visual Box,Java Virtual Machine(Jav...

骚年锦时
31分钟前
0
0
C 语言 二级指针的使用

#include <stdio.h>#include <stdlib.h>typedef struct node Node;struct node {int data;struct node* next;struct node* prev;};Node head;Node* insert(Node......

小张525
今天
4
0
【大数据技术】——Hadoop(1)

什么是大数据 基本概念 《数据处理》 在互联网技术发展到现今阶段,大量日常、工作等事务产生的数据都已经信息化,人类产生的数据量相比以前有了爆炸式的增长,以前的传统的数据处理技术已经...

须臾之余
今天
9
0
比特币从地址逆向计算私钥

区块链 区块链简介 说到比特币,就不得不提区块链。那什么是区块链呢? 区块链本质是一个数据集,只不过数据的组织采用了比较特殊的方式,就是把数据拆分为一块一块的小数据集。 为什么要进行...

trayvon
今天
2
0
TypeScript……真香

写前端或者用 node 写命令行小工具一直采用的 es6 的语法,对于 TypeScript 则是秉持敬而远之的态度,毕竟团队中多推广一门语言所需要花费的精力都是让人望而却步的。所以对于 JavaScript 的...

郁也风
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部