大型网站架构设计-HBase 简单操作API

2014-12-8 13:09:46     28 人阅读    

除了通过shell进行操作,HBase作为分布式数据库,自然也提供程序访问的接口,此处以 Java为例。
首先,需要配置HBase的HMaster服务器地址和对应的端口(默认为60000),以及对应的 ZooKeeper服务器地址和端口:

private static Configuration conf = null; static {
conf = HBaseConfiguration.create(); conf = HBaseConfiguration.create();
conf .set("hbase.ZooKeeper.property.clientPort", "2181"); conf .set("hbase.ZooKeeper.quorum", "192.168.136.135"); conf .set("hbase.master", "192.168.136.135:60000");
}


接下来,通过程序来新增user表,user表中有三个列族,分别为info、class、parent,如果
该表已经存在,则先删除该表:

public static void createTable() throws Exception {
String tableName = "user";
HBaseAdmin hBaseAdmin = new HBaseAdmin( conf); if (hBaseAdmin.tableExists(tableName)) { hBaseAdmin.disableTable(tableName); hBaseAdmin.deleteTable(tableName);
}
HTableDescriptor tableDescriptor = new
HTableDescriptor(TableName.valueOf(tableName)); tableDescriptor.addFamily(new HColumnDescriptor("info")); tableDescriptor.addFamily(new HColumnDescriptor("class")); tableDescriptor.addFamily(new HColumnDescriptor("parent")); hBaseAdmin.createTable(tableDescriptor); hBaseAdmin.close();
}

将数据添加到user表,每个列族指定一个列col,并给该列赋值:

public static void putRow() throws Exception {
String tableName = "user";
String[] familyNames = {"info","class","parent"};
HTable table = new HTable(conf, tableName); for(int i = 0; i < 20; i ++){
for (int j = 0; j < familyNames.length; j++) {
Put put = new Put(Bytes. to^y^tes (i + "")); put.add(Bytes.toBytes (familyNames[j]),
Bytes.toBytes("col"),
Bytes.toBytes("value_"+i+"_"+j)); table.put(put);
}
}
table.close();
}

取得rowkey为1的行,并将该行打印出来:

public static void getRow() throws IOException {
String tableName = "user";
String rowKey = "1";
HTable table = new HTable(conf, tableName);
Get g = new Get(Bytes.toBytes(rowKey));
Result r = table.get(g); outputResult(r); table.close();
}
public static void outputResult(Result rs){
List<Cell> list = rs.listCells();
System.out.println("row key : " + new String(rs.getRow())); for(Cell cell : list){
System.out.println("family: " + new String(cell.getFamily()) + ", col: " + new String(cell.getQualifier())
+ ", value: " + new String(cell.getValue()));
}
}

scan扫描user表,并将查询结果打印出来:

public static void scanTable() throws Exception {
String tableName = "user";
HTable table = new HTable(conf, tableName);
Scan s = new Scan();
ResultScanner rs = table.getScanner(s); for (Result r : rs) { outputResult(r);
}
//设置startrow和endrow进行查询 s = new Scan("2".getBytes(),"6".getBytes()); rs = table.getScanner(s); for (Result r : rs) { outputResult(r);
}
table.close();
}

删除rowkey为1的记录:

public static void deleteRow( ) throws IOException {
String tableName = "user";
String rowKey = "1";
HTable table = new HTable(conf, tableName);
List<Delete> list = new ArrayList<Delete>();
Delete d = new Delete(rowKey.getBytes());
list.add(d);
table.delete(list);
table.close();
}

rowkey 设计
要想访问HBase的行,只有三种方式,一种是通过指定rowkey进行访问,另一种是指定 rowkey的range进行scan,再者就是全表扫描。由于全表扫描对于性能的消耗很大,扫描一张 上亿行的大表将带来很大的开销,以至于整个集群的吞吐都会受到影响。因此,rowkey设计的 好坏,将在很大程度上影响表的查询性能,是能否充分发挥HBase性能的关键。
举例来说,假设使用HBase来存储用户的订单信息,我们可能会通过这样几个维度来记录 订单的信息,包括购买用户的id、交易时间、商品id、商品名称、交易金额、卖家id等。假设 需要从卖家维度来查看某商品已售出的订单,并且按照下单时间区间来进行查询,那么订单表 可以这样设计:
rowkey : seller_id + auction_id + create_time
      :order_info(auction_title,price,user_id)
使用卖家id+商品id+交易时间作为表的rowkey,列族为order,该列族包含三列,即商品 标题、价格、购买者id,如图2-13所示。由于HBase的行是按照rowkey来排序的,这样通过 rowkey进行范围查询,可以缩小scan的范围。

图2-13根据rowkey进行表的scan

而假设需要从购买者维度来进行订单数据的查询,展现用户购买过的商品,并且按照购买 时间进行查询分页,那么rowkey的设计又不同了:
rowkey : user_id + create_time :order_info(auction_id,auction_title,price,seller_id)
这样通过买家id+交易时间区间,便能够查到用户在某个时间范围内因购买所产生的订单。

但有些时候,我们既需要从卖家维度来查询商品售出情况,又需要从买家维度来查询商品 购买情况,关系型数据库能够很好地支持类似的多条件复杂查询。但对于HBase来说,实现起 来并不是那么的容易。基本的解决思路就是建立一张二级索引表,将查询条件设计成二级索引 表的rowkey,而存储的数据则是数据表的rowkey,这样就可以在一定程度上实现多个条件的查 询。但是二级索引表也会引入一系列的问题,多表的插入将降低数据写入的性能,并且由于多 表之间无事务保障,可能会带来数据一致性的问题19。


          与传统的关系型数据库相比,HBase有更好的伸缩能力,更适合于海量数据的存储和处理。 由于多个Region Server的存在,使得HBase能够多个节点同时写入,显著提高了写入性能,并 且是可扩展的。但是,HBase本身能够支持的查询维度有限,难以支持复杂查询,如group by、 order by、join等,这些特点使得它的应用场景受到了限制。当然,这也并非是不可弥补的硬伤, 通过后面章节所介绍的搜索引擎来构建索引,可以在一定程度上解决HBase复杂条件组合查询 的问题。

本文出自   《大型分布式网站架构设计与实践试读样章》 试读,如果感觉到对你有帮助可以去购买该书


原文地址:http://www.itmmd.com/201412/276.html
该文章由 萌萌的IT人 整理发布,转载须标明出处。

linux命令详解(14)shell脚本学习,创建简单的shell脚本   上一篇
下一篇  产品经理学习笔记(7)-如何有效地发现需求

精彩回复
发表评论
姓名:       

《程序员app》专门为程序员量身定做!