涉及概念梳理:命名空间

4.1.1、命名空间的结构

1) Table:表,所有的表都是命名空间的成员,即表必属于某个命名空间,如果没有指定,则在default默认的命名空间中。

2) RegionServer group:一个命名空间包含了默认的RegionServer Group。

3) Permission:权限,命名空间能够让我们来定义访问控制列表ACL(Access Control List)。例如,创建表,读取表,删除,更新等等操作。

4) Quota:限额,可以强制一个命名空间可包含的region的数量。

4.1.2、命名空间的使用

1) 创建命名空间

hbase(main):002:0> create_namespace 'student_namespace'

2) 创建表时指定命名空间

hbase(main):004:0> create 'student_namespace:student_table','student_info'

3) 观察HDFS中的目录结构的变化

 

4.2、微博系统

4.1.1、需求分析

1) 微博内容的浏览,数据库表设计

2) 用户社交体现:关注用户,取关用户

3) 拉取关注的人的微博内容

4.1.2、代码实现

代码设计总览:

1) 创建命名空间以及表名的定义

2) 创建微博内容表

3) 创建用户关系表

4) 创建用户微博内容接收邮件表

5) 发布微博内容

6) 添加关注用户

7) 移除(取关)用户

8) 获取关注的人的微博内容

9) 测试

1) 创建命名空间以及表名的定义

//获取配置conf

private Configuration conf = HBaseConfiguration.create();

//微博内容表的表名

private static final byte[] TABLE_CONTENT = Bytes.toBytes("weibo:content");

//用户关系表的表名

private static final byte[] TABLE_RELATIONS = Bytes.toBytes("weibo:relations");

//微博收件箱表的表名

private static final byte[] TABLE_RECEIVE_CONTENT_EMAIL = Bytes.toBytes("weibo:receive_content_email");

public void initNamespace(){

HBaseAdmin admin = null;

try {

admin = new HBaseAdmin(conf);

//命名空间类似于关系型数据库中的schema,可以想象成文件夹

NamespaceDescriptor weibo = NamespaceDescriptor

.create("weibo")

.addConfiguration("creator", "Jinji")

.addConfiguration("create_time", System.currentTimeMillis() + "")

.build();

admin.createNamespace(weibo);

} catch (MasterNotRunningException e) {

e.printStackTrace();

} catch (ZooKeeperConnectionException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}finally{

if(null != admin){

try {

admin.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

2) 创建微博内容表

表结构:

方法名

creatTableeContent

Table Name

weibo:content

RowKey

用户ID_时间戳

ColumnFamily

info

ColumnLabel

标题,内容,图片

Version

1个版本

代码:

/**

* 创建微博内容表

* Table Name:weibo:content

* RowKey:用户ID_时间戳

* ColumnFamily:info

* ColumnLabel:标题 内容 图片URL

* Version:1个版本

*/

public void createTableContent(){

HBaseAdmin admin = null;

try {

admin = new HBaseAdmin(conf);

//创建表表述

HTableDescriptor content = new HTableDescriptor(TableName.valueOf(TABLE_CONTENT));

//创建列族描述

HColumnDescriptor info = new HColumnDescriptor(Bytes.toBytes("info"));

//设置块缓存

info.setBlockCacheEnabled(true);

//设置块缓存大小

info.setBlocksize(2097152);

//设置压缩方式

// info.setCompressionType(Algorithm.SNAPPY);

//设置版本确界

info.setMaxVersions(1);

info.setMinVersions(1);

content.addFamily(info);

admin.createTable(content);

} catch (MasterNotRunningException e) {

e.printStackTrace();

} catch (ZooKeeperConnectionException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}finally{

if(null != admin){

try {

admin.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

3) 创建用户关系表

表结构:

方法名

createTableRelations

Table Name

weibo:relations

RowKey

用户ID

ColumnFamily

attends、fans

ColumnLabel

关注用户ID,粉丝用户ID

ColumnValue

用户ID

Version

1个版本

代码:

/**

* 用户关系表

* Table Name:weibo:relations

* RowKey:用户ID

* ColumnFamily:attends,fans

* ColumnLabel:关注用户ID,粉丝用户ID

* ColumnValue:用户ID

* Version:1个版本

*/

public void createTableRelations(){

HBaseAdmin admin = null;

try {

admin = new HBaseAdmin(conf);

HTableDescriptor relations = new HTableDescriptor(TableName.valueOf(TABLE_RELATIONS));

//关注的人的列族

HColumnDescriptor attends = new HColumnDescriptor(Bytes.toBytes("attends"));

//设置块缓存

attends.setBlockCacheEnabled(true);

//设置块缓存大小

attends.setBlocksize(2097152);

//设置压缩方式

// info.setCompressionType(Algorithm.SNAPPY);

//设置版本确界

attends.setMaxVersions(1);

attends.setMinVersions(1);

//粉丝列族

HColumnDescriptor fans = new HColumnDescriptor(Bytes.toBytes("fans"));

fans.setBlockCacheEnabled(true);

fans.setBlocksize(2097152);

fans.setMaxVersions(1);

fans.setMinVersions(1);

relations.addFamily(attends);

relations.addFamily(fans);

admin.createTable(relations);

} catch (MasterNotRunningException e) {

e.printStackTrace();

} catch (ZooKeeperConnectionException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}finally{

if(null != admin){

try {

admin.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

4) 创建微博收件箱表

表结构:

方法名

createTableReceiveContentEmails

Table Name

weibo:receive_content_email

RowKey

用户ID

ColumnFamily

info

ColumnLabel

用户ID

ColumnValue

取微博内容的RowKey

Version

1000

代码:

/**

* 创建微博收件箱表

* Table Name: weibo:receive_content_email

* RowKey:用户ID

* ColumnFamily:info

* ColumnLabel:用户ID-发布微博的人的用户ID

* ColumnValue:关注的人的微博的RowKey

* Version:1000

*/

public void createTableReceiveContentEmail(){

HBaseAdmin admin = null;

try {

admin = new HBaseAdmin(conf);

HTableDescriptor receive_content_email = new HTableDescriptor(TableName.valueOf(TABLE_RECEIVE_CONTENT_EMAIL));

HColumnDescriptor info = new HColumnDescriptor(Bytes.toBytes("info"));

info.setBlockCacheEnabled(true);

info.setBlocksize(2097152);

info.setMaxVersions(1000);

info.setMinVersions(1000);

receive_content_email.addFamily(info);;

admin.createTable(receive_content_email);

} catch (MasterNotRunningException e) {

e.printStackTrace();

} catch (ZooKeeperConnectionException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}finally{

if(null != admin){

try {

admin.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

5) 发布微博内容

a、微博内容表中添加1条数据

b、微博收件箱表对所有粉丝用户添加数据

代码:Message.java

package com.z.hbase.weibo;

public class Message {

private String uid;

private String timestamp;

private String content;

public String getUid() {

return uid;

}

public void setUid(String uid) {

this.uid = uid;

}

public String getTimestamp() {

return timestamp;

}

public void setTimestamp(String timestamp) {

this.timestamp = timestamp;

}

public String getContent() {

return content;

}

public void setContent(String content) {

this.content = content;

}

@Override

public String toString() {

return "Message [uid=" + uid + ", timestamp=" + timestamp + ", content=" + content + "]";

}

}

代码:public void publishContent(String uid, String content)

/**

* 发布微博

* a、微博内容表中数据+1

* b、向微博收件箱表中加入微博的Rowkey

*/

public void publishContent(String uid, String content){

HConnection connection = null;

try {

connection = HConnectionManager.createConnection(conf);

//a、微博内容表中添加1条数据,首先获取微博内容表描述

HTableInterface contentTBL = connection.getTable(TableName.valueOf(TABLE_CONTENT));

//组装Rowkey

long timestamp = System.currentTimeMillis();

String rowKey = uid + "_" + timestamp;

Put put = new Put(Bytes.toBytes(rowKey));

put.add(Bytes.toBytes("info"), Bytes.toBytes("content"), timestamp, Bytes.toBytes(content));

contentTBL.put(put);

//b、向微博收件箱表中加入发布的Rowkey

//b.1、查询用户关系表,得到当前用户有哪些粉丝

HTableInterface relationsTBL = connection.getTable(TableName.valueOf(TABLE_RELATIONS));

//b.2、取出目标数据

Get get = new Get(Bytes.toBytes(uid));

get.addFamily(Bytes.toBytes("fans"));

Result result = relationsTBL.get(get);

List<byte[]> fans = new ArrayList<byte[]>();

//遍历取出当前发布微博的用户的所有粉丝数据

for(Cell cell : result.rawCells()){

fans.add(CellUtil.cloneQualifier(cell));

}

//如果该用户没有粉丝,则直接return

if(fans.size() <= 0) return;

//开始操作收件箱表

HTableInterface recTBL = connection.getTable(TableName.valueOf(TABLE_RECEIVE_CONTENT_EMAIL));

List<Put> puts = new ArrayList<Put>();

for(byte[] fan : fans){

Put fanPut = new Put(fan);

fanPut.add(Bytes.toBytes("info"), Bytes.toBytes(uid), timestamp, Bytes.toBytes(rowKey));

puts.add(fanPut);

}

recTBL.put(puts);

} catch (IOException e) {

e.printStackTrace();

}finally{

if(null != connection){

try {

connection.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

 

6) 添加关注用户

a、在微博用户关系表中,对当前主动操作的用户添加新关注的好友

b、在微博用户关系表中,对被关注的用户添加新的粉丝

c、微博收件箱表中添加所关注的用户发布的微博

代码实现:public void addAttends(String uid, String... attends)

/**

* 关注用户逻辑

* a、在微博用户关系表中,对当前主动操作的用户添加新的关注的好友

* b、在微博用户关系表中,对被关注的用户添加粉丝(当前操作的用户)

* c、当前操作用户的微博收件箱添加所关注的用户发布的微博rowkey

*/

public void addAttends(String uid, String... attends){

//参数过滤

if(attends == null || attends.length <= 0 || uid == null || uid.length() <= 0){

return;

}

HConnection connection = null;

try {

connection = HConnectionManager.createConnection(conf);

//用户关系表操作对象(连接到用户关系表)

HTableInterface relationsTBL = connection.getTable(TableName.valueOf(TABLE_RELATIONS));

List<Put> puts = new ArrayList<Put>();

//a、在微博用户关系表中,添加新关注的好友

Put attendPut = new Put(Bytes.toBytes(uid));

for(String attend : attends){

//为当前用户添加关注的人

attendPut.add(Bytes.toBytes("attends"), Bytes.toBytes(attend), Bytes.toBytes(attend));

//b、为被关注的人,添加粉丝

Put fansPut = new Put(Bytes.toBytes(attend));

fansPut.add(Bytes.toBytes("fans"), Bytes.toBytes(uid), Bytes.toBytes(uid));

//将所有关注的人一个一个的添加到puts(List)集合中

puts.add(fansPut);

}

puts.add(attendPut);

relationsTBL.put(puts);

//c.1、微博收件箱添加关注的用户发布的微博内容(content)的rowkey

HTableInterface contentTBL = connection.getTable(TableName.valueOf(TABLE_CONTENT));

Scan scan = new Scan();

//用于存放取出来的关注的人所发布的微博的rowkey

List<byte[]> rowkeys = new ArrayList<byte[]>();

for(String attend : attends){

//过滤扫描rowkey,即:前置位匹配被关注的人的uid_

RowFilter filter = new RowFilter(CompareFilter.CompareOp.EQUAL, new SubstringComparator(attend + "_"));

//为扫描对象指定过滤规则

scan.setFilter(filter);

//通过扫描对象得到scanner

ResultScanner result = contentTBL.getScanner(scan);

//迭代器遍历扫描出来的结果集

Iterator<Result> iterator = result.iterator();

while(iterator.hasNext()){

//取出每一个符合扫描结果的那一行数据

Result r = iterator.next();

for(Cell cell : r.rawCells()){

//将得到的rowkey放置于集合容器中

rowkeys.add(CellUtil.cloneRow(cell));

}

}

}

//c.2、将取出的微博rowkey放置于当前操作用户的收件箱中

if(rowkeys.size() <= 0) return;

//得到微博收件箱表的操作对象

HTableInterface recTBL = connection.getTable(TableName.valueOf(TABLE_RECEIVE_CONTENT_EMAIL));

//用于存放多个关注的用户的发布的多条微博rowkey信息

List<Put> recPuts = new ArrayList<Put>();

for(byte[] rk : rowkeys){

Put put = new Put(Bytes.toBytes(uid));

//uid_timestamp

String rowKey = Bytes.toString(rk);

//借取uid

String attendUID = rowKey.substring(0, rowKey.indexOf("_"));

long timestamp = Long.parseLong(rowKey.substring(rowKey.indexOf("_") + 1));

//将微博rowkey添加到指定单元格中

put.add(Bytes.toBytes("info"), Bytes.toBytes(attendUID), timestamp, rk);

recPuts.add(put);

}

recTBL.put(recPuts);

} catch (IOException e) {

e.printStackTrace();

}finally{

if(null != connection){

try {

connection.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

7) 移除(取关)用户

a、在微博用户关系表中,对当前主动操作的用户移除取关的好友(attends)

b、在微博用户关系表中,对被取关的用户移除粉丝

c、微博收件箱中删除取关的用户发布的微博

代码:public void removeAttends(String uid, String... attends)

/**

* 取消关注(remove)

* a、在微博用户关系表中,对当前主动操作的用户删除对应取关的好友

* b、在微博用户关系表中,对被取消关注的人删除粉丝(当前操作人)

* c、从收件箱中,删除取关的人的微博的rowkey

*/

public void removeAttends(String uid, String... attends){

//过滤数据

if(uid == null || uid.length() <= 0 || attends == null || attends.length <= 0) return;

HConnection connection = null;

try {

connection = HConnectionManager.createConnection(conf);

//a、在微博用户关系表中,删除已关注的好友

HTableInterface relationsTBL = connection.getTable(TableName.valueOf(TABLE_RELATIONS));

//待删除的用户关系表中的所有数据

List<Delete> deletes = new ArrayList<Delete>();

//当前取关操作者的uid对应的Delete对象

Delete attendDelete = new Delete(Bytes.toBytes(uid));

//遍历取关,同时每次取关都要将被取关的人的粉丝-1

for(String attend : attends){

attendDelete.deleteColumn(Bytes.toBytes("attends"), Bytes.toBytes(attend));

//b

Delete fansDelete = new Delete(Bytes.toBytes(attend));

fansDelete.deleteColumn(Bytes.toBytes("fans"), Bytes.toBytes(uid));

deletes.add(fansDelete);

}

deletes.add(attendDelete);

relationsTBL.delete(deletes);

//c、删除取关的人的微博rowkey 从 收件箱表中

HTableInterface recTBL = connection.getTable(TableName.valueOf(TABLE_RECEIVE_CONTENT_EMAIL));

Delete recDelete = new Delete(Bytes.toBytes(uid));

for(String attend : attends){

recDelete.deleteColumn(Bytes.toBytes("info"), Bytes.toBytes(attend));

}

recTBL.delete(recDelete);

} catch (IOException e) {

e.printStackTrace();

}

}

8) 获取关注的人的微博内容

a、从微博收件箱中获取所关注的用户的微博RowKey

b、根据获取的RowKey,得到微博内容

代码实现:public List<Message> getAttendsContent(String uid)

/**

* 获取微博实际内容

* a、从微博收件箱中获取所有关注的人的发布的微博的rowkey

* b、根据得到的rowkey去微博内容表中得到数据

* c、将得到的数据封装到Message对象中

*/

public List<Message> getAttendsContent(String uid){

HConnection connection = null;

try {

connection = HConnectionManager.createConnection(conf);

HTableInterface recTBL = connection.getTable(TableName.valueOf(TABLE_RECEIVE_CONTENT_EMAIL));

//a、从收件箱中取得微博rowKey

Get get = new Get(Bytes.toBytes(uid));

//设置最大版本号

get.setMaxVersions(5);

List<byte[]> rowkeys = new ArrayList<byte[]>();

Result result = recTBL.get(get);

for(Cell cell : result.rawCells()){

rowkeys.add(CellUtil.cloneValue(cell));

}

//b、根据取出的所有rowkey去微博内容表中检索数据

HTableInterface contentTBL = connection.getTable(TableName.valueOf(TABLE_CONTENT));

List<Get> gets = new ArrayList<Get>();

//根据rowkey取出对应微博的具体内容

for(byte[] rk : rowkeys){

Get g = new Get(rk);

gets.add(g);

}

//得到所有的微博内容的result对象

Result[] results = contentTBL.get(gets);

List<Message> messages = new ArrayList<Message>();

for(Result res : results){

for(Cell cell : res.rawCells()){

Message message = new Message();

String rowKey = Bytes.toString(CellUtil.cloneRow(cell));

String userid = rowKey.substring(0, rowKey.indexOf("_"));

String timestamp = rowKey.substring(rowKey.indexOf("_") + 1);

String content = Bytes.toString(CellUtil.cloneValue(cell));

message.setContent(content);

message.setTimestamp(timestamp);

message.setUid(userid);

messages.add(message);

}

}

return messages;

} catch (IOException e) {

e.printStackTrace();

}finally{

try {

connection.close();

} catch (IOException e) {

e.printStackTrace();

}

}

return null;

}

9) 测试

-- 测试发布微博内容

public void testPublishContent(WeiBo wb)

-- 测试添加关注

public void testAddAttend(WeiBo wb)

-- 测试取消关注

public void testRemoveAttend(WeiBo wb)

-- 测试展示内容

public void testShowMessage(WeiBo wb)

代码:

/**

* 发布微博内容

* 添加关注

* 取消关注

* 展示内容

*/

public void testPublishContent(WeiBo wb){

wb.publishContent("0001", "今天买了一包空气,送了点薯片,非常开心!!");

wb.publishContent("0001", "今天天气不错。");

}

public void testAddAttend(WeiBo wb){

wb.publishContent("0008", "准备下课!");

wb.publishContent("0009", "准备关机!");

wb.addAttends("0001", "0008", "0009");

}

public void testRemoveAttend(WeiBo wb){

wb.removeAttends("0001", "0008");

}

public void testShowMessage(WeiBo wb){

List<Message> messages = wb.getAttendsContent("0001");

for(Message message : messages){

System.out.println(message);

}

}

public static void main(String[] args) {

WeiBo weibo = new WeiBo();

weibo.initTable();

weibo.testPublishContent(weibo);

weibo.testAddAttend(weibo);

weibo.testShowMessage(weibo);

weibo.testRemoveAttend(weibo);

weibo.testShowMessage(weibo);

}

 

五、总结

不一定所有的企业都会使用HBase,大数据的框架可以是相互配合相互依赖的,同时,根据不同的业务,部分框架之间的使用也可以是相互独立的。例如有些企业在处理整个业务时,只是用HDFS+Spark部分的内容。所以在学习HBase框架时,一定要有宏观思维,了解其框架特性,不一定非要在所有的业务中使用所有的框架,要具体情况具体分析,酌情选择。

参考:尽际

Hbase项目(完整版)的更多相关文章

  1. 使用Nginx+uwsgi在亚马逊云服务器上部署python+django项目完整版(二)——部署配置及相关知识

    ---恢复内容开始--- 一.前提: 1.django项目文件已放置在云服务器上,配置好运行环境,可正常运行 2.云服务器可正常连接 二.相关知识 1.python manage.py runserv ...

  2. Eclipse 搭建tomcat+动态项目完整版

    1. Tomcat搭建 1.新加服务器,右击控制台的server目录->new->server->选择本地tomcat 2.配置tomcat属性(如果更改失败,将tomcat下的项目 ...

  3. 完成向后台添加用户的ssm项目,完整版

    1:ssm框架整合 1.1添加maven依赖pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns: ...

  4. 老王Python培训视频教程(价值500元)【基础进阶项目篇 – 完整版】

    老王Python培训视频教程(价值500元)[基础进阶项目篇 – 完整版] 教学大纲python基础篇1-25课时1.虚拟机安装ubuntu开发环境,第一个程序:hello python! (配置开发 ...

  5. Asp.NET Core2.0 项目实战入门视频课程_完整版

    END OR START? 看到这个标题,你开不开心,激不激动呢? 没错,.net core的入门课程已经完毕了.52ABP.School项目从11月19日,第一章视频的试录制,到今天完整版出炉,离不 ...

  6. Spring Boot → 11:项目实战-账单管理系统完整版

    Spring Boot → 11:项目实战-账单管理系统完整版

  7. flexbox-CSS3弹性盒模型flexbox完整版教程

    原文链接:http://caibaojian.com/flexbox-guide.html flexbox-CSS3弹性盒模型flexbox完整版教程 A-A+ 前端博客•2014-05-08•前端开 ...

  8. RadioStream应用源码完整版(iphone版和ipad版)

    RadioStream应用源码完整版(iphone版和ipad版),这个项目是从那个ios教程网分析过了的,也是一个不错的国外音乐应用的,支持iphone版和ipad版. <ignore_js_ ...

  9. Genymotion配置及使用教程(最新最完整版附各部分下载地址)

    Genymotion配置及使用教程(最新最完整版附各部分下载地址) FROM:http://blog.csdn.net/beiminglei/article/details/13776013 早都听说 ...

随机推荐

  1. 【POJ 2828】Buy Tickets

    [题目链接] http://poj.org/problem?id=2828 [算法] 离线用线段树维护序列即可 [代码] #include <algorithm> #include < ...

  2. DB-MySql:MySQL 及 SQL 注入

    ylbtech-DB-MySQL:MySQL 及 SQL 注入 1.返回顶部 1. MySQL 及 SQL 注入 如果您通过网页获取用户输入的数据并将其插入一个MySQL数据库,那么就有可能发生SQL ...

  3. kubernetes系列:(一)、kubeadm搭建kubernetes(v1.13.1)单节点集群

    kubeadm是Kubernetes官方提供的用于快速部署Kubernetes集群的工具,本篇文章使用kubeadm搭建一个单master节点的k8s集群. 节点部署信息 节点主机名 节点IP 节点角 ...

  4. Spring学习笔记(二) 初探Spring

    版权声明 笔记出自<Spring 开发指南>一书. Spring 初探 前面我们简单介绍了 Spring 的基本组件和功能,现在我们来看一个简单示例: Person接口Person接口定义 ...

  5. 有关DevExpress 安装后vs工具箱不显示图标的错误

    在https://www.devexpress.com/Support/Center/Question/Details/T214296/missing-icons-from-toolbox找到解决方法 ...

  6. codeforces 567 E. President and Roads 【 最短路 桥 】

    给出一个有向图,从起点走到终点(必须走最短路),问一条边是否一定会被经过,如果不经过它,可以减小它的多少边权使得经过它(边权不能减少到0) 正反向建图,分别求出起点到每个点的最短距离,终点到每个点的最 ...

  7. ZOJ 3019 Puzzle

    解题思路:给出两个数列an,bn,其中an,bn中元素的顺序可以任意改变,求an,bn的LCS 因为数列中的元素可以按任意顺序排列,所以只需要求出an,bn中的元素有多少个是相同的即可. 反思:一开始 ...

  8. ZBrush中Pinch捏挤笔刷介绍

    随着版本的升级ZBrush®中给我们提供了越来越多的笔刷,对于这款软件来说,笔刷的使用是第一要素,也会一直伴随我们创作.虽然Zbrush中有那么多的笔刷,但是很多朋友会根据自己的习惯来使用,这个并不是 ...

  9. P3387 【模板】缩点 && P3388 【模板】割点(割顶)

    Tarjan算法 应用: 有向图的强连通分量 无向图割点和桥 双连通分量 接下来主要谈论前面两者的应用(主要是第三种还没学会) 算法简要介绍 我们需要先理解一下知识:搜索树 有向图的搜索树的4种边,如 ...

  10. SPOJ CIRU

    SPOJ CIRU 题意 给出n个圆,求他们覆盖的面积. 解法 自适应Simpson,但需要将圆离散化一下,以保证我们查询的是一个连续的有圆的区间. 奇怪的是我没有离散化,样例都没有过,却把题给A了 ...