HBase 学习分享

作者:陈云龙

MySql的性能瓶颈

虽说关系型数据库,如MySql已经足够满足我们大部分活动开发的需求,然而有些时候你可曾面对产品看似普通且合理的需求,例如:1、能否让网页活动拉取用户的游戏好友关系链从而更精准的推送Tips?2、判断用户是否在所有大区都没有角色这类需求时却感到了深深的蛋疼,Why?

在现有条件下,我们处理需求1时的方法通常是用DC从tlog中拉取用户好友信息并以如下可能的两种方式建库存储:

左边的表结构是将每个用户的一个好友作为一条记录插入库中,通常我们也就是这么做的。然而如果有百万、千万级的用户,每个用户又有着多个好友。且不考虑单台服务器能否承载如此大的数据,从如此庞大的数据中检索出单个用户好友的sql语句的效率可以想象。右边的表结构虽然每个用户只有一条记录,查询效率不错,但是不可行。因为关系型数据库的表结构是固定的,我们无从得知一个用户会有多少个好友,因此无法确定字段数。肿么办?

需求2的通常处理方法同需求1,不仅效率低tlog拉数据还有着一天的数据延迟,用户体验极差。什么?你说可以通过IDIP接口来实时查询用户是否有角色?如果你觉得炫舞39个大区发39条IDIP指令可以不超时的话可以那么做….

HBase简介

为了解决上述问题,我们决定引入HBase,HBase是一个稀疏的,长期存储的,多维度的,排序的映射表,采用Key-Value方式存储数据。这张表的索引是行关键字,列关键字和时间戳。每个值是一个不解释的字符数组,数据都是字符串,没类型,属于非关系型的分布式数据库。

如果采用HBase,存储用户各大区注册时间信息的表结构可以变成这样:

row key:是用来检索记录的主键,其作用类似于Mysql中的主键。访问hbase table中的行,只有三种方式:

1 、通过单个row key访问

2 、通过row key的range

3、 全表扫描

Row key行键 (Row key)可以是任意字符串(最大长度是 64KB,实际应用中长度一般为 10-100bytes),在hbase内部,row key保存为字节数组。

列族

Column Family: HBase表中的每个列,都归属与某个列族。列族是表的chema的一部分(而列不是),必须在使用表之前定义。列名都以列族作为前缀。

TimeStamp:HBase中通过row和columns确定的一个数据存贮单元称为cell。每个 cell都保存着同一份数据的多个版本。版本通过时间戳来索引。时间戳的类型是 64位整型。时间戳可以由hbase(在数据写入时自动 )赋值,此时时间戳是精确到毫秒的当前系统时间。时间戳也可以由客户显式赋值。如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳。每个 cell中,不同版本的数据按照时间倒序排序,即最新的数据排在最前面。

Cell:由{row key, column( =<family> + <label>), version} 唯一确定的单元。cell中的数据是没有类型的,全部是字节码形式存贮。

由于HBase采用Key-Value的存储格式,将用户QQ号作为rowkey就能高效的查询到所对应的信息字符串,加以解析即可得到我们所需要的结果。由于HBase是非关系型数据库,Table在水平方向有一个或者多个Column Family组成,一个Column Family中可以由任意多个Column组成,即Column Family支持动态扩展,无需预先定义Column的数量以及类型。在HBase中,表结构还可以是这样的:

需要注意的是,HBase中所有的行都按照字典序进行排列,字典序对int排序的结果是1,10,100,11,12,13,14,15,16,17,18,19,2,20,21,如下图:

行的一次读写是原子操作 (不论一次读写多少列)。这个设计决策能够使用户很容易的理解程序在对同一个行进行并发更新操作时的行为。

HBase不支持条件查询和Order by等查询,读取记录只能按Row key(及其range)或全表扫描,因此Row key需要根据业务来设计以利用其存储排序特性(Table按Row key字典序排序如1,10,100,11,2)提高性能,如果我们希望将行按自然顺序排列,可以在最左边补0。

上述看起来似乎还是没解决问题,如果存放海量用户的关系链数据,单台服务器还是难以负载,HBase又是如何解决数据的存储与检索问题的呢?

HBase的数据存储与检索原理

HBase在行的方向上可以分为多个region,一个region类似于一张mysql中的表.HRegion与表的不同之处在于随着数据不断插入表,region不断增大,当增大到一个阀值的时,Hregion就会等分会两个新的Hregion。当table中的行不断增多,就会有越来越多的Hregion。

Region是HBase分布式存储的最小单位,数据存放在不同服务器上的的region中,而一个region只可能存放于一台服务器上,那么当我们需要从HBase中查询数据的时候,它又是怎样从分布在不同机器上的region中检索数据的呢?

这是由于每个region都记录了Row的Start和Endkey,并由Master交给相应的RegionServer进行管理存储,如下图所示:

那么是如何得知所要查询的数据存放在哪个RegionServer上呢?在HBase中.META.表记录了每个RS上存放数据的Start key和End Key以及RegionServer地址等信息。

现在假设我们要从Table里面查询一条RowKey是100的数据。那么我们应该遵循以下步骤:

  1. 从.META.表里面查询哪个Region包含这条数据。
  2. 获取管理这个Region的RegionServer地址。

  1. 连接这个RegionServer, 查到这条数据。

然而问题也随之而来,.META.自己也是一张表,虽然它记录了数据在RS中的位置信息,如果表的region实在太多导致META表中的数据也多到让其自身分割为多个region存放于不同机器上我们该如何寻址?因此在.META.表之上还有一层-ROOT-表,它用来存放所有.META.表的信息且只有一个region,再由ZooKeeper记录ROOT表的位置。因此假设要检索某条数据,大致流程如下:

HBase存储系统的架构:

HBase分布式数据库,只是分布式存储系统中的一部分,其系统组成包含HDFS、Region Server、Master节点、ZooKeeper集群等四大部分。各部分的具体功能如下描述:

HDFS:

HBase底层存储上依赖于HDFS,HDFS保证了HBase的高可靠性。HDFS为Region Server和Master节点提供分布式存储服务,同时保证数据的可靠性,主要功能如下:

1、提供元数据和表数据的存储

2、数据多副本保存,保证数据的高可靠性和高可用性

Master节点主要负责:

1、为Region Server(在hbase中称之为Region Server)分配region。

2、负责整个集群的负载均衡

3、维护集群中的元数据

4、负责监控整个集群,发现失效的Region Server,并重新分配其上的Region

RegionServer节点主要负责:

  1、管理Master分配的Region,处理来自客户端对Region的读取工作。

  2、切分在运行过程中变的过大的Region。

  3、负责和底层的HDFS交互,存储数据。

Zookeeper节点功能:

  1、保证集群中仅仅存在一个Master能够运行。

  2、监控Region Server的状态,通过回调的形式通知Master RegionServer的上下线的信息。

  3、存储寻址的入口地址。

Hbase存储系统基本上按照google bigtable的论文来实现,基本上的架构如下:

HBase——不仅仅是存储性能的提升

由上图可知,HBase存储系统的底层存储依赖于HDFS(分布式文件系统),分布式的存储方式决定了它优于普通数据库的海量数据存储能力,可是它优秀的仅仅只是存储性能吗?NO!

假如有一个活动,产品想提出所有于某日之后新玩家(所有大区均无角色)名单,并为他们发放新手礼包。按照我们运营开发的传统思想,只可能通过DC从tlog里拉取注册玩家信息,并通过定时脚本遍历该玩家所有大区的角色信息。且不谈这数据量之大mysql是否能够承受,即使能承受,从如此海量的数据找出我们所需要的答案,仅凭脚本所在的一台机器,这个脚本要跑到猴年马月?

既然一台机器的运算能力不够,那多台机器又如何呢?考虑到HBase中的数据存储于多台服务器中,如果能在每台服务器中执行脚本得出结果,再将结果进行合并岂不是能大幅度提高运算效率?

谷歌的MapReduce 编程模型为我们提供了解决方法,它通常把一个问题分成两个子步骤:Map 函数被用来采用大输出并将其分为若干个更小的块,然后将此数据交给其它空闲并且能够用它做一些事情的进程。而Reduce 函数的功能则

是将单一答案从Map所产生的若干个中间输出中化简并带给最终输出。对于上述假设活动,如果运用HBase+MapReduce处理该需求的过程如下:

HBase对于活动开发来说不仅仅是提供了大数据的存储能力,还提供了高效的离线并行计算、数据分析能力,对于将来的活动开发有着极大的意义。

上述就是我总结的一些HBase知识小结,希望大家积极分享、拍砖共同学习。

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏运维小白

18.7 LVS介绍

LVS介绍 LVS是由国人章文嵩开发 流行度不亚于apache的httpd,基于TCP/IP做的路由和转发,稳定性和效率很高 LVS最新版本基于Linux内核2...

1828
来自专栏desperate633

浅谈应对数据库高负载访问的几种思路1.使用优化查询的方法2.主从复制, 读写分离, 负载均衡3.数据库分表, 分区, 分库

目前,大部分的主流关系型数据库都提供了主从复制的功能,通过配置两台(或多台)数据库的主从关系,可以将一台数据库服务器的数据更新同步到另一台服务器上。网站可以利用...

601
来自专栏一名合格java开发的自我修养

交易系统使用storm,在消息高可靠情况下,如何避免消息重复

概要:在使用storm分布式计算框架进行数据处理时,如何保证进入storm的消息的一定会被处理,且不会被重复处理。这个时候仅仅开启storm的ack机制并不能解...

713
来自专栏博客园迁移

分布式事务 小结

分布式事务    如果系统规模较小,数据表都在一个数据库实例上,上述本地事务方式可以很好地运行,   但是如果系统规模较大,比如用户A账户表和用户B账户表显然不...

621
来自专栏网络

服务器模型——从单线程阻塞到多线程非阻塞(上)

前言的前言 服务器模型涉及到线程模式和IO模式,搞清楚这些就能针对各种场景有的放矢。该系列分成三部分: 单线程/多线程阻塞I/O模型 单线程非阻塞I/O模型 多...

1875
来自专栏IT技术精选文摘

网站海量数据和高并发解决方案(一)

现在无论是企业的业务系统还是互联网上的网站程序都面临着数据量大的问题,这个问题如果解决不好将严重的影响系统的运行速度,下面就针对这个问题的各种解决解决方案进行介...

2775
来自专栏服务端技术杂谈

搞定分库后数据冗余和数据一致

当单个数据库数据量达到一定程度后,我们可以采用多个从库解决读请求的系统瓶颈。 而写请求的系统瓶颈往往需要通过分库解决。

913
来自专栏云计算认知升级

【腾讯云的1001种玩法】十分钟轻松搞定云架构 · 负载均衡的最佳实践

视频内容 大家好,这节课,我们来看一看负载均衡的最佳实践。 虽然说我们明白了,负载均衡是什么和能干什么,但是想要真正用好负载均衡还是差一些火候,这里,我们来...

2119
来自专栏架构师之路

session一致性架构设计实践

一、缘起 什么是session? 服务器为每个用户创建一个会话,存储用户的相关信息,以便多次请求能够定位到同一个上下文。 Web开发中,web-server可...

3799
来自专栏大闲人柴毛毛

架构高性能网站秘笈(七)——负载均衡

什么是负载均衡? 当一台服务器的性能达到极限时,我们可以使用服务器集群来提高网站的整体性能。那么,在服务器集群中,需要有一台服务器充当调度者的角色,用户的所有...

3346

扫码关注云+社区