一、部署前提
1.在Linux环境
2.安装部署了hadoop
3.安装部署了hbase
4.安装了web应用服务器,如tomcat、或者jetty等
5.部署struts2
二、应用介绍
以基于Hbase的hadoop为数据库,实现用户发布微博和,关注用户及等功能,涉及到Hbase表结构设计,相应实现的Java API等一些内容。使用hbase作为微博系统的数据存储平台有如下好处:根据微博系统的特点,微博用户数量庞大,且关注和被关注数据严重不相等,这些特点刚好可以通过hbase分布式处理数据的一些特性得以满足,如果使用旧的关系数据库可能对一个单独的服务器要求非常之高。
三、部分实现
由于篇幅较长,就用最常见的用户注册和登录来举例说明,其他功能其实都类似,总的架构来说都是比较熟悉的MVC,浏览器发送请求到服务器,通过struts分发请求,最终结果又返回到浏览器。
1.用户注册/登录,前台页面就不一一描述了,就是普通的输入用户名密码然后点击注册/登录等。
struts配置
UserAction类实现
mport org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Result;
import com.opensymphony.xwork2.ActionSupport;
public class UserAction extends ActionSupport {
String username;
String password;
String status;
HbaseIf hbase;
public String register() throws Exception{
hbase = new HbaseIf();
hbase.create_new_user(username, password);
return SUCCESS;
}
public String login() throws Exception{
Long userid = null;
hbase = new HbaseIf();
userid = hbase.getUser(username, password);
System.out.println(username+":"+password);
System.out.println(userid.intValue());
if(userid.intValue() > 0)
return SUCCESS;
return ERROR;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
hbaseif类实现
import java.io.IOException;
import java.util.List;
import java.util.NavigableMap;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
public class HbaseIf {
Configuration conf;
HbaseIf() {
conf = HBaseConfiguration.create();
}
public long getNewUserId() throws IOException {
HTable table = new HTable(conf, "tab_global");
long n = table.incrementColumnValue(Bytes.toBytes("row1"),
Bytes.toBytes("param"), Bytes.toBytes("userid"), 1);
table.close();
return n;
}
public boolean create_new_user(String name, String password)
throws IOException {
HTable tab_global = new HTable(conf, "tab_global");
HTable tab_users = new HTable(conf, "tab_users");
if (tab_users.exists(new Get(name.getBytes())))
return false;
long id = tab_global.incrementColumnValue(Bytes.toBytes("row1"),
Bytes.toBytes("param"), Bytes.toBytes("userid"), 1);
Put put = new Put(Bytes.toBytes(id));
put.add(Bytes.toBytes("info"), Bytes.toBytes("username"),
Bytes.toBytes(name));
put.add(Bytes.toBytes("info"), Bytes.toBytes("pwd"),
Bytes.toBytes(password));
tab_users.put(put);
return true;
}
// create table
public void create_table(String table_name, String fms[]) throws Exception {
HBaseAdmin admin = new HBaseAdmin(conf);
if (admin.tableExists(table_name)) {
System.out.println("table already created!");
return;
}
HTableDescriptor des = new HTableDescriptor(table_name);
for (int i = 0; i < fms.length; i++) {
des.addFamily(new HColumnDescriptor(fms[i]));
}
admin.createTable(des);
admin.close();
System.out.println("table already created!");
}
public Long getUser(String name, String password) throws Exception {
Long id = (long) 0;
HTable tab_users = new HTable(conf, "tab_users");
Scan s = new Scan();
ResultScanner rs = tab_users.getScanner(s);
for (Result r : rs) {
KeyValue[] kv = r.raw();
for (int i = 0; i < kv.length; i++) {
//System.out.print(new String(kv[i].getRow()) + "");
// System.out.print(new String(kv[i].getFamily()) + ":");
// System.out.print(new String(kv[i].getQualifier()) + "");
// System.out.print(kv[i].getTimestamp() + "");
// System.out.println(new String(kv[i].getValue()));
if(new String(kv[i].getQualifier()).equals("pwd")&&new String(kv[i].getValue()).equals(password))
{
if(new String(kv[i+1].getQualifier()).equals("username")&&new String(kv[i+1].getValue()).equals(name))
{
System.out.println(Bytes.toLong(kv[i].getRow()));
id = Bytes.toLong(kv[i].getRow());
}
}
}
}
return id;
}
}
其中校验用户的算法有点拙劣,这跟hase表结构设计有莫大关系,特别是对rowkey的设计,所以hbase项目设计的时候要特别关注根据具体的项目特点设计良好的表结构。
以下是我设计的tab_globle和tab_users表,tab_globle用于存储当前最大的userid值
字段名 | 家族名:列名 |
user_id | param:userid |
字段名 | 家族名 | 列名1 | 列名2 |
userid | info | 用户名 | 密码 |