风炉煮茶系列(1)-聊聊HBase

本文涉及的产品
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 这一切的一切,还要从谷歌的那篇论文说起。。。。06年google对外发布了三大论文之一Bigtable: A Distributed Storage System for Structured Data(原文地址:链接)。从此以后,浩如烟海的各种所谓大数据存储类的产品或完全复用,或者部分借鉴,或者在此基础上微创新,基本上都能看到BigTable里面的设计影子。这里面有开源的HBase,公司内部使用的Lindorm,商业化的OTS,包括最近大火的ClickHorse基本上都或多或少的有类似的设计。而Hbase完全是基于BigTable开源的实现。

HBase的前世今生

这一切的一切,还要从谷歌的那篇论文说起。。。。

06年google对外发布了三大论文之一Bigtable: A Distributed Storage System for Structured Data(原文地址:链接)。从此以后,浩如烟海的各种所谓大数据存储类的产品或完全复用,或者部分借鉴,或者在此基础上微创新,基本上都能看到BigTable里面的设计影子。

这里面有开源的HBase,公司内部使用的Lindorm,商业化的OTS,包括最近大火的ClickHorse基本上都或多或少的有类似的设计。

而Hbase完全是基于BigTable开源的实现。

HBase八股介绍

OLAP(联机分析处理)场景的关键特征

  • 大多数以读为主的。
  • 数据以大的批次更新,很少单行更新(或者说没有单行);也可能没有更新。
  • 已添加到数据库的数据不能修改。
  • 读取的时候,从数据库总读取多行和列,但是只用其中几列数据。
  • 一般表都是一张大宽表。
  • 查询并发不高(QPS 100?)。
  • 检查查询允许一定的延迟。百毫秒级返回。
  • 列中的数据相对较小,数字和短字符。
  • 处理单个查询时需要很高的吞吐量。(十亿行)
  • 不需要事务
  • 数据一致性要求不是非常高。
  • 每个查询有一个大表,其他的都很小。
  • 查询结果不大。数据经过过滤和聚合,可以存在单个服务器。

一句话总结:做饭就一个人做,吃就大家都来吃。说错了,写的时候尽量批量些,读的性能发挥到机制。

为什么分析类查询更适合列式存储数据库

  • 针对分析类查询,通常只需要读取表的一小部分列。在列式数据库中你可以只读取你需要的数据。
  • 由于数据总是批量读取的,同时数据按列分别存储这也更容易压缩。
  • 同构数据压缩比高
  • 有效利用cache IO
  • 机械硬盘的特点也决定了顺序读消耗的时间更短。其实看下磁盘结构就容易理解了,如果被读取的数据相邻,那么盘片正常转动即可。如果不是顺序存储,还需要增加重新定位的时间。

总结:

  • 同构数据便于压缩,利于磁盘顺序读取特性。
  • 结合磁盘特性,顺序写入的时候,也会更加高效。

Hbase分布式策略

在学习Hbase之前,一定要带着一个问题,为什么Hbase比传统的关系型数据库性能要高很多?
说到这里就不得不提Hbase的数据结构,简而言之,Hbase维护的是一个Map数据,对于每一条数据,在Hbase上都是一个独立的Map,其中有一个RowKey,然后我们的查询都是基于这个RowKey进行的,在Hbase内部,维护了一个RowKey到具体分片数据的映射,类似于查字典,Hbase Master Server维护了一个字典的目录,这样查询的时候,你只需要提供RowKey,就能知道对应的数据存储的位置。但是关系型数据库,相当于从字典的第一页,查询直到查到数据位置,所以Hbase的时间复杂度理论上是接近O(1),而Mysql等关系型数据库尽管也通过B+树等数据结构做了优化,但是复杂度依然是O(Logn)。

当然,Hbase的缺点也很明显,无法根据条件进行查询,不支持事物,而且也不支持数据分析(如果是聚合,统计,最好使用ES)。

本质上Hbase是个列簇式数据库。

理解和感悟:我们在做技术选型的时候,不能一味的追求一些高大上的技术,要牢记一点,技术永远是服务于业务的,要找到合适的技术,而不是高大上的技术。

什么是列簇式存储?

先回顾下列式存储和行式存储。

  • 列式存储:以列先关存储架构进行数据存储的数据库,主要适用于OLAP
  • 行式存储:行相关存储体系架构进行空间分配,主要是和小批量的数据处理,常用语OLTP。

Hbase存储的特点:

  • 不同的列簇存储在不同的FileStore(HFile).
  • 数据按照Rowkey进行字典排序。
  • 每一列的数据在HFile中都是以KV存储。
  • 同一行的数据,如果列簇一样,是顺序放在一起的。

所以说HBase不是列存储也不是行存储,更像是一个列簇式存储,因为不同行相同的列簇是顺序存储的。同一行的不同列簇是存储的不同的位置的。

HBase实际上在HDFS上的存储形式:/hbase/data/default/<tbl_name>/<region_id>/<cf>/<hfile_id>

因此创建表的时候,必须指定列簇。

Hbase主要的组件

MasterServer,Zookeeper,Region Server.
其中:

  • MaserService负责表,列创建,维护集群状态。
  • RegionServer处理查询数据的操作,每个Region存储了Startkey-EndKey数量的数据,因为MasterServer维护了RowKey到Region的映射,因此可以很清楚的知道每一个RowKey存储在哪台RegionServer上。

那么问题来了,Hbase是如何管理这些映射呢?
通过下图就可以清晰的了解了,.META.表记录了Row和Region的映射关系,但是由于这个映射关系本身数据量可能很大,因此,又通过-ROOT-表来存储.META.表和Region的映射关系,而-ROOT-表要小得多,因此-ROOT-表是只有一个Region的,在Zookeeper中存储了-ROOT-表的地址



也就是说,一个Client访问HBase操作数据的时候,首先要经过Zookeeper
查询到-ROOT-的地址,然后,查询.META.表,最后查询RegionServer,进行相应的操作,但是HBase对这些数据做了Cache,所以不需要太担心性能问题。

HRegionServer架构图

每个HRegion对应了一个Table的一个Region(关键点,Region划分是和Table相关的)。

每个HStore对应一个Column Family的存储。因此需要将相同IO特性的数据放在一个CF里面。

几个关键点

  • RegionServer中存储的是什么?Hbase如何和HDFS通信?
  • 本质上Hbase的存储是HDFS。RegionServer上有多个Region,一个Region上有多个StoreFile(基于HFile)和memStore。一个RegionServer有一个HLog。
  • 说白了,因为MemStore是为了减少小写入。定时将内存的数据刷到HDFS中。但是因为多了这个设计,如果遇到断电等极端情况,为了防止内存的数据丢失设计的。类似Mysql的Bin-Log文件。
  • 写入MemStore的同时也会写入HLog。当MemStore写入文件的时候,HLog也会刷新,将写入文件的数据删除掉。
  • 针对于一次Hbase数据查询,过程是怎么样的?

Client->Zookeeper->-Root- ->  -META- ->用户表的RowKey对应的数据位置。

到Zookeeper及访问-ROOT- 甚至是-META-表都是有缓存的。具体的缓存逻辑要看下。

  • HRegionServer写入数据之后的单region扩容是如何完成的?
  • HStore是Hbase存储的核心,由MemStore和StoreFiles组成。MemStore是Sorted Memory Buffer。
  • 用户写入的数据会先放入MemStore.MemStore满了之后,会Flush成一个StoreFile(底层还是HFile)。
  • StoreFile文件数量到达一个阈值之后,触发Compact操作,多个StoreFiles合并成一个。合并过程中会进行版本合并和数据删除。
  • Compact之后形成的StoreFile会越来越大,然后触发阈值,进行Split。
  • 当前的Region也会Split成两个Region。父Region下线,新的Split region会被Hmaster分配到对应的RegionServer。原来一个Region的压力也进行分流。

     

  • Hlog的功能介绍
  • HRegionServer意外退出,memStore内存中的数据会丢失,因此引入Hlog.
  • 一个HRegionServer一个Hlog对象,Hlog是实现 Write Ahead Log的类。每次用户操作写入MemStore的同时也会写入Hlog。HLog会滚动清除已经写入文件StoreFiles的数据.
  • HRegionServer意外退出,Zk会感知到,HMaster首先处理遗留的Hlog.将不同Region的Log数据拆分,分别放到对应的Region目录下。
  • 失效的Region重新分配,领取到新Region的HRegionServer会进行LoadRegion过程。
  • 发现有历史HLog需要处理,会Replay HLog中的数据到MemStore.
  • 然后Flush到StoreFiles中。

Hbase数据模型

从网上摘抄了一个图,非常清晰的阐述了HBase的数据模型。


关于Hbase源码:https://github.com/apache/hbase/tree/master/ (代码量过大,感兴趣的话,可以网上搜写源码解析的文章)


Hbase局限

不支持二级索引(引申二级索引方案)

核心是主表+索引表的设计方式,其实Hbase也有内置的一个方案(Coprocessor协处理器

ES+Hbase。

Solr+Hbase.

HBase设计启发

如果只是为了学习原理而学习原理,那就真成八股文了,学以致用才是重点,接下来分享下基于Hbase的原理的设计注意事项

HBase热点问题

关键字:RowKey字典序存储

由于Rowkey是字典序存储,一个设计糟糕的Rowkey,会直接导致ReginServer热点问题,旱的旱死涝的涝死。

回顾下Hbase的架构图和数据模型,如果Rowkey没有很好的散列,就会导致:

  • 数据量不均匀:某个RegionServer下存储了大量的数据,而其他RegionServer下数据却相对少很多。
  • 数据访问频次不均匀:虽然数据量均匀分布,由于业务数据的特点(例如用户数据的RowKey按照 地域+UserID的方式设计),导致某个RegionServer下的数据更加活跃,被频繁访问。

为了避免热点问题,设计RowKey的时候需要注意尽可能的让Rowkey离散:

加盐

即在ID前缀加上一个随机字符串。以用户ID为例,加盐之后的RowKey:randomStr(length)+userID。

但由于前缀随机,业务查询的时候,如何获取RowKey是个很大的问题,所以并不推荐(除非前缀有固定的计算逻辑,例如经过哈希,但这方式放在了下面一类了)。

用哈希值

这个比较好理解,对ID进行哈希之后,作为Rowkey整体或者前缀的一部分。这样Rowkey本身足够散列,同时也可以按照固定的逻辑计算出Rowkey。是比较常用的方式。

反转ID

例如手机号,自增用户ID等,由于前缀相同,为了更好的散列,通常可以将ID反转之后进行存储。

HBase实践

案例:

在蚂蚁风控项目中,通过Redis+Hbase的方案(当然蚂蚁内部做了优化,TBASE对标Redis,Lindorm对标Hbase),承接了巅峰1400W/S的查询量级的数据访问。

如图:


在该项目中Lindorm(Hbase)中,通过RowKey${hash5}_${支付宝ID}_${支付明细ID} 的精心设计,让数据更加离散,防止出现热点数据。

在TBase(类比Redis),内存数据库中,直接将同一用户数据放在一起,让Value聚集,更方便数据压缩。

注:

  • 实际业务中Rowkey的最后一段并不是支付明细ID,而是一个叫做velocityID的东东,为了降低理解成本,用支付明细ID代替,不影响案例描述。
  • 为什么Lindorm中,明细要分开,本质上因为Hbase类的数据库,修改数据是极为不推荐的,一般都是增量写入的方式。


提问交流环节

问题1:支付宝以2088开头的支付宝账号ID,或者身份证号,作为RowKey是不是一个很好的设计?

问题2:您还有关于RowKey设计的一些最佳实践或者技巧分享么。

问题3:Hbase支持修改数据么?怎么支持?性能如何?

评论区留言讨论。

相关实践学习
lindorm多模间数据无缝流转
展现了Lindorm多模融合能力——用kafka API写入,无缝流转在各引擎内进行数据存储和计算的实验。
云数据库HBase版使用教程
&nbsp; 相关的阿里云产品:云数据库 HBase 版 面向大数据领域的一站式NoSQL服务,100%兼容开源HBase并深度扩展,支持海量数据下的实时存储、高并发吞吐、轻SQL分析、全文检索、时序时空查询等能力,是风控、推荐、广告、物联网、车联网、Feeds流、数据大屏等场景首选数据库,是为淘宝、支付宝、菜鸟等众多阿里核心业务提供关键支撑的数据库。 了解产品详情:&nbsp;https://cn.aliyun.com/product/hbase &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
5月前
|
存储 分布式数据库 数据库
Hbase学习二:Hbase数据特点和架构特点
Hbase学习二:Hbase数据特点和架构特点
84 0
|
7月前
|
存储 算法 分布式数据库
HBase原理 | HBase内部探险
HBase原理 | HBase内部探险
120 0
|
存储 SQL 分布式计算
HBase 与 Cassandra 架构对比分析的经验分享
HBase 与 Cassandra 架构对比分析的经验分享
|
负载均衡 Java Shell
HBase纪要(上)
HBase纪要(上)
137 0
|
存储 缓存 分布式计算
HBase纪要(中)
HBase纪要(中)
109 0
|
负载均衡 监控 Shell
HBase纪要(下)
HBase纪要(下)
105 0
|
缓存 分布式数据库 Hbase
【HBase】(六)详解 HBase 的读、写流程(面试重点)
【HBase】(六)详解 HBase 的读、写流程(面试重点)
275 0
【HBase】(六)详解 HBase 的读、写流程(面试重点)
|
SQL 搜索推荐 Java
「从零单排HBase 12」HBase二级索引Phoenix使用与最佳实践
「从零单排HBase 12」HBase二级索引Phoenix使用与最佳实践
543 0
「从零单排HBase 12」HBase二级索引Phoenix使用与最佳实践
|
SQL 存储 分布式计算
「从零单排HBase 11」HBase二级索引解决方案
「从零单排HBase 11」HBase二级索引解决方案
187 0
下一篇
无影云桌面