该实例中需要建立的四张表:
微博表:用来存贮所有的人发布的所有微博;
关注人表:用来存贮自己所关注的人;
粉丝表:用来存贮自己的粉丝;
收信箱表:用来存贮关注的人所发布的微博。
在Hbase模拟微博的实例中,行键的设计如下:
表名 | 行键 |
微博表 | 用户ID+时间戳 |
关注人表 | 用户ID |
粉丝表 | 用户ID |
收信箱表 | 用户ID |
对于关注人表中用户的关注人的存贮采用的是宽表的形式,即一个被关注的人占一列,这样的好处是只需get一行数据就可以获得所有的关注人,且增删关注人都是原子操作,粉丝表的设计同理。
收信箱记录关注人所发表的微博的行键,即其用户ID+时间戳,对于同一用户人发表的多条微博的记录也是采用的宽表的设计形式,用户每发表一条微博都会在收信箱表其粉丝行里增加一列。
操作HBase数据库的类:
package mblog;
import java.io.IOException;
import java.util.ArrayList;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellScanner;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Bytes;
public class HBase {
static Configuration cfg = HBaseConfiguration.create();
public static int create(String tablename, String [] columnFamilys)
throws MasterNotRunningException, ZooKeeperConnectionException,
IOException {
HBaseAdmin admin = new HBaseAdmin(cfg);
int retflag = 0;
if (admin.tableExists(tablename)) {
System.out.println("table exists!");
retflag = 1;
} else {
HTableDescriptor tableDescriptor = new HTableDescriptor(tablename);
for(String s : columnFamilys){
HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(s);
hColumnDescriptor.setMinVersions(1000);
tableDescriptor.addFamily(hColumnDescriptor);
}
admin.createTable(tableDescriptor);
System.out.println("create table successfully!");
retflag = 0;
}
admin.close();
return retflag;
}
public static void put(String tableName, String row, String familyName,
String column, String value) throws IOException {
HTable table = new HTable(cfg, tableName);
Put p1 = new Put(Bytes.toBytes(row));
p1.add(Bytes.toBytes(familyName), Bytes.toBytes(column), Bytes.toBytes(value));
table.put(p1);
System.out.println("put ok");
table.close();
}
public static void get(String tablename, String row) throws IOException{
HTable table = new HTable(cfg, tablename);
Get g1 = new Get(Bytes.toBytes(row));
Result result = table.get(g1);
// List list = (List) result.getColumn("f1".getBytes(), "c1".getBytes());
// Iterator it = list.iterator();
// while(list.){
// System.out.println(o);
// }
System.out.println("get: " + result);
table.close();
}
public static ArrayList<String> getAllColumns(String tablename, String row, String family) throws IOException{
HTable table = new HTable(cfg, tablename);
Get g1 = new Get(Bytes.toBytes(row));
g1.addFamily(Bytes.toBytes(family));
Result result = table.get(g1);
ArrayList<String> arrayList = new ArrayList<String>();
if(result.listCells() != null){
for(Cell cell : result.listCells()){
arrayList.add(new String(cell.getValue()));
}
}
table.close();
return arrayList;
}
public static void scan(String tableName) throws IOException{
HTable table = new HTable(cfg, tableName);
Scan scan = new Scan();
ResultScanner res = table.getScanner(scan);
for(Result r : res){
System.out.println(r);
}
table.close();
}
public static boolean delete(String tablename) throws MasterNotRunningException, ZooKeeperConnectionException, IOException{
HBaseAdmin admin = new HBaseAdmin(cfg);
if(admin.tableExists(tablename)){
try{
admin.disableTable(tablename);
admin.deleteTable(tablename);
}
catch (Exception e){
e.printStackTrace();
return false;
}
}
return true;
}
}
模拟微博的类,重点时row key的设计:
package mblog;
import hadoop.Hbase;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.collections.map.HashedMap;
import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.util.Bytes;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
public class Mblog {
public static String tmblog = "tmblog";
public static String tfocus = "tfocus";
public static String tfans = "tfans";
public static String trcvbox = "trcvbox";
public static int createTable() throws MasterNotRunningException, ZooKeeperConnectionException, IOException{
int retflag = 0;
//创建微博表
String [] columnFamilys = new String[2];
columnFamilys[0] = "f1";
columnFamilys[1] = "f2";
retflag += HBase.create(tmblog, columnFamilys);
//创建关注人表
retflag += HBase.create(tfocus, columnFamilys);
//创建粉丝表
retflag += HBase.create(tfans, columnFamilys);
//创建收信箱
retflag += HBase.create(trcvbox, columnFamilys);
return retflag;
}
public static void publish(String uid, String content) throws IOException{
String tableName = tmblog;
String row = uid + "_" + System.currentTimeMillis();
String columnFamily = "f1";
String column = "cont";
HBase.put(tableName, row, columnFamily, column, content);
//向uid的fans收信箱中发送row
ArrayList<String> fans = getFans(uid);
for(String fan : fans){
sendMessage(fan, row);
}
}
public static void addFocus(String uid, String who) throws IOException{
String columnFamily = "f1";
HBase.put(tfocus, uid, columnFamily, who, who);
HBase.put(tfans, who, columnFamily, uid, uid);
}
public static ArrayList<String> getFans(String uid) throws IOException{
return HBase.getAllColumns(tfans, uid, "f1");
}
public static void sendMessage(String uid, String column) throws IOException{
HBase.put(trcvbox, uid, "f1", column, column);
}
public static Multimap<String, String> getMessage(String uid) throws IOException{
Multimap<String, String> multimap = ArrayListMultimap.create();
ArrayList<String> blogs = HBase.getAllColumns(trcvbox, uid, "f1");
for(String blog : blogs){
ArrayList<String> tmp = HBase.getAllColumns(tmblog, blog, "f1");
String [] sz = blog.split("_");
multimap.putAll(sz[0], tmp);
}
Iterator it = multimap.entries().iterator();
while(it.hasNext()){
Map.Entry<String, String> entry = (Entry<String, String>) it.next();
System.out.println(entry.getKey() + ": " + entry.getValue());
}
return multimap;
}
public static void main(String [] args){
try{
int ret = createTable();
addFocus("xiaoming", "xiaohong");
addFocus("xiaoming", "xiaoqiang");
addFocus("xiaoming", "xiaozhang");
addFocus("x1", "xiaoming");
addFocus("x2", "xiaoming");
addFocus("x3", "xiaoming");
publish("xiaoming", "today is rainning day!");
publish("xiaohong", "My shirt is beautiful!");
publish("xiaoqiang", "I will climb tomorrow!");
publish("xiaohong", "The cake is very nice!");
publish("xiaoming", "I like socker!");
System.out.println("=======xiaoming's blog=======");
getMessage("xiaoming");
System.out.println();
System.out.println("=======x1's blog=======");
getMessage("x1");
System.out.println();
}
catch(Exception e){
e.printStackTrace();
}
}
}