Hbase作业

在社交网站,社交APP上会存储有大量的用户数据以及用户之间的关系数据,比如A用户的好友列表会展示出他所有的好友,现有一张Hbase表,存储就是当前注册用户的好友关系数据,如下

需求

  1. 使用Hbase相关API创建一张结构如上的表

  2. 删除好友操作实现(好友关系双向,一方删除好友,另一方也会被迫删除好友)

    例如:uid1用户执行删除uid2这个好友,则uid2的好友列表中也必须删除uid1

协处理器监听是针对region的操作,这两次delete会形成递归调用,

使用协处理器实现

  1. 创建表

package com.colin.job;
​
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
​
import java.io.IOException;
import java.util.*;
​
public class RelationDemo {
    //创建一张维护社交好友关系的hbase
    /*
    表名:relation
    rowkey:uid
    列族:friends
     */
    static Configuration conf = null;
    static Connection conn = null;
​
    static {
        conf = HBaseConfiguration.create();
​
        conf.set("hbase.zookeeper.quorum", "linux121,linux122");
        conf.set("hbase.zookeeper.property.clientPort", "2181");
        //通过conf获取到hbase集群的连接
        try {
            conn = ConnectionFactory.createConnection(conf);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
​
    // 创建表方法
    public void createRelationTable() throws IOException {
        final Admin admin = conn.getAdmin();
        final HTableDescriptor relation = new HTableDescriptor(TableName.valueOf("relation"));
        final HColumnDescriptor cf = new HColumnDescriptor("friends");
        final HTableDescriptor hTableDescriptor = relation.addFamily(cf);
        admin.createTable(hTableDescriptor);
​
        System.out.println("relation表创建成功!!");
        admin.close();
    }
​
    //初始化部分数据
    public void initRelationData() throws IOException {
        final Table relation = conn.getTable(TableName.valueOf("relation"));
        //插入uid1用户
        final Put uid1 = new Put(Bytes.toBytes("uid1"));
        uid1.addColumn(Bytes.toBytes("friends"), Bytes.toBytes("uid2"), Bytes.toBytes("uid2"));
        uid1.addColumn(Bytes.toBytes("friends"), Bytes.toBytes("uid3"), Bytes.toBytes("uid3"));
        uid1.addColumn(Bytes.toBytes("friends"), Bytes.toBytes("uid4"), Bytes.toBytes("uid4"));
        //插入uid2用户
        final Put uid2 = new Put(Bytes.toBytes("uid2"));
        uid2.addColumn(Bytes.toBytes("friends"), Bytes.toBytes("uid1"), Bytes.toBytes("uid1"));
        uid2.addColumn(Bytes.toBytes("friends"), Bytes.toBytes("uid3"), Bytes.toBytes("uid3"));
        uid2.addColumn(Bytes.toBytes("friends"), Bytes.toBytes("uid4"), Bytes.toBytes("uid4"));
        //准备list集合
        final ArrayList<Put> puts = new ArrayList<Put>();
        puts.add(uid1);
        puts.add(uid2);
        //执行写入
        relation.put(puts);
        System.out.println("数据初始化成功!!");
    }
​
    //某个用户其中一个好友,
    public void deleteFriedns(String uid, String friend) throws IOException {
        /*
        1 需要根据传入用户删除其列族中对应好友的列
        2 其好友的列族对应需要删除该用户的列
         */
        final Table relation = conn.getTable(TableName.valueOf("relation"));
        final Delete delete = new Delete(Bytes.toBytes(uid));
        delete.addColumn(Bytes.toBytes("friends"), Bytes.toBytes(friend));//最好使用协处理器实现
​
        relation.delete(delete);
​
    }
​
    public static void main(String[] args) throws IOException {
        final RelationDemo r = new RelationDemo();
//        r.createRelationTable();//创建表
        r.initRelationData();//初始化数据
        //假设uid1用户删除了uid2这个好友,需要执行删除操作
        r.deleteFriedns("uid1", "uid2");
    }
}
​

  1. 编写协处理器

    package com.colin.job;
    ​
    import org.apache.commons.lang.StringUtils;
    import org.apache.hadoop.hbase.Cell;
    import org.apache.hadoop.hbase.CellUtil;
    import org.apache.hadoop.hbase.KeyValue;
    import org.apache.hadoop.hbase.TableName;
    import org.apache.hadoop.hbase.client.*;
    import org.apache.hadoop.hbase.coprocessor.BaseRegionObserver;
    import org.apache.hadoop.hbase.coprocessor.ObserverContext;
    import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
    import org.apache.hadoop.hbase.filter.ByteArrayComparable;
    import org.apache.hadoop.hbase.filter.CompareFilter;
    import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
    import org.apache.hadoop.hbase.util.Bytes;
    ​
    import java.io.IOException;
    import java.util.List;
    import java.util.Map;
    import java.util.NavigableMap;
    import java.util.Set;
    import java.util.concurrent.ConcurrentMap;
    ​
    public class DeleteProcessor extends BaseRegionObserver {
        //predelete
        //postdelete:通过判断数据是否已经删除来跳出递归
    ​
        @Override
        public void postDelete(ObserverContext<RegionCoprocessorEnvironment> e, Delete delete, WALEdit edit, Durability durability) throws IOException {
            final HTable relation = e.getEnvironment().getTable(TableName.valueOf("relation"));
            final byte[] rowkeyUid = delete.getRow();//获取rowkey
            //获取到所有的cell对象
            final NavigableMap<byte[], List<Cell>> familyCellMap = delete.getFamilyCellMap();
            final Set<Map.Entry<byte[], List<Cell>>> entries = familyCellMap.entrySet();
            for (Map.Entry<byte[], List<Cell>> entry : entries) {
                System.out.println(Bytes.toString(entry.getKey()));//列族信息
                final List<Cell> cells = entry.getValue();
                for (Cell cell : cells) {
                    final byte[] rowkey = CellUtil.cloneRow(cell);//rowkey信息
                    final byte[] column = CellUtil.cloneQualifier(cell);//列信息
                    //验证删除的目标数据是否存在,存在则执行删除否则不执行,必须有此判断否则造成协处理器被循环调用耗尽资源
                    final boolean flag = relation.exists(new Get(column).addColumn(Bytes.toBytes("friends"), rowkey));
                    if(flag){
                        final Delete myDelete = new Delete(column).addColumn(Bytes.toBytes("friends"), rowkey);
                        relation.delete(myDelete);
                    }
                }
            }
        }
    }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Colin_lqk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值