1、需求分析
- 假设用Hbase来实现微博应用业务中所有的数据存储,如何设计Hbase的表?
- 发微博
- 需要一张表A,存储用户所发的微博
- 文字、图片、话题、连接、视频
- 关注别人
- 需要一张表B来存储用户之间的关系
- 关系:A关注了B
- 关注:A多了一个关注用户
- 粉丝:B多了一个粉丝用户
- 产生了两条数据
- 取关别人
- 刷微博
- 要看到我们关注的人所发的最新的微博
- 需要有一张C,用于记录每个用户所关注的人所发的微博表A中的rowkey
2、表设计
微博内容表:记录所有人发的微博
- 每个用户发一条微博,就存储一条
- rowkey:userid_timestamp
- family:info
- column
用户关系表:用于记录用户之间的关系
- 只要产生了关注,就发生了关系的构建
- A关注了B
- 每个人都能看到自己关注的人的列表和粉丝的列表
- rowkey:userid
- family
- attend:存储用户所关注的用户的id
- fans:存储当前用户所有粉丝的id
- column
- attend:关注的人的userid作为列的名称
- 只要我有一个关注的用户,attend列族中就有用户id这一列
- fans:粉丝的usereid作为列的名称
- value
微博邮件箱表:用于记录所有人关注的用户所发的微博的rowkey
- 用户A刷微博,要推送A关注的B、C、D所发的最新的微博
- B、C、D所发的最新的微博,都存储在微博内容表中
- 通过这张表来记录每个用户所发的微博的rowkey
- rowkey:userid
- 列族:info
- 列:关注的人
- B
B_20200101123012
B_20200101123013
C_20200101123012
D_20200101123012
- 值:所关注的人所发的微博在内容表中的rowkey
- 通过多版本来记录一个用户发的多条微博的rowkey
3、代码实现
public class WeiboHbaseTest {
private String weiboContent = "weibo:weiboContent";
private String weiboRelation = "weibo:weiboRelation";
private String weiboEmail = "weibo:weiboEmail";
String table1Cf = "info";
String table2Cf1 = "attend";
String table2Cf2 = "fans";
String table3Cf = "cf";
public static void main(String[] args) throws IOException {
WeiboHbaseTest weibo = new WeiboHbaseTest();
weibo.createWeiboNameSpace();
weibo.createWeiboTable();
weibo.publishWeibo("userid","content");
weibo.addAttend("a","b");
weibo.removeAttend("a","b");
weibo.flushWeibo("A");
}
private void flushWeibo(String a) throws IOException {
Connection conn = getConnect();
Table table1 = conn.getTable(TableName.valueOf(weiboContent));
Table table3 = conn.getTable(TableName.valueOf(weiboEmail));
Get get = new Get(Bytes.toBytes(a));
get.addFamily(Bytes.toBytes(table3Cf));
Result result = table3.get(get);
for(Cell cell:result.rawCells()){
byte[] weiboRow = CellUtil.cloneValue(cell);
Get get1 = new Get(weiboRow);
Result result1 = table1.get(get1);
for(Cell content : result1.rawCells()){
}
}
}
private void removeAttend(String a, String b) throws IOException {
Connection conn = getConnect();
Table table1 = conn.getTable(TableName.valueOf(weiboContent));
Table table2 = conn.getTable(TableName.valueOf(weiboRelation));
Table table3 = conn.getTable(TableName.valueOf(weiboEmail));
Delete deleteFans = new Delete(Bytes.toBytes(b));
deleteFans.addColumn(Bytes.toBytes(table2Cf2),Bytes.toBytes(a));
table2.delete(deleteFans);
Delete deleteAttend = new Delete(Bytes.toBytes(a));
deleteAttend.addColumn(Bytes.toBytes(table2Cf1),Bytes.toBytes(b));
table2.delete(deleteAttend);
Delete delete = new Delete(Bytes.toBytes(a));
delete.addColumn(Bytes.toBytes(table3Cf),Bytes.toBytes(b));
table3.delete(delete);
}
private void addAttend(String a, String b) throws IOException {
Connection conn = getConnect();
Table table1 = conn.getTable(TableName.valueOf(weiboContent));
Table table2 = conn.getTable(TableName.valueOf(weiboRelation));
Table table3 = conn.getTable(TableName.valueOf(weiboEmail));
Put putFans = new Put(Bytes.toBytes(b));
putFans.addColumn(Bytes.toBytes(table2Cf2),Bytes.toBytes(a),Bytes.toBytes(a));
table2.put(putFans);
Put putAttend = new Put(Bytes.toBytes(a));
putAttend.addColumn(Bytes.toBytes(table2Cf1),Bytes.toBytes(b),Bytes.toBytes(b));
table2.put(putAttend);
Scan scan = new Scan();
PrefixFilter prefixFilter = new PrefixFilter(Bytes.toBytes(b));
scan.setFilter(prefixFilter);
ResultScanner scanner = table1.getScanner(scan);
for (Result result : scanner) {
byte[] row = result.getRow();
Put put = new Put(Bytes.toBytes(a));
put.addColumn(Bytes.toBytes(table3Cf),Bytes.toBytes(b),row);
table3.put(put);
}
}
private void publishWeibo(String userid, String content) throws IOException {
Connection conn = getConnect();
Table table1 = conn.getTable(TableName.valueOf(weiboContent));
Table table2 = conn.getTable(TableName.valueOf(weiboRelation));
Table table3 = conn.getTable(TableName.valueOf(weiboEmail));
long time = System.currentTimeMillis();
Put putToTable1 = new Put(Bytes.toBytes(userid + "_" + time));
putToTable1.addColumn(Bytes.toBytes(table1Cf),Bytes.toBytes("content"),Bytes.toBytes(content));
table1.put(putToTable1);
Get getFans = new Get(Bytes.toBytes(userid));
getFans.addFamily(Bytes.toBytes(table2Cf2));
Result result = table2.get(getFans);
for(Cell cell : result.rawCells() ){
byte[] fansId = CellUtil.cloneQualifier(cell);
Put putToTable3 = new Put(fansId);
putToTable3.addColumn(Bytes.toBytes(table3Cf),Bytes.toBytes(userid),Bytes.toBytes(userid+"_"+time));
table3.put(putToTable3);
}
}
private void createWeiboTable() throws IOException {
HBaseAdmin admin = getAdmin();
HTableDescriptor desc1 = new HTableDescriptor(TableName.valueOf(weiboContent));
HColumnDescriptor info = new HColumnDescriptor(Bytes.toBytes(table1Cf));
desc1.addFamily(info);
admin.createTable(desc1);
HTableDescriptor desc2 = new HTableDescriptor(TableName.valueOf(weiboRelation));
HColumnDescriptor attend = new HColumnDescriptor(Bytes.toBytes(table2Cf1));
HColumnDescriptor fans = new HColumnDescriptor(Bytes.toBytes(table2Cf2));
desc2.addFamily(attend);
desc2.addFamily(fans);
admin.createTable(desc2);
HTableDescriptor desc3 = new HTableDescriptor(TableName.valueOf(weiboEmail));
HColumnDescriptor cf = new HColumnDescriptor(Bytes.toBytes(table3Cf));
cf.setMaxVersions(1000);
cf.setBlockCacheEnabled(true);
desc3.addFamily(cf);
admin.createTable(desc3);
}
private void createWeiboNameSpace() throws IOException {
HBaseAdmin admin = getAdmin();
NamespaceDescriptor descriptor = NamespaceDescriptor.create("weibo").build();
admin.createNamespace(descriptor);
}
public HBaseAdmin getAdmin() throws IOException {
Connection conn = getConnect();
HBaseAdmin admin = (HBaseAdmin) conn.getAdmin();
return admin;
}
public Connection getConnect() throws IOException {
Configuration conf = HBaseConfiguration.create();
Connection conn = ConnectionFactory.createConnection(conf);
return conn;
}
}