HBase总结(1)-- 数据插入与Put对象
来源:互联网 发布:淘宝上哪家日代靠谱 编辑:程序博客网 时间:2024/05/17 14:18
一、介绍
HBase的客户端包中集中了CURD操作,用户可以通过其中不同种类的API尽心CURD操作。HBase数据插入使用Put对象,Put对象在进行数据插入时,首先会想Hbase集群发送一个RPC请求,得到响应后将Put类中的数据通过序列化的方式传给HBase集群,集群节点拿到数据后进行添加功能。
二、数据插入详解
HBase客户端拥有多重方式进行数据插入,通过调整不同的属性从而实现不同插入方式。
1、单行插入:put(Put p)
单行插入即每一次插入一行数据
public void put(String tableName,String rowKey,String family,String column,String value){Configuration conf=init();try {HTable table=new HTable(conf,TableName.valueOf(tableName));HBaseAdmin admin=new HBaseAdmin(conf);//判断表是否存在,如果不存在进行创建if(!admin.tableExists(Bytes.toBytes(tableName))){HTableDescriptor tableDescriptor=new HTableDescriptor(Bytes.toBytes(tableName));HColumnDescriptor columnDescriptor=new HColumnDescriptor(Bytes.toBytes(family));tableDescriptor.addFamily(columnDescriptor);admin.createTable(tableDescriptor);}table.setAutoFlush(true);//进行数据插入Put put=new Put(Bytes.toBytes(rowKey));put.add(Bytes.toBytes(family),Bytes.toBytes(column),Bytes.toBytes(value));table.put(put);table.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}
HTable.put(Put p)方法想表中添加一行数据。在此过程中会发送一次RPC操作进行请求,并将Put中的数据序列化以后传送给相应的服务器进行数据插入。
2、批量插入:put(List<Put> list)
批量插入中生成一个List容器,然后将多行数据全部转载到该容器中,然后通过客户端的代码一次将多行数据进行提交
public void putList(String tableName,String[] rowKeys,String[] families,String[] columns,String[] values){Configuration conf=init();try {HBaseAdmin admin=new HBaseAdmin(conf);HTable table=new HTable(conf,tableName.valueOf(tableName));int length=rowKeys.length;List<Put> putList=new ArrayList<>();if(!admin.tableExists(Bytes.toBytes(tableName))){System.err.println("the "+tableName+" is not exist");System.exit(1);}for(int i=0;i<length;i++){Put put=new Put(Bytes.toBytes(rowKeys[i]));put.add(Bytes.toBytes(families[i]),Bytes.toBytes(columns[i]),Bytes.toBytes(values[i]));putList.add(put);}table.put(putList);table.close();} catch (Exception e) {// TODO: handle exception}}多行插入的本质就是对List容器中的所有对象进行迭代,然后通过 HTable.put(Put p)方法进行多次插入操作。这样的批量操作将会发送多次PRC请求。
3、检查并写入:checkAndPut(byte[] row, byte[] family, byte[] qualifier, byte[] value,Put put)
该方法提供了一种原子性操作,即该操作如果失败,则操作中的所有更改都失效。该函数在多个客户端对同一个数据进行修改时将会提供较高的效率。
public void checkAndPut(String tableName,String row,String family,String column,String value){Configuration conf=init();try {HBaseAdmin admin=new HBaseAdmin(conf);if(!admin.tableExists(Bytes.toBytes(tableName))){System.err.println("the table "+tableName+" is not exist");System.exit(1);}HTable table=new HTable(conf, TableName.valueOf(tableName));Put put=new Put(Bytes.toBytes(row));put.addColumn(Bytes.toBytes(family),Bytes.toBytes(column),Bytes.toBytes(value));table.checkAndPut(Bytes.toBytes(row),Bytes.toBytes(family),Bytes.toBytes(column),null, put);table.flushCommits();} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}上述代码实现了只有在写入位置的值为Null的时候将才会将数据写入到数据库中。
注意:需要注意的时,checkAndPut方法以及类似的方法(统称为compact and set(CAS)操作)都只能对一行进行原子性操作。当checkAndPut函数中的参数row和参数put中的row不相同时,即该操作已经不再同一行中时,则会抛出异常。
org.apache.hadoop.hbase.DoNotRetryIOException: org.apache.hadoop.hbase.DoNotRetryIOException: Action's getRow must match the passed rowat org.apache.hadoop.hbase.regionserver.HRegion.checkAndMutate(HRegion.java:3276)at org.apache.hadoop.hbase.regionserver.RSRpcServices.mutate(RSRpcServices.java:2102)at org.apache.hadoop.hbase.protobuf.generated.ClientProtos$ClientService$2.callBlockingMethod(ClientProtos.java:32203)at org.apache.hadoop.hbase.ipc.RpcServer.call(RpcServer.java:2114)at org.apache.hadoop.hbase.ipc.CallRunner.run(CallRunner.java:101)at org.apache.hadoop.hbase.ipc.RpcExecutor.consumerLoop(RpcExecutor.java:130)at org.apache.hadoop.hbase.ipc.RpcExecutor$1.run(RpcExecutor.java:107)at java.lang.Thread.run(Thread.java:745)
4、缓存块操作
2方法虽然提供了批量操作,但实际的RPC请求次数没有任何的减少,因此put(List)和多次put(Put p)方法理论上的速率是相同的。而Put对象提供了一种可以打开Put缓存区的方式来提高数据提交的速率。该方式在客户端的内存中提供一块缓存区域,客户端并设置其大小,然后在用户每次进行提交时并不立刻将数据提交给Hbase集群中,而是当所有该缓存区已经满溢的时候将缓存区中的数据通过一次RPC操作,一次提交到HBase集群中去。所以缓存块在进行大量put请求,且数据量较小时将会明显提高效率。
public void startBufferAndInsert(String tableName,String[] rows,String[] families,String[] columns,String[] values) { Configuration conf=init(); try { //检查制定的表是否村存在 HBaseAdmin admin=new HBaseAdmin(conf); if(!admin.tableExists(Bytes.toBytes(tableName))) { System.err.println("the table "+tableName+" is not exist"); System.exit(1); } admin.close(); //创建表连接 HTable table=new HTable(conf,TableName.valueOf(tableName)); //将数据自动提交功能关闭 table.setAutoFlush(false); //设置数据缓存区域 table.setWriteBufferSize(64*1024*1024); //然后开始写入数据 int length=rows.length; for(int i=0;i<length;i++) { Put put=new Put(Bytes.toBytes(rows[i])); put.addColumn(Bytes.toBytes(families[i]),Bytes.toBytes(columns[i]),Bytes.toBytes(values[i])); table.put(put); } //刷新缓存区 table.flushCommits(); //关闭表连接 table.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } }使用缓存插入方式时,要注意将table的自动填充属性进行关闭,并且在数据插入完成后进行一次手动的提交操作。将缓存区中的数据手动的提交到HBase服务器中。
三、Put类详解
1、主要属性:KeyValue对象数组
Put类中主要含有一个KeyValue对象数组,KeyValue对象是HBase底层存储的一个重要类,代表了数据在底层存储时的状态。KeyValue对象代表了一个Hbase表中的一个数据单元,即含有行值(row)、列簇(family)、列(column)、时间戳(timestamp)和值(value),从这些信息能够在表中唯一确定一个数据单元。在KeyValue对象中,Key(键)包含了一个value值的row、family、column和timestamp信息,而value则是该表单元格的数据。
当插入一条数据时,其实就是讲KeyValue进行序列化后,然后传递后Hbase集群,集群在根据KeyValue的值进行相应的操作。
2、主要方法
(1)Put(byte[] row) / Put(byte[] row,RowLock lock)
初始化函数,一个Put对象值代表一行数据,但是因为其内部含有多个KeyValue键值对,Put对象可以填充多个列簇(family)、列(qualifier),甚至是多时间戳(timestampe)数据。第二个函数中有行锁(RowLock)参数,用户可以通过设定该参数指定一个行锁。一般来说系统在进行Put时会对put所在的行添加一个行锁。系统并不提倡用户自己定义行锁,因为可能在多个用户指定多个行锁时会造成死锁的情况,导致系统资源在两个客户端断开连接之前一直被占用。
(2)add(Cell kv) / add(byte[] family, byte[] qualifier, long ts, byte[] value
) /addColumn(byte[] family, ByteBuffer qualifier, long ts, ByteBuffer value
) / addImmutable(byte[] family, byte[] qualifier, long ts, byte[] value, org.apache.hadoop.hbase.Tag[] tag)
这四种方法都是想Put对象中添加单元数据,即增加一个KeyValue对象。
A、添加Cell对象,Cell类可以引用KeyVakue的对象,因此此处也可以插入KeyValue对象,因此即可将该函数理解为插入一个完整的KeyValue对象即可
B、添加列簇、列、时间戳、值,Put对象会在接收这些数据后将其初始化成一个KeyValue对象,不过该方法已经废弃,不建议使用
C、该方法和第二方法作用相同
D、添加恒定数据,通过该方法添加一个恒定的KeyValue对象值,具体效果没有试验过
(3)has(byte[] family, byte[] qualifier, byte[] value)
判断Put对象中是否含有制定的value值/列/列簇,返回值为Boolean值
(4)setWriteToWAL(boolean write)
是否将数据写入到预写日志(Write-Ahead-Log)中,预写日志是一种数据保护措施,如果当HBase某一个节点故障时,可以通过预写日志中的记录的数据操作进行数据恢复。该选项如果打开,数据会被写入到预写日志中,安全性增加,但是会损耗一定性能,如果不打开,则损耗变小,安全性降低
(5)setTTL(long ttl)
ttl毫秒数。该函数对该行中的所有的KeyValue对象设置TTL,TTL(Time-To-Live)的作用是从数据产生起,经过TTL时间后就会被作为废弃数据而被删除掉。
(6)setDurability(Durability d
)
该函数对写入WAL模式进行设定。可填充的值为:Durability.ASYNC_WAL(异步进行数据写入)、Durability.SYNC_WAL(同步进行写入)、Durabiliry.SKIP_WAL(不进行WAL填写)、Durability.FSYNC_WAL(强制同步进行WAL写入)、Durability.USE_DEFAULT(默认选项,为SYNC_WAL选项)
(7)其他方法
A、getRow() 获取创建Put实例时的行健
B、getRowLock() 获取创建Put实例时的行锁
C、getLockId() 返回使用rowlock参数传递给构造函数的可选的锁ID,当违背制定时放回-1L
D、getTimeStamp() 获取相应Put实例的时间戳,改制在构造函数中有ts参数传入,如果没有指定的话则返回 Long.MAX_VALUE
E、isEmpty() 返回该Put实例中是否含有KeyValue实例
F、numFamilies() 返回该Put实例中的列簇数量
G、size() 返回本次Put对象添加的KeyValue实例的数量
四、总结
通过Put的设计,我们能够体会到一些HBase底层的设计结构,因此需要好好理解KeyValue对象。上面便是笔者对Hbase Put进行输入插入的裂解,如果有什么错误的地方请指出,希望共同进步
- HBase总结(1)-- 数据插入与Put对象
- HBase table Put 插入数据
- HBase使用Put插入数据
- HBase总结(2)--数据查询与Get对象
- HBase总结(3)--数据删除与Delete对象
- HBase总结(4)--数据扫描与Scan对象
- HBase数据迁移(1)-使用HBase的API中的Put方法
- HBase数据迁移(1)-使用HBase的API中的Put方法 .
- hbase数据迁移put方法java代码
- Hbase源码研究(一)------put(1)
- HBase总结(十五)HBase数据恢复
- HBase——使用Put迁移MySql数据到Hbase
- 《hbase学习》-02-程序批量put数据到Hbase
- java 插入数据 hbase
- Hbase插入数据
- hbase插入数据分析
- hbase插入数据
- Hbase之插入数据
- 手把手教你编写一个具有基本功能的shell(已开源)
- hdoj 1811 Rank of Tetris【拓扑排序 + 并查集】
- Android Studio移除的Module如何恢复(转载)
- Hibernate配置文件(.cfg.xml)参考实例
- 架构(三层架构)、框架(MVC)、设计模式三者异同点
- HBase总结(1)-- 数据插入与Put对象
- 查找指定目录下的所有日志文件*.log perl
- android学习之LayoutParams
- vim 的使用
- Android之 看“马达”如何贯通Android系统 (从硬件设计 --> 驱动 --> HAL --> JNI --> Framework --> Application)
- C++高阶函数
- gdb 命令列表
- shell type使用
- 南京趋势科技面试-处子面