hbase--小案例

1、需求分析

  • 假设用Hbase来实现微博应用业务中所有的数据存储,如何设计Hbase的表?
  • 发微博
    • 需要一张表A,存储用户所发的微博
    • 文字、图片、话题、连接、视频
  • 关注别人
    • 需要一张表B来存储用户之间的关系
    • 关系:A关注了B
      • 关注: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作为列的名称
      • 只要有一个粉丝,fans列族下就有这一列
  • value
    • 存储用户的id

微博邮件箱表:用于记录所有人关注的用户所发的微博的rowkey

  • 用户A刷微博,要推送A关注的B、C、D所发的最新的微博
  • B、C、D所发的最新的微博,都存储在微博内容表中
  • 通过这张表来记录每个用户所发的微博的rowkey
  • rowkey:userid
    • A
  • 列族:info
  • 列:关注的人
  • B
B_20200101123012
B_20200101123013
  • C
C_20200101123012
  • D
D_20200101123012
  • 值:所关注的人所发的微博在内容表中的rowkey
  • 通过多版本来记录一个用户发的多条微博的rowkey

3、代码实现

/**
 * @ClassName WeiboHbaseTest
 * @Description TODO 用于实现微博功能的管理,基于Hbase存储
 * @Date 2020/7/1 16:28
 * @Create By     Frank
 */
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();
        //创建ns和表
        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));
        //todo:1-从邮箱表中获取这个用户所关注的所有用户发的最新的微博的rowkey
        Get get = new Get(Bytes.toBytes(a));
        get.addFamily(Bytes.toBytes(table3Cf));
        Result result = table3.get(get);
        //todo:2-根据rowkey到第一张表中查询数据
        for(Cell cell:result.rawCells()){
            //取出每个用户发的微博的rowkey
            byte[] weiboRow = CellUtil.cloneValue(cell);
            //到第一张表查询这个rowkey对应的微博内容
            Get get1 = new Get(weiboRow);
            Result result1 = table1.get(get1);
            for(Cell content : result1.rawCells()){
                //打印即可
            }
        }
    }

    //取关,a取关了b
    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));
        //todo:1-将a从b的粉丝列表中移除
        Delete deleteFans = new Delete(Bytes.toBytes(b));
        deleteFans.addColumn(Bytes.toBytes(table2Cf2),Bytes.toBytes(a));
        table2.delete(deleteFans);
        //todo:2-将b从a的关注列表中移除
        Delete deleteAttend = new Delete(Bytes.toBytes(a));
        deleteAttend.addColumn(Bytes.toBytes(table2Cf1),Bytes.toBytes(b));
        table2.delete(deleteAttend);
        //todo:3-将a的邮箱中b的微博全部移除
        Delete delete = new Delete(Bytes.toBytes(a));
        delete.addColumn(Bytes.toBytes(table3Cf),Bytes.toBytes(b));
        table3.delete(delete);
    }

    //添加关注:a关注了b
    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));
        //todo:1-将a添加到b的粉丝列表
        Put putFans = new Put(Bytes.toBytes(b));
        putFans.addColumn(Bytes.toBytes(table2Cf2),Bytes.toBytes(a),Bytes.toBytes(a));
        table2.put(putFans);
        //todo:2-将b添加到a的关注列表
        Put putAttend = new Put(Bytes.toBytes(a));
        putAttend.addColumn(Bytes.toBytes(table2Cf1),Bytes.toBytes(b),Bytes.toBytes(b));
        table2.put(putAttend);
        //todo:3-将b所发的微博的rowkey存储在a的邮箱中
        Scan scan = new Scan();
        PrefixFilter prefixFilter = new PrefixFilter(Bytes.toBytes(b));
        scan.setFilter(prefixFilter);
        ResultScanner scanner = table1.getScanner(scan);
        for (Result result : scanner) {
            //获取b发的微博的每一个rowkey,写入第三张表a的邮箱中
            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));
        //todo:1-将用户所发的微博,写入第一张表
        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);
        //todo:2-将用户所发的微博的rowkey推送给他的粉丝
        //先获取这个用户所有的粉丝列表
        Get getFans = new Get(Bytes.toBytes(userid));
        getFans.addFamily(Bytes.toBytes(table2Cf2));
        Result result = table2.get(getFans);
        //取出每个粉丝id,将这条微博的rowkey写入这个粉丝的邮箱中
        for(Cell cell : result.rawCells() ){
            byte[] fansId = CellUtil.cloneQualifier(cell);
            //将当前的微博id写入这个粉丝的邮件箱
            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);
    }

    //用于创建namespace
    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;
    }
    
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值