热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

HBase概念学习(八)开发一个类twitter系统之表设计

这边文章先将可能的需求分析一下,设计出HBase表,下一步再开始编写客户端代码。TwiBase系统1、背景为了加深HBase基本概念的学习,参考HBase实战这本书实际

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

TwiBase系统


1、背景

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


2、需求

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

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


3、概要设计

3.1表设计

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

1)用户表

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

创建用户表的语句是:

create‘users‘, ‘info‘


其中用户名用作rowkey,这样能够快速根据用户登陆ID查找到用户所有基本信息。


2)推特表

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

创建推特表的语句是:

create‘twits‘, ‘twits‘


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


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

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


3)关系表

现在只有用户和推文功能,这明显不够,我们希望能够阅读其他人的推文,这就希望用户能够关注一些其他的用户。

创建关系表的命令是:

create‘follows‘, ‘f‘


具体我们需要存储哪些关系呢?

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

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

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


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

rowKey:用户A#1:用户B2:用户C3:用户D

rowKey:用户B#1:用户H2:用户C

这样可以很轻松回答问题1和问题3.

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


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

这样设计表:

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)处理。


这样很容易就能想到这样一个设计:

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

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

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

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

这样很容易就可以回答上面三个问题,分别是用户A关注了谁?用户A关注了用户B?谁关注了用户A。不过要注意,当查找用户A的粉丝列表时,往往不想把用户A关注了谁这些集合也返回给客户端,这个时候可以通过为扫描设置起始和停止键来做到。


这里需要再次优化,即使用MD5对用户名进行处理,得到定长的散列值,这样做有几个好处:

1可以抛弃掉分隔符,为扫描操作计算起始和停止键更加容易。

2行键长度统一,可以帮助你很好地预测读写性能。

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

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的昵称


4)推贴流表

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

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


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


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

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


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


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

规范化是关系型数据库里面的概念,每种重复信息都会放进一个自己的表,这样有两个好处:当发生更新和删除的时候,不用担心更新指定的数据的所有副本;通过保存单一副本,而不是多个副本,减少了占用的存储空间。需要查询时,使用SQL语句里面的join子句就可以轻易连接这些数据。

反规范化是一个相反的概念,数据是重复的,存储在多个地方,因为你不需要开销很大的join操作,这时候查询数据更加容易和快速。

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

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


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

推特流表创建的命令是:

create‘twitsStream‘, ‘info‘


推特流表设计是这样的:

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

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

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


(未完待续。。。)

若有什么疑问和指教,欢迎交流,联系邮箱: jiq408694711@163.com  季义钦
作为兴趣点,目前本人正在研究HBase和Hadoop


HBase概念学习(八)开发一个类twitter系统之表设计,,

HBase概念学习(八)开发一个类twitter系统之表设计


推荐阅读
  • importpymysql#一、直接连接mysql数据库'''coonpymysql.connect(host'192.168.*.*',u ... [详细]
  • 解决SQL Server数据库sa登录名无法连接的问题
    在安装SQL Server数据库后,使用Windows身份验证成功,但使用SQL Server身份验证时遇到问题。本文将介绍如何通过设置sa登录名的密码、启用登录名状态以及开启TCP协议来解决这一问题。 ... [详细]
  • 本文介绍了如何在 ASP.NET 中设置 Excel 单元格格式为文本,获取多个单元格区域并作为表头,以及进行单元格合并、赋值、格式设置等操作。 ... [详细]
  • SQL 连接详解与应用
    本文详细介绍了 SQL 连接的概念、分类及实际应用,包括内连接、外连接、自连接等,并提供了丰富的示例代码。 ... [详细]
  • 如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:1)延时时间较长,且资源占用率高 ... [详细]
  • 网络爬虫的规范与限制
    本文探讨了网络爬虫引发的问题及其解决方案,重点介绍了Robots协议的作用和使用方法,旨在为网络爬虫的合理使用提供指导。 ... [详细]
  • 本文介绍了 AngularJS 中的 $compile 服务及其用法,通过示例代码展示了如何使用 $compile 动态编译和链接 HTML 元素。 ... [详细]
  • [c++基础]STL
    cppfig15_10.cppincludeincludeusingnamespacestd;templatevoidprintVector(constvector&integer ... [详细]
  • ZooKeeper 入门指南
    本文将详细介绍ZooKeeper的工作机制、特点、数据结构以及常见的应用场景,包括统一命名服务、统一配置管理、统一集群管理、服务器动态上下线和软负载均衡。 ... [详细]
  • 自动验证时页面显示问题的解决方法
    在使用自动验证功能时,页面未能正确显示错误信息。通过使用 `dump($info->getError())` 可以帮助诊断和解决问题。 ... [详细]
  • Linux CentOS 7 安装PostgreSQL 9.5.17 (源码编译)
    近日需要将PostgreSQL数据库从Windows中迁移到Linux中,LinuxCentOS7安装PostgreSQL9.5.17安装过程特此记录。安装环境&#x ... [详细]
  • 数字资产量化交易通过大数据分析,以客观的方式制定交易决策,有效减少人为的主观判断和情绪影响。本文介绍了几种常见的数字资产量化交易策略,包括搬砖套利和趋势交易,并探讨了量化交易软件的开发前景。 ... [详细]
  • 自定义滚动条美化页面内容
    当页面内容超出显示范围时,为了提升用户体验和页面美观,通常会添加滚动条。如果默认的浏览器滚动条无法满足设计需求,我们可以自定义一个符合要求的滚动条。本文将详细介绍自定义滚动条的实现过程。 ... [详细]
  • 微软推出Windows Terminal Preview v0.10
    微软近期发布了Windows Terminal Preview v0.10,用户可以在微软商店或GitHub上获取这一更新。该版本在2月份发布的v0.9基础上,新增了鼠标输入和复制Pane等功能。 ... [详细]
  • 本文对SQL Server系统进行了基本概述,并深入解析了其核心功能。SQL Server不仅提供了强大的数据存储和管理能力,还支持复杂的查询操作和事务处理。通过MyEclipse、SQL Server和Tomcat的集成开发环境,可以高效地构建银行转账系统。在实现过程中,需要确保表单参数与后台代码中的属性值一致,同时在Servlet中处理用户登录验证,以确保系统的安全性和可靠性。 ... [详细]
author-avatar
手浪用户2602897055
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有