基于 hadoop 文件系统以及 Hbase 的微博系统

一、部署前提

1.在Linux环境

2.安装部署了hadoop

3.安装部署了hbase

4.安装了web应用服务器,如tomcat、或者jetty等

5.部署struts2

二、应用介绍

     以基于Hbase的hadoop为数据库,实现用户发布微博和,关注用户及等功能,涉及到Hbase表结构设计,相应实现的Java API等一些内容。使用hbase作为微博系统的数据存储平台有如下好处:根据微博系统的特点,微博用户数量庞大,且关注和被关注数据严重不相等,这些特点刚好可以通过hbase分布式处理数据的一些特性得以满足,如果使用旧的关系数据库可能对一个单独的服务器要求非常之高。

三、部分实现

由于篇幅较长,就用最常见的用户注册和登录来举例说明,其他功能其实都类似,总的架构来说都是比较熟悉的MVC,浏览器发送请求到服务器,通过struts分发请求,最终结果又返回到浏览器。

1.用户注册/登录,前台页面就不一一描述了,就是普通的输入用户名密码然后点击注册/登录等。

struts配置



<action name="user_register" class="org.robby.UserAction" method="register">
<result>/login.jsp</result>
</action>

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值

tab_globle
字段名 家族名:列名
user_id param:userid
tab_users
字段名 家族名 列名1 列名2
userid info 用户名 密码


由于hbase获取数据的时候,必须通过字段名,而不能直接像关系型数据库一样通过用户名去获取,所以这样的设计必须全表扫描后把结果通过Java处理以后再比较,可想而知这样的设计是有问题的,如果数据量很大的话这肯定是一个令人崩溃的事情。

Para obtener más información sobre las optimizaciones del compilador, consulte el aviso sobre la optimización.