这边文章先将可能的需求分析一下,设计出HBase表,下一步再開始编写client代码。

TwiBase系统

1、背景

为了加深HBase基本概念的学习,參考HBase实战这本书实际动手做了这个样例。

2、需求

这是一个用户推特系统,用户登陆到系统。须要维护用户的基本信息。然后用户能够发帖和其它用户进行互动。用户之间能够相互关注。用户能够浏览关注用户的推文等等。

这是一个比較简单的推特系统。不考虑用户之间的私信,用户评论推特等功能。

3、概要设计

3.1表设计

首先须要设计三个表:用户表。推特表以及用户之间的关系表。

(1)用户表

用户表至少包括唯一的username,用户昵称,用户邮箱以及用户发帖数量。用一个列族存储。

创建用户表的语句是:

create'users', 'info'

当中username用作rowkey。这样可以高速依据用户登陆ID查找到用户全部基本信息。

(2)推特表

推特表存储用户的发帖,至少包含username,发帖时间。以及发帖内容。用一个列族存储。

创建推特表的语句是:

create'twits', 'twits'

为了可以高速查找到指定用户的全部推文(登陆个人推特时显示),须要将同一个用户的全部推文都存储在一块,所以考虑将用户ID作为行键的第一部分,另外希望每一个用户的推文依照时间有序,所以将时间戳作为行键的第二部分,可是这里有个问题。username是变长的,怎么知道行键中前面到哪儿是username呢,这个时候可以对username做MD5散列,将变长的username变为定长的散列值。

另外你希望用户显示自己的推文的时候依照时间顺序倒序排列。即读出来的推文时间新的排在前面。那么就须要利用一个小技巧,不存储真正的时间戳。而是存储倒序时间戳=Long.MAXVALUE -时间戳。

所以表设计是这种:

rowKey:MD5(用户A)+倒序时间戳#time:发帖时间,content:内容

(3)关系表

如今仅仅实用户和推文功能。这明显不够。我们希望可以阅读其它人的推文,这就希望用户可以关注一些其它的用户。

详细我们须要存储哪些关系呢?

1用户A登陆,须要查看自己关注了谁,以及显示其关注的用户的推文,所以要存储用户A关注了谁?

2用户A登陆,想要查看自己的粉丝,所以须要存储谁关注了用户A?

3用户A登陆,訪问用户B的推特,那么须要知道用户A有没有关注用户B?

一開始你可能会想这样设计表:

rowKey:用户A#1:用户B,2:用户C,3:用户D

rowKey:用户B#1:用户H。2:用户C

这样能够非常轻松回答问题1和问题3.

可是问题2似乎非常难回答。除非扫描整个表。以及每一行的全部列,否则找不出全部关注某个用户的人。

这个表设计另一个大问题,就是当用户A关注用户B的时候,须要在用户A这一行加一列。可是我不知道如今加到哪一列了,即put数据的时候无法指定qualifier。你可能想到在每一行添加一列计数器来解决问题,即counter:x,可是不幸的是。HBase不支持事务操作。一旦多个client同一时候关注两个不同的用户,它们都须要取得计数器,然后插入新的一列,两个client非常可能读到同一个计数器值,这样一个client的写入就会被另一个给覆盖,所以必须去掉计数器,能够用以下方式解决:

这样设计表:

rowKey:用户A#用户B:1,用户C:2。用户D:3

rowKey:用户B#用户H:1,用户C:2

到眼下为止的设计还是没有高效的办法回答问题2.

上面两种设计都是“宽表”的形式。如今能够考虑使用“高表”的形式。

rowKey:用户A+分隔符+用户B#1:用户B昵称

即行键存储用户A关注用户B,我们将用户B的昵称放入qualifier能够节省再去用户表找用户B的昵称的时间。这是一种反规范化(de-nomalize)处理。

这样非常easy就能想到这样一个设计:

rowKey:用户A+分隔符+关注+分隔符+用户B#1:用户B昵称

rowKey:用户A+分隔符+关注+分隔符+用户C#1:用户C昵称

rowKey:用户A+分隔符+被关注+分隔符+用户D#1:用户D昵称

rowKey:用户A+分隔符+被关注+分隔符+用户H#1:用户H昵称

这样非常easy就能够回答上面三个问题,各自是用户A关注了谁?用户A关注了用户B?谁关注了用户A。只是要注意,当查找用户A的粉丝列表时。往往不想把用户A关注了谁这些集合也返回给client。这个时候能够通过为扫描设置起始和停止键来做到。

这里须要再次优化,即使用MD5对username进行处理,得到定长的散列值。这样做有几个优点:

1 能够抛弃掉分隔符,为扫描操作计算起始和停止键更加easy。

2 行键长度统一,能够帮助你非常好地预測读写性能。

3  MD5有助于数据更加均匀地分布在region上。

所以关系表设计再次改动为这样:

rowKey:MD5(用户A)+关注+MD5(用户B)#1:用户B的昵称

rowKey:MD5(用户A)+关注+MD5(用户C)#1:用户C的昵称

rowKey:MD5(用户A)+被关注+MD5(用户D)#1:用户D的昵称

rowKey:MD5(用户A)+被关注+MD5(用户H)#1:用户H的昵称

可是这样还不是最优的。之前已经说过了,当查找用户A的粉丝列表时,往往不想把用户A关注了谁这些集合也返回给client,尽管能够通过为扫描设置起始和停止键来做到。可是在region
server上面仍然要将这些不关心的数据从硬盘上读出来,才会经过扫描过滤。

所以考虑将被关注和关注两种类型分开,分别建立一个表,这下终于的表设计就这样了:

关注表:

rowKey:MD5(用户A)+MD5(用户B)#1:用户B的昵称

rowKey:MD5(用户A)+MD5(用户C)#1:用户C的昵称

被关注表:

rowKey:MD5(用户A)+MD5(用户D)#1:用户D的昵称

rowKey:MD5(用户A)+MD5(用户H)#1:用户H的昵称

创建关系表的命令是:

create'follows', 'f'

create'followedBy', 'f'

(4)推贴流表

进一步优化 ---反规范化处理!

设计HBase表的一个关键概念叫做反规范化。

截止眼下为止,我们已经维护了单个用户的关注用户列表,当用户登陆账户的时候,希望看到他关注的全部人的推特。你的应用会提取关注用户列表,然后到推特表中获取每个被关注用户的推特,然后集合这些推特依照时间排序显示出来。

随着系统用户数量增长,用户关注的用户的数量增长,这个过程会花费非常长的时间。

此外,假设一个用户被很多人关注。那么当他的全部粉丝登陆的时候,他的推特都会被訪问。他的推特都是物理上存放在一起的,所以托管这个受欢迎的人的推特的region将会不断回应请求,这样就制造了一个读热点。

解决问题的办法就是为每个用户维护一个推特流。一旦某一个人写了推特,就将这个内容写入到关注他的人的推特流里面。这就是反规范化。

概念介绍:规范化和反规范化

规范化是关系型数据库里面的概念,每种反复信息都会放进一个自己的表,这样有两个优点:当发生更新和删除的时候,不用操心更新指定的数据的全部副本;通过保存单一副本。而不是多个副本,降低了占用的存储空间。须要查询时,使用SQL语句里面的join子句就能够轻易连接这些数据。

反规范化是一个相反的概念,数据是反复的,存储在多个地方。由于你不须要开销非常大的join操作,这时候查询数据更加easy和高速。

规范化为写操作进行了优化,在读取数据时付出了连接数据的开销。

反规范化为读操作进行了优化。在写入时付出写多个副本的开销。

所以,为了为每一个用户维护一个推特流。我们建立一张新表(不打算为users表添加一个列族。由于users表的行键不是为了这个目的而优化的)。

推特流表创建的命令是:

create'twitsStream', 'info'

推特流表设计是这种:

rowKey:MD5(用户A)+倒序时间戳#1:用户B的昵称,2:推贴内容

rowKey:MD5(用户A)+倒序时间戳#1:用户D的昵称,2:推贴内容

rowKey:MD5(用户A)+倒序时间戳#1:用户H的昵称,2:推贴内容

(未完待续。。。

若有什么疑问和不吝赐教,欢迎交流。联系邮箱: jiq408694711@163.com  季义钦

作为兴趣点,眼下本人正在研究HBase和Hadoop

HBase概念学习(八)开发一个类twitter系统之表设计的更多相关文章

  1. 基于Hadoop开发网络云盘系统客户端界面设计初稿

    基于Hadoop开发网络云盘系统客户端界面设计初稿 前言: 本文是<基于Hadoop开发网络云盘系统架构设计方案>的第二篇,针对界面原型原本考虑有两个方案:1.类windows模式,文件夹 ...

  2. Django完整的开发一个博客系统

    今天花了一些时间搭了一个博客系统,虽然并没有相关于界面的美化,但是发布是没问题的. 开发环境 操作系统:windows 7 64位 Django: 1.96 Python:2.7.11 IDE: Py ...

  3. 开发一个基于 Android系统车载智能APP

    很久之前就想做一个车载相关的app.需要实现如下功能: (1)每0.2秒更新一次当前车辆的最新速度值. (2)可控制性记录行驶里程. (3)不连接网络情况下获取当前车辆位置.如(北京市X区X路X号) ...

  4. 如何开发一个异常检测系统:使用什么特征变量(features)来构建异常检测算法

    如何构建与选择异常检测算法中的features 如果我的feature像图1所示的那样的正态分布图的话,我们可以很高兴地将它送入异常检测系统中去构建算法. 如果我的feature像图2那样不是正态分布 ...

  5. 如何开发一个异常检测系统:异常检测 vs 监督学习

    异常检测算法先是将一些正常的样本做为无标签样本来学习模型p(x),即评估参数,然后用学习到的模型在交叉验证集上通过F1值来选择表现最好的ε的值,然后在测试集上进行算法的评估.这儿用到了带有标签的数据, ...

  6. Python+MySQL开发医院网上预约系统(课程设计)二

    ---恢复内容开始--- 1:报错 1.1.创建表时报错 CREATE TABLE Admin (        A_ID VARCHAR(20) NOT NULL AUTO_INCREMENT, p ...

  7. Python+MySQL开发医院网上预约系统(课程设计)一

    一:开发环境的配置 1:桌面环境为cnetos7+python2.7 2:MySQL的安装与配置 1)MySQL的安装 MySQL官方文档: http://dev.mysql.com/doc/mysq ...

  8. HBase二次开发之搭建HBase调试环境,如何远程debug HBase源代码

    版本 HDP:3.0.1.0 HBase:2.0.0 一.前言 之前的文章也提到过,最近工作中需要对HBase进行二次开发(参照HBase的AES加密方法,为HBase增加SMS4数据加密类型).研究 ...

  9. linux入门--类UNIX系统详解

    有人说,这个世界上只有两种操作系统: UNIX 和类 UNIX 操作系统: 其它操作系统. 类 UNIX 系统(英文 Unix-like)既包括各种传统的 UNIX 系统,比如 FreeBSD.Ope ...

随机推荐

  1. Leaflet--建设移动设备友好的互动地图

    Leaflet 是一个为建设移动设备友好的互动地图,而开发的现代的.开源的 JavaScript 库.它是由 Vladimir Agafonkin 带领一个专业贡献者团队开发,尽管代码仅有 33 KB ...

  2. django 笔记13 CSRF

    CSRF a. CSRF原理 b. 无CSRF时存在隐患 c. Form提交(CSRF) d. Ajax提交(CSRF) CSRF请求头 x-CSRFToken HTTP_X_CSRFToken dj ...

  3. HDFS文件上传下载过程(详图)

  4. .NET简谈——跨进高级编程门槛的必经之路

    我们继续C#基础知识的学习,这篇文章对前面基础知识学习的朋友有着举足轻重的作用:为了延续基础知识学习的热情,我编写了这篇特殊的文章. 本篇文章的中心是想借“.NET简谈反射(动态调用)”一文继续发挥下 ...

  5. 不同框架实现的todomvc

    http://todomvc.com/ http://hao.jobbole.com/

  6. Git 内部原理 - (7)维护与数据恢复 (8) 环境变量 (9)总结

    维护与数据恢复 有的时候,你需要对仓库进行清理 - 使它的结构变得更紧凑,或是对导入的仓库进行清理,或是恢复丢失的内容. 这个小节将会介绍这些情况中的一部分. 维护 Git 会不定时地自动运行一个叫做 ...

  7. centOS7下 安装nodejs+nginx+mongodb+pm2部署vue项目

    一.购买服务器并远程连接 1.购买服务器和域名 可以选择阿里云或者是其他的厂商的服务器.然后会获得服务器ip地址,用户名和密码. 购买域名,将域名绑定到ip地址上. 2.下载xshell,winscp ...

  8. nodejs学习(一)--express+ejs生成项目

    一.说一下 首先保证node环境已经安装完毕,npm能正常使用,安装可自行百度,比较简单,在此不做赘述. 二.直接开码 安装 npm install express express-generator ...

  9. 「BZOJ3343」教主的魔法(分块+二分查找)

    题意: 给定一个数列,您需要支持以下两种操作:给[l,r]同加一个数询问[l,r]中有多少数字大于或等于v (n<=1000000,m<=3000) 题解 块内排序二分查询修改就用个数组存 ...

  10. Vue+ElementUI: 手把手教你做一个audio组件

    目的 本项目的目的是教你如何实现一个简单的音乐播放器(这并不难) 本项目并不是一个可以用于生产环境的element播放器,所以并没有考虑太多的兼容性问题 本项目不是ElementUI的一个音频插件,只 ...