批量操作
如果我们去查看HBaseAPI
的源码会发现,在上次实训中我们使用的delete、get,put
这些批量操作,实际上都是调用了batch()
方法。
查看put(List<Put> puts)
函数源码:
我们可以发现put(List<Put> puts)
方法最终还是调用的batch(final List<? extends Row> actions, final Object[] results, int rpcTimeout)
,其他get
和delete
的批量操作也同样。
所以我们如果既有get
操作又有Put
操作那是不是可以整合在一起呢?
答案是肯定的。
我们来看个例子:
List<Row> rows = new ArrayList<>();
//上传操作
Put put = new Put(Bytes.toBytes("row1"));
put.addColumn(Bytes.toBytes("data"),Bytes.toBytes("2"), Bytes.toBytes("value1"));
rows.add(put);
//删除操作
Delete delete = new Delete(Bytes.toBytes("row1"));
delete.addColumn(Bytes.toBytes("data"),Bytes.toBytes("1"));
rows.add(delete);
//获取操作
Get get = new Get(Bytes.toBytes("row1"));
get.addColumn(Bytes.toBytes("data"),Bytes.toBytes("2"));
rows.add(get);
//定义结果数组长度
Object[] results = new Object[rows.size()];
table.batch(rows, results);//这是一个同步的操作,批量操作的结果将会在操作之后放在results中
for (Object object : results) {
System.out.println(object.toString());
}
上述代码delete
和put
操作的结果为keyvalues=NONE
,即没有结果,当然如果get
操作没有获取到结果也会输出keyvalues=NONE
。 有结果则会输出类似这样的数据:keyvalues={row1/data:1/1543220978519/Put/vlen=7/seqid=0}
是一个Result
类型的对象。
值的注意的是:最好不要将put和delete操作放在同一个批处理的请求中,因为这样会有很大的风险。在学习多线程的时候我们学过多线程三大特性之一有序性,也许会因为其他原因导致操作的实现顺序不同,这样会产生不可预料的结果,还有就是资源竞争,会使结果波动。
上述使用的是同步的方式进行批量操作,其实API
还提供了一个异步执行的方法
table.batchCallback(actions, results, callback):
batchCallback(
final List<? extends Row> actions, final Object[] results, final Batch.Callback<R> callback)
在我们需要使用异步执行批量操作,并且想要获取异步执行结果的时候可以考虑使用batchCallback()
方法,Batch.Callback<R> callback
就是异步执行结果的监听器。
编程要求
纸上得来终觉浅,我们来实际操练吧,在右侧编辑器begin-end
处编写代码补全batchOp(String tablename)
函数,参数:tablename
为待操作表的表名,要求实现如下操作:
- 删除表中行键为
row1
,row2
的行; - 获取表中行键为
row3
,row10
的行; - 四个操作需要依照以上先后顺序,即先删除在获取
row3,row10
。
不需要你直接输出,只需要将批量操作的执行结果作为返回值返回即可
package step1;
import java.util.ArrayList;
import java.util.List;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.client.coprocessor.Batch;
import org.apache.hadoop.hbase.util.Bytes;
public class Task {
public Object[] batchOp(String tablename) throws Exception {
/********* Begin *********/
Configuration conf = HBaseConfiguration.create();
Connection conn = ConnectionFactory.createConnection(conf);
Table table = conn.getTable(TableName.valueOf(tablename));
List<Row> rows = new ArrayList<>();
//删除操作
Delete delete = new Delete(Bytes.toBytes("row1"));
Delete delete2 = new Delete(Bytes.toBytes("row2"));
rows.add(delete);
rows.add(delete2);
//获取操作
Get get = new Get(Bytes.toBytes("row3"));
Get get2 = new Get(Bytes.toBytes("row10"));
rows.add(get);
rows.add(get2);
//定义结果数组长度
Object[] results = new Object[rows.size()];
table.batch(rows, results);//这是一个同步的操作,批量操作的结果将会在操作之后放在results中
//delete和put操作的结果为NONE 即没有结果
return results;
/********* End *********/
}
}
start-dfs.sh
start-hbase.sh