Hbase相关总结

Hbase

1、Hbase的数据写入流程
  • 由客户端发起写入数据的请求, 首先会先连接zookeeper

  • 从zookeeper中获取到当前HMaster的信息,并与HMaster建立连接从HMaster中获取RegionServer列表信息

  • 连接meta表对应的RegionServer地址, 从meta表获取当前要写入的表对应region被那个RegionServer所管理(一般只会返回一个RegionServer地址, 除非一次性写入多条数据)

  • 连接对应要写入RegionServer的地址, 开始写入数据, 将数据首先会写入到HLog中,然后将数据写入到对应Region的对应Store模块的MemStore中(有可能会写入到MemStore), 当这两个地方都写入完成后, 客户端认为数据写入完成了服务端写入过程: 异步操作(可能客户端执行N多次写入后, 服务端才开始对之前的数据进行操作)

  • 随着客户端不断的写入操作, memstore中数据会越来越多, 当内存中数据达到阈值(128M / 1h)后, 就会触发flush刷新机制, 将数据<最终>刷新到HDFS上形成StoreFile(小Hfile)文件.

  • 随着不断的刷新, 在HDFS上StoreFile文件会越来越多, 当StoreFlie文件数量达到阈值(3个及以上)后, 就会触发compact合并压缩机制, 将多个StoreFlie文件<最终>合并为一个大的HFile文件

  • 随着不断的合并, 大的HFile也会越来越大, 当大HFile达到一定的阈值(<最终>10GB)后, 就会触发Split分裂机制, 将大HFile进行一分为二,形成两个新的大HFile, 同时管理这个大HFile的Region也会形成两个新的Region, 形成的两个新的Region和两个新的大HFile 进行一对一的管理即可, 原来的Region和原来的大的HFile就会下线删除掉。

2、Hbase的数据读取流程
  • 客户端从zookeeper中获取Hmaster信息并且建立连接获取到regionserver列表信息

  • 客户端访问meta表所在的regionserver节点,获取到region所在的regionserver信息

  • 客户端访问具体的region所在的regionserver,找到对应的regionstore

  • 首先从memstore中读取数据,如果读取到了那么直接将数据返回,如果没有,则去blockcache读取数据

  • 如果blockcache中读取到数据,则直接返回数据给客户端,如果读取不到,则遍历storefile文件,查找数据

  • 如果从storefile中读取不到数据,则返回客户端为空,如果读取到数据,那么需要将数据先缓存到blockcache中(方便下一次读取),然后再将数据返回给客户端。

  • blockcache是内存空间,如果缓存的数据比较多,满了之后会采用LRU策略,将比较老的数据进行删除。

3、Hbase的LSM树

LSM树的由来

在了解LSM树之前,我们需要对hash表和B+树有所了解。hash表就不用说了,通过key值经过hash算法,直接定位到数据存储地址,然后取出value值。时间复杂度O(1),找数据和存数据就需要那么一下子,就给找到了。B+树我们常用的数据库Mysql的底层数据结构,例如我们的索引就是B+树结构。既有排序树的优点,能够很快沿着树枝找到目标节点,又能防止树的高度过高,大大减少磁盘IO次数。还能进行快速全表扫描遍历。

hash存储方式支持增、删、改以及随机读取操作,但不支持顺序扫描,对应的存储系统为key-value存储系统。对于key-value的插入以及查询,哈希表的复杂度都是O(1),明显比树的操作O(n)快,如果不需要有序的遍历数据,哈希表就是最佳选择。B+树不仅支持单条记录的增、删、读、改操作,还支持顺序扫描(B+树的叶子节点之间的指针),对应的存储系统就是关系数据库(Mysql等)。但是删除和更新操作比较麻烦。正是基于以上结构的分析,LSM树应运而生。LSM树(Log-Structured Merge Tree)存储引擎和B树存储引擎一样,同样支持增、删、读、改、顺序扫描操作。而且通过批量存储技术规避磁盘随机写入问题。当然凡事有利有弊,LSM树和B+树相比,LSM树牺牲了部分读性能,用来大幅提高写性能。

LSM树的原理

LSM树的设计思想非常简单:将对数据的修改增量保持在内存中,达到指定的大小限制后将这些修改操作批量写入磁盘,不过读取的时候稍微麻烦,需要合并磁盘中历史数据和内存中最近修改操作,所以写入性能大大提升,读取时可能需要先看是否命中内存,否则需要访问较多的磁盘文件。极端的说,基于LSM树实现的HBase的写性能比Mysql高了一个数量级,读性能低了一个数量级。(有舍有得)

LSM树原理把一棵大树拆分成N棵小树,它首先写入内存中,随着小树越来越大,内存中的小树会flush到磁盘中,磁盘中的树定期可以做merge操作,合并成一棵大树,以优化读性能。

在hbase中LSM的应用流程对应说下:

1、因为小树先写到内存中,为了防止内存数据丢失,写内存的同时需要暂时持久化到磁盘,对应了HBase的MemStore和HLog

2、MemStore上的树达到一定大小之后,需要flush到HRegion磁盘中(一般是Hadoop DataNode),这样MemStore就变成了DataNode上的磁盘文件StoreFile,定期HRegionServer对DataNode的数据做merge操作,彻底删除无效空间,多棵小树在这个时机合并成大树,来增强读性能。

lsm tree,理论上,可以是内存中树的一部分和磁盘中第一层树做merge,对于磁盘中的树直接做update操作有可能会破坏物理block的连续性,但是实际应用中,一般lsm有多层,当磁盘中的小树合并成一个大树的时候,可以重新排好顺序,使得block连续,优化读性能。

hbase在实现中,是把整个内存在一定阈值后,flush到disk中,形成一个file,这个file的存储也就是一个小的B+树,因为hbase一般是部署在hdfs上,hdfs不支持对文件的update操作,所以hbase这么整体内存flush,而不是和磁盘中的小树merge update,这个设计也就能讲通了。内存flush到磁盘上的小树,定期也会合并成一个大树。整体上hbase就是用了lsm tree的思路。

4、Hbase的架构组成

Hbase主要包含Hbase Client/HMaster/HRegionServer/Zookeeper/HDFS

HBase Client 负责接受用户的各种请求

  • HBase Client 为用户提供了访问 HBase 的接口,可以通过元数据表来定位到目标数据的 RegionServer,另外 HBase Client 还维护了对应的 cache 来加速 Hbase 的访问,比如缓存元数据的信息。

HRegionServer 负责实际数据的读写. 当访问数据时, 客户端直接与RegionServer通信

  • HBase的表根据Row Key的区域分成多个Region, 一个Region包含这这个区域内所有数据. 而Region server负责管理多个Region, 负责在这个Region server上的所有region的读写操作.

HMaster 负责管理Region的位置, DDL(新增和删除表结构)

  • 协调RegionServer

  • 在集群处于数据恢复或者动态调整负载时,分配Region到某一个RegionServer中

  • 管控集群,监控所有Region Server的状态

  • 提供DDL相关的API, 新建(create),删除(delete)和更新(update)表结构.

Zookeeper 负责维护和记录整个Hbase集群的状态

  • zookeeper探测和记录Hbase集群中服务器的状态信息.如果zookeeper发现服务器宕机,它会通知Hbase的master节点.

HDFS 负责为Hbase提供数据存储

  • HDFS 为 HBase 提供底层数据存储服务,同时为 HBase提供高可用的支持, HBase 将 HLog 存储在 HDFS 上,当服务器发生异常宕机时,可以重放 HLog 来恢复数据。

5、每天百亿数据如何写入Hbase
  1. 百亿数据:证明数据量非常大;

  2. 存入HBase:证明是跟HBase的写入数据有关;

  3. 保证数据的正确:要设计正确的数据结构保证正确性;

  4. 在规定时间内完成:对存入速度是有要求的。

解决思路:

  1. 假设一整天60x60x24 = 86400秒都在写入数据,那么每秒的写入条数高达100万条,HBase当然是支持不了每秒百万条数据的, 所以这百亿条数据可能不是通过实时地写入,而是批量地导入。批量导入推荐使用BulkLoad方式,性能是普通写入方式几倍以上;

  2. 存入HBase:普通写入是用JavaAPI put来实现,批量导入推荐使用BulkLoad;

  3. 保证数据的正确:这里需要考虑RowKey的设计、预建分区和列族设计等问题;

  4. 还有region热点的问题,如果你的hbase数据不是那种每天增量的数据,建议跑个mapreduce对你的数据进行各评判,看看如何能将数据尽可能均匀的分配到每个region中,当然这需要预先分配region

6、Hbase的RowKey设计原则

rowkey长度原则

rowkey是一个二进制码流,可以是任意字符串,最大长度64kb,实际应用中一般为10-100bytes,以byte[]形式保存,一般设计成定长。议越短越好,不要超过16个字节,设计过长会降低memstore内存的利用率和HFile存贮数据的效率。

原因如下,首先一条数据是根据rowkey来当成索引的,如果过长就会快速占据memstore的128M,然后被刷写到磁盘,也就是说相同的空间存贮的内容被rowkey占据了一大部分,减少了主要内容的存贮

rowkey唯一原则

必须在设计上保证其唯一性,rowkey是按照字典顺序排序存储的,因此,设计rowkey的时候,要充分利用这个排序的特点,可以将经常读取的数据存储到一块,将最近可能会被访问的数据放到一块。

rowkey散列原则

建议将rowkey的高位作为散列字段,这样将提高数据均衡分布在每个RegionServer,以实现负载均衡的几率。如果没有散列字段,首字段直接是时间信息。

所有的数据都会集中在一个RegionServer上,这样在数据检索的时候负载会集中在个别的RegionServer上,造成热点问题,会降低查询效率。

其中常见的散列方法有如下:

  • reverse反转,将原来的rowkey反过来

  • 加盐,随机生成字符串加载rowkey前面

  • hashcode或求模,通过一个固定的算法计算hash值获得一个字符串加载rowkey前面 如果前缀是纯数字的可以使用求模方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值