题目
在社交网站,社交APP上会存储有大量的用户数据以及用户之间的关系数据,比如A用户的好友列表会展示出他所有的好友,现有一张Hbase表,存储就是当前注册用户的好友关系数据。
需求
1. 使用Hbase相关API创建一张结构如上的表
2. 删除好友操作实现(好友关系双向,一方删除好友,另一方也会被迫删除好友)
例如:uid1用户执行删除uid2这个好友,则uid2的好友列表中也必须删除uid1
环境搭建
-- 创建表 create 'relations', {NAME => 'friends', VERSIONS => '1'}
-- 添加数据 put 'relations', 'uid1', 'friends:uid2', 'uid2' put 'relations', 'uid1', 'friends:uid3', 'uid3' put 'relations', 'uid1', 'friends:uid4', 'uid4' put 'relations', 'uid2', 'friends:uid1', 'uid1' put 'relations', 'uid2', 'friends:uid3', 'uid3' put 'relations', 'uid3', 'friends:uid1', 'uid1' -- 查看数据 scan 'relations'
ROW COLUMN+CELL uid1 column=friends:uid2, timestamp=1608010040706, value=uid2 uid1 column=friends:uid3, timestamp=1608010077381, value=uid3 uid1 column=friends:uid4, timestamp=1608010083645, value=uid4 uid2 column=friends:uid1, timestamp=1608010098725, value=uid1 uid2 column=friends:uid3, timestamp=1608010090459, value=uid3 uid3 column=friends:uid1, timestamp=1608010090459, value=uid1
实现
1.编写协处理器
package com.lagou.hbase; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.CellUtil; 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.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; // 继承协处理器BaseRegionObserver public class DelRelation extends BaseRegionObserver { // 重写postDelete @Override public void postDelete(final ObserverContext<RegionCoprocessorEnvironment> e, final Delete delete, final WALEdit edit, final Durability durability) throws IOException { super.postDelete(e, delete, edit, durability); //获取表对象 HTableWrapper roles = (HTableWrapper)e.getEnvironment().getTable(TableName.valueOf("roles")); //获取执行删除的列族队列集合 NavigableMap<byte[], List<Cell>> familyCellMap = delete.getFamilyCellMap(); //通过队列集合 Set<Map.Entry<byte[], List<Cell>>> entries = familyCellMap.entrySet(); //循环队列获取cells对象 for (final Map.Entry<byte[], List<Cell>> entry : entries) { System.out.println(Bytes.toString(entry.getKey())); List<Cell> cells = entry.getValue(); //循环cells对象获取每个cell的rowkey以及列族 for (final Cell cell : cells) { byte[] rowkey = CellUtil.cloneRow(cell); byte[] qualifier = CellUtil.cloneQualifier(cell); //判断是否存在删除的rowkey的cell boolean flag = roles.exists(new Get(qualifier).addColumn(Bytes.toBytes("friends"), rowkey)); if (flag){ //生成一个delete对象对需要删除的列族进行删除 Delete delQualifier = new Delete(qualifier).addColumn(Bytes.toBytes("friends"), rowkey); roles.delete(delQualifier); } } } } }
2.打成Jar包,上传HDFS
-- 复制文件到linux系统并修改名称
cd /opt/lagou/softwares mv original-hbaseStudy-1.0-SNAPSHOT.jar precessor2.jar
-- 上传jar包至hdfs hdfs dfs -mkdir -p /processor hdfs dfs -put precessor2.jar /processor
3. 挂载协处理器
-- 查看表信息 describe 'relations'
-- 挂在协处理器 alter 'relations',METHOD =>'table_att','Coprocessor'=>'hdfs://centos7-1:9000/processor/processor.jar|com.lagou.hbase.DelRelation|1001|'
-- 再次查看表信息(注意变化的地方) describe 'relations'
4.验证协处理器
-- 删除数据,查看功能实现 delete 'relations', 'uid1', 'friends:uid2'
验证结果