Hbase-API-概述、单多行put

来源:互联网 发布:mysql官网下载 编辑:程序博客网 时间:2024/05/22 21:22

概述
HBase的主要客户端接口是由org.apache.hbase.client包中的HTable类提供的,通过这个类,可以完成向HBase存储和检索数据,以及删除无效数据之类的操作。
HTable

  1. 所有的修改操作都保证行级别的原子性,这关系这一行的所有的并发读写操作,其它线程或客户端对同一行的读写操作不会影响该行数据的原子性(要么读到最新的修改,要么等待系统允许写入该行的修改)
  2. region服务器采用多版本并发控制机制(RWCC),该机制保证读程序可以不用等待写程序结束,而写程序必须等待其他写程序结束之后才能执行
  3. 在正常负载和常规操作下,客户端读操作不会受到其他修改数据的客户端的影响,他们的冲突忽略。(许多用户需要同时修改时,尽量使用批处理)
  4. 写操作中涉及的列的数目不会影响行级别的原子性(要么成功,要么失败,不会有其它状态),行级原子性会同时保护所有列
  5. 创建HTable实例是有代价的,每一个实例都需要扫描.META.表以检查该表是否存在、是否可用,还有一些其他操作,这些检查和操作导致实例调用非常耗时。(因此推荐只创建一个HTable实例,每个线程创建一个,然后复用)
  6. .META.表系统内置表,存region详细和分布,找regionserver。client数据操作->regionserver
  7. HTable需要先有表,才能进行操作。不然会报Not Found

CRUD操作
增、删、改、查都是HTable类提供的。

put方法:一类操作单行,一类操作多行
单行put
HTable下 put(Put put):这个方法以单个put或存储在列表中的一组Put对象为参数

Put构造函数:
Put(byte[] row)
Put(byte[] row,long ts)
创建Put时需提供一个行健row,HBase中每行数据都有唯一的行健(rowkey)作为标识,类型为Java的byte[]数组

HBase提供一个辅助类将Java类转为byte[]数组
Bytes类
static byte[] toBytes(ByteBuffer bb)
static byte[] toBytes(String s)……

创建Put实例之后,就向该实例添加数据
Put add(byte[] family,byte[] qualifier,byte[] value)
Put add(byte[] family,byte[] qualifier,long ts,byte[] value)
Put add(KeyValue kv):KeyValue(代表一个唯一的单元格) 是HBase的底层数据类型,Put放进去就成为KeyValue ,所有也可以直接添加KeyValue
KeyValue 类似一个协调系统,使用行健、列族、列限定符、时间戳指向一个单元格的值(这就是完整地址和实际数据),像一个三维立方系统(时间为第三维度)
每一次调用add都可以特定的添加一列数据,如果再加一个时间戳(用户指定,region服务器自动设定为当前时间)就成为一个单元格
获取Put实例内部添加的KeyValue需要调用get()

List<KeyValue> get(byte[] family,byte[] qualifier)//获取特定单元格的信息Map<byte[],List<KeyValue>> getFamilyMap()//遍历每一个可用KeyValue实例

检查是否存在特定单元格,而不需要遍历整个集合
boolean has(地址)

Put类还有其它方法,主要获得预设定内容(行键、大小、是否空等)

        Configuration conf = HBaseConfiguration.create();//创建所需的配置        HTable table = new HTable(conf,"testtable");//实例化一个新的客户端        Put put = new Put(Bytes.toBytes("row1"));//指定一行创建一个put        put.add(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),Bytes.toBytes("val1"));//添加colfam1:qual1列        table.put(put);//将这一行存到HBase的表中

通过客户端访问配置文件
应用程序通过默认位置(classpath)下的hbase-site.xml获知如何访问集群。也可在代码里指定集群的地址
无论哪种方式,都需要在代码中使用HBaseConfiguration类来处理配置属性,方法
static Configuration create()
static Configuration create(Configuration that)//使用一个已经存在的配置,融合并覆盖
create会载入两个配置文件hbase-site和hbase-default,用户自配置优先级更高
例:

Configuration conf = HBaseConfiguration.create();conf.set("hbase.zookeeper.quorum","zk1.foo.com,zk2.foo.com");

简单忽略任何外部客户端的配置文件,而在代码中直接配置


数据的版本化
必须更改版本
这里写图片描述


Put列表
客户端的API有批处理操作的高级特性。

//HTablevoid put(List<put> puts) throws IOException//只需建立一个Put实例的列表
        Configuration conf = HBaseConfiguration.create();        HTable table = new HTable(conf,"testtable");        List<Put> puts = new ArrayList<Put>();        Put put = new Put(Bytes.toBytes("rowt3"));        put.add(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),Bytes.toBytes("val1"));        puts.add(put);        Put put1 = new Put(Bytes.toBytes("rowt2"));        put1.add(Bytes.toBytes("colfam1"),Bytes.toBytes("qual1"),Bytes.toBytes("val2"));        puts.add(put1);        Put put2 = new Put(Bytes.toBytes("rowt3"));        put2.add(Bytes.toBytes("colfam1"),Bytes.toBytes("qual2"),Bytes.toBytes("val2"));        puts.add(put2);        table.put(puts);

由于用户提交的修改可能涉及多行,所以可能部分会失败。原因很多:

  1. 一个远程的region服务器出现问题,导致客户端重试次数超过配置最大值,不得不放弃当前操作(错误会通过随后的IOE反馈给客户端)
  2. 使用一个错误的列族名。(客户端不知道远程表的结构,因此对列族的检查会在服务器段完成)
//插入一个错误的列族HTable table = new HTable(conf,"testtable");        Put put2 = new Put(Bytes.toBytes("rowt3"));        put2.add(Bytes.toBytes("BOGUS"),Bytes.toBytes("qual2"),Bytes.toBytes("val2"));        table.put(put2);//错误的列族会调用失败返回RetriesExhaustedWithDetailsException//如果是列表操作,正确的会添加进HBase中//服务器会遍历所有的操作并设法执行他们,失败的返回,然后客户端使//用RetriesExhaustedWithDetailsException报告远程错误//这些在服务器上失败的Put实例会被保存在本地的写缓冲区中,下一次缓冲区//刷写的时候重试//用户也可以通过HTable的getWriteBuffer方法访问它们,并做处理

有一些检查会在客户端进行,如,put是否为空。这种情况客户端会抛出异常,同时将出错的Put留在客户端写缓冲区中不处理
调用列表实例Put时,客户端会将所有的Put实例插入本地缓冲区中,隐式的调用flushCache。在插入每一个Put时客户端都会做检查。如果失败,例,5个实例第三个失败,前两个加入缓冲区中,后两个不会触发刷写命令

//向HBase中插入一个空的Put实例        Put put2 = new Put(Bytes.toBytes("rowt3"));        puts.add(put2);        try{        table.put(puts);        }catch(Exception e){            e.printStackTrace();            table.flushCommits();            }//如果客户端激活了写缓冲区功能,不会马上报告异常,而是延迟到缓冲区刷写时才抛出

基于列表的Put调用时:用户无法控制服务器端执行put的顺序
如果要保证写写入顺序,减少每批处理数量,并显示的刷写客户端缓冲区,强制把操作发送到远程服务器

原创粉丝点击