1.简介

HBase从诞生至今将近10年,在apache基金会的孵化下,已经变成一个非常成熟的项目,也有许多不同的公司支持着许多不同的分支版本,如cloudra等等。

HBase不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库。另一个不同的是HBase基于列的而不是基于行的模式。

hadoop所有应用都是构建于hdfs(它提供高可靠的底层存储支持,几乎已经成为分布式文件存储系统事实上的工业标准)之上的分布式列存储系统,主要用于海量结构化数据存储。通过Hadoop生态圈,可以看到HBase的身影,可见HBase在Hadoop的生态圈是扮演这一个重要的角色那就是 实时、分布式、高维数据 的数据存储;

  • 特性:

    • 强一致性读写:HBase不是“Eventual Consistentcy(最终一致性)”数据存储,这让它很适合高速计数聚合类任务;
  • 自动分片(Automatic sharding):HBase表通过region分布在集群中,数据增长时,region会自动分割并重新分布;

  • RegionServer自动故障转移

  • Hadoop/HDFS集成:HBase支持开箱即用HDFS作为它的分布式文件系统;

  • MapRecue:HBase通过MapRecue支持大并发处理;

  • Java客户端API:HBase支持易于使用的Java API进行编程访问;

  • Thrift/REST API:HBase也支持Thrift和Rest作为非Java前端访问;

  • Block Cache和Bloom Filter:对于大容量查询优化,HBase支持Block Cache和Bloom Filter;

  • 运维管理:HBase支持JMX提供内置网页用于运维。

  • HBase的优点

    • 列可以动态增加,并且列为空就不存储数据,节省存储空间;
  • HBase可以自动切分数据,使得数据存储自动具有水平扩展功能;

  • HBase可以提供高并发读写操作的支持;

  • 与Hadoop MapRecue相结合有利于数据分析;

  • 容错性;版权免费;非常灵活的模式设计(或者说没有固定模式的限制);

  • 可以跟Hive集成,使用类SQL查询;

  • 自动故障转移;客户端接口易于使用;

  • 行级别原子性,即PUT操作一定是完全成功或者完全失败。

  • HBase的缺点

    • HDFS是分布式文件系统,适合保存大文件。官方宣称它并非普通用途的文件系统,不提供文件的个别记录的快速查询。
  • 另一方面,HBase基于HDFS,并能够提供大表的记录快速查询和更新。HBase内部将数据放到索引好的“StoreFiles”存储文件中,以便提供高速查询,而存储文件位于HDFS中。

 

2.典型应用

  1. FacebookFacebook用HBase存储在线消息,每天数据量近百亿,每月数据量250 ~ 300T, HBase读写比基本在1:1,吞吐量150w qps

  2. 小米10+在线HBase集群,好几百台服务器,米聊历史数据,消息push系统等多个重要应用系统都建立在HBase基础之上网易哨兵监控系统,云信历史数据,日志归档数据等一系列重要应用底层都由HBase提供服务。

  3. 网易哨兵监控系统,云信历史数据,日志归档数据等一系列重要应用底层都由HBase提供服务。


 

3.适用场景

  1. 写密集型应用,每天写入量巨大,而相对读数量较小的应用,比如IM的历史消息,游戏的日志等等

  2. 不需要复杂查询条件来查询数据的应用,HBase只支持基于rowkey的查询,对于HBase来说,单条记录或者小范围的查询是可以接受的,大范围的查询由于分布式的原因,可能在性能上有点影响,而对于像SQL的join等查询,HBase无法支持。

  3. 对性能和可靠性要求非常高的应用,由于HBase本身没有单点故障,可用性非常高。 数据量较大,而且增长量无法预估的应用,HBase支持在线扩展,即使在一段时间内数据量呈井喷式增长,也可以通过HBase横向扩展来满足功能。

    • HBase作为默认的大数据时代的存储,基本解决以下三大类的场景:
  1. 平台类:存放是平台的产品,就是其它软件的存储,比如目前很就行的Kylin,阿里内部的日志同步工具TT,图组件Titan等。此类存放的往往平台的数据,有时候往往是无业务含义的。作为平台的底层存储使用。

  2. 用户行为类:此类主要是面向各个业务系统。这里的用户不仅仅指的人,也包括物,比如物联网。在阿里主要还是人产生的数据,比如:淘宝收藏夹、交易数据、旺旺聊天记录等等。这里使用比较直接,就直接存放HBase,再读取。难度就是需要支持千万级别的并发写访问及读取,需要解决服务质量的问题。

  3. 报表类的需求:比如报表、大屏等,如阿里巴巴的天猫双十一大屏。


 

4.Habse数据结构

HBase不是一个关系型数据库,它需要不同的方法定义你的数据模型,HBase实际上定义了一个四维数据模型,下面就是每一维度的定义:

  • 行键:每行都有唯一的行键,行键没有数据类型,它内部被认为是一个字节数组。

    • 决定一行数据的唯一标识
    • RowKey是按照字典顺序排序的。
    • Row key最多只能存储64k的字节数据。
  • 列簇:数据在行中被组织成列簇,每行有相同的列簇,但是在行之间,相同的列簇不需要有相同的列修饰符。在引擎中,HBase将列簇存储在它自己的数据文件中,所以,它们需要事先被定义,此外,改变列簇并不容易。

  • 列修饰符:列簇定义真实的列,被称之为列修饰符,你可以认为列修饰符就是列本身。

    • Cell单元格:

      • 由行和列的坐标交叉决定;
      • 单元格是有版本的(由时间戳来作为版本);
      • 单元格的内容是未解析的字节数组(Byte[]),cell中的数据是没有类型的,全部是字节码形式存贮。
      • 由{row key,column(= +),version}唯一确定的单元。
  • 版本:每列都可以有一个可配置的版本数量,你可以通过列修饰符的制定版本获取数据。

    • Timestamp时间戳:

      在HBase每个cell存储单元对同一份数据有多个版本,根据唯一的时间戳来区分每个版本之间的差异,不同版本的数据按照时间倒序排序,最新的数据版本排在最前面。

      • 时间戳的类型是64位整型。
      • 时间戳可以由HBase(在数据写入时自动)赋值,此时时间戳是精确到毫 秒的当前系统时间。
      • 时间戳也可以由客户显式赋值,如果应用程序要避免数据版本冲突, 就必须自己生成具有唯一性的时间戳。

如图1中所示,通过行键获取一个指定的行,它由一个或多个列簇构成,每个列簇有一个或多个列修饰符(图1中称为列),每列又可以有一个或多个版本。为了获取指定数据,你需要知道它的行键、列簇、列修饰符以及版本。当设计HBase数据模型时,对考虑数据是如何被获取是十分有帮助的。你可以通过以下两种方式获得HBase数据:
* 通过他们的行键,或者一系列行键的表扫描。

  • 使用map-reduce进行批操作

 

5.Habse数据结表设计

key是我们所提到过的行键,value是列簇的集合。你可以通过key检索到value,或者换句话说,你可以通过行键“得到”行,或者你能通过给定起始和终止行键检索一系列行,这就是前面提到的表扫描。你不能实时的查询一个列的值,这就引出了一个重要的话题:行键的设计。

  • 有两个原因令行键的设计十分重要:
  1. 表扫描是对行键的操作,所以,行键的设计控制着你能够通过HBase执行的实时/直接获取量。
  2. 当在生产环境中运行HBase时,它在HDFS上部运行,数据基于行键通过HDFS,如果你所有的行键都是以user-开头,那么很有可能你大部分数据都被分配一个节点上(违背了分布式数据的初衷),因此,你的行键应该是有足够的差异性以便分布式地通过整个部署。

 

6.Hbase优化

  1. 预先分区

默认情况下,在创建 HBase 表的时候会自动创建一个 Region 分区,当导入数据的时候,所有的 HBase 客户端都向这一个 Region 写数据,直到这个 Region 足够大了才进行切分。一种可以加快批量写入速度的方法是通过预先创建一些空的 Regions,这样当数据写入 HBase 时,会按照 Region 分区情况,在集群内做数据的负载均衡。

  1. Rowkey优化

HBase 中 Rowkey 是按照字典序存储,因此,设计 Rowkey 时,要充分利用排序特点,将经常一起读取的数据存储到一块,将最近可能会被访问的数据放在一块。

此外,Rowkey 若是递增的生成,建议不要使用正序直接写入 Rowkey,而是采用 reverse 的方式反转Rowkey,使得 Rowkey 大致均衡分布,这样设计有个好处是能将 RegionServer 的负载均衡,否则容易产生所有新数据都在一个 RegionServer 上堆积的现象,这一点还可以结合 table 的预切分一起设计。

  1. 减少列族数量

不要在一张表里定义太多的 ColumnFamily。目前 Hbase 并不能很好的处理超过 2~3 个 ColumnFamily 的表。因为某个 ColumnFamily 在 flush 的时候,它邻近的 ColumnFamily 也会因关联效应被触发 flush,最终导致系统产生更多的 I/O。

  1. 缓存策略

创建表的时候,可以通过 HColumnDescriptor.setInMemory(true) 将表放到 RegionServer 的缓存中,保证在读取的时候被 cache 命中。

  1. 设置存储生命期

创建表的时候,可以通过 HColumnDescriptor.setTimeToLive(int timeToLive) 设置表中数据的存储生命期,过期数据将自动被删除。

  1. 硬盘配置

每台 RegionServer 管理 10~1000 个 Regions,每个 Region 在 1~2G,则每台 Server 最少要 10G,最大要1000*2G=2TB,考虑 3 备份,则要 6TB。方案一是用 3 块 2TB 硬盘,二是用 12 块 500G 硬盘,带宽足够时,后者能提供更大的吞吐率,更细粒度的冗余备份,更快速的单盘故障恢复。

  1. 分配合适的内存给RegionServer服务

在不影响其他服务的情况下,越大越好。例如在 HBase 的 conf 目录下的 hbase-env.sh 的最后添加 export HBASE_REGIONSERVER_OPTS="-Xmx16000m$HBASE_REGIONSERVER_OPTS”
其中 16000m 为分配给 RegionServer 的内存大小。

  1. 写数据的备份数

备份数与读性能成正比,与写性能成反比,且备份数影响高可用性。有两种配置方式,一种是将 hdfs-site.xml拷贝到 hbase 的 conf 目录下,然后在其中添加或修改配置项 dfs.replication 的值为要设置的备份数,这种修改对所有的 HBase 用户表都生效,另外一种方式,是改写 HBase 代码,让 HBase 支持针对列族设置备份数,在创建表时,设置列族备份数,默认为 3,此种备份数只对设置的列族生效。

  1. WAL(预写日志)

可设置开关,表示 HBase 在写数据前用不用先写日志,默认是打开,关掉会提高性能,但是如果系统出现故障(负责插入的 RegionServer 挂掉),数据可能会丢失。配置 WAL 在调用 JavaAPI 写入时,设置 Put 实例的WAL,调用 Put.setWriteToWAL(boolean)。

  1. 批量写

HBase 的 Put 支持单条插入,也支持批量插入,一般来说批量写更快,节省来回的网络开销。在客户端调用JavaAPI 时,先将批量的 Put 放入一个 Put 列表,然后调用 HTable 的 Put(Put 列表) 函数来批量写。

  1. 客户端一次从服务器拉取的数量

通过配置一次拉去的较大的数据量可以减少客户端获取数据的时间,但是它会占用客户端内存。有三个地方可进行配置:

  1. 在 HBase 的 conf 配置文件中进行配置 hbase.client.scanner.caching;

  2. 通过调用HTable.setScannerCaching(intscannerCaching) 进行配置;

  3. 通过调用Scan.setCaching(intcaching) 进行配置。三者的优先级越来越高。

  1. RegionServer的请求处理I/O线程数

较少的 IO 线程适用于处理单次请求内存消耗较高的 Big Put 场景 (大容量单次 Put 或设置了较大 cache 的Scan,均属于 Big Put) 或 ReigonServer 的内存比较紧张的场景。

较多的 IO 线程,适用于单次请求内存消耗低,TPS 要求 (每秒事务处理量 (TransactionPerSecond)) 非常高的场景。设置该值的时候,以监控内存为主要参考。

在 hbase-site.xml 配置文件中配置项为 hbase.regionserver.handler.count。

  1. Region的大小设置

配置项为 hbase.hregion.max.filesize,所属配置文件为 hbase-site.xml.,默认大小 256M。

在当前 ReigonServer 上单个 Reigon 的最大存储空间,单个 Region 超过该值时,这个 Region 会被自动 split成更小的 Region。小 Region 对 split 和 compaction 友好,因为拆分 Region 或 compact 小 Region 里的StoreFile 速度很快,内存占用低。缺点是 split 和 compaction 会很频繁,特别是数量较多的小 Region 不停地split, compaction,会导致集群响应时间波动很大,Region 数量太多不仅给管理上带来麻烦,甚至会引发一些Hbase 的 bug。一般 512M 以下的都算小 Region。大 Region 则不太适合经常 split 和 compaction,因为做一次 compact 和 split 会产生较长时间的停顿,对应用的读写性能冲击非常大。

此外,大 Region 意味着较大的 StoreFile,compaction 时对内存也是一个挑战。如果你的应用场景中,某个时间点的访问量较低,那么在此时做 compact 和 split,既能顺利完成 split 和 compaction,又能保证绝大多数时间平稳的读写性能。compaction 是无法避免的,split 可以从自动调整为手动。只要通过将这个参数值调大到某个很难达到的值,比如 100G,就可以间接禁用自动 split(RegionServer 不会对未到达 100G 的 Region 做split)。再配合 RegionSplitter 这个工具,在需要 split 时,手动 split。手动 split 在灵活性和稳定性上比起自动split 要高很多,而且管理成本增加不多,比较推荐 online 实时系统使用。内存方面,小 Region 在设置memstore 的大小值上比较灵活,大 Region 则过大过小都不行,过大会导致 flush 时 app 的 IO wait 增高,过小则因 StoreFile 过多影响读性能。

  1. 操作系统参数

Linux系统最大可打开文件数一般默认的参数值是1024,如果你不进行修改并发量上来的时候会出现“Too Many Open Files”的错误,导致整个HBase不可运行,你可以用ulimit -n 命令进行修改,或者修改/etc/security/limits.conf和/proc/sys/fs/file-max 的参数,具体如何修改可以去Google 关键字 “linux limits.conf ”

  1. Jvm配置

修改 hbase-env.sh 文件中的配置参数,根据你的机器硬件和当前操作系统的JVM(32/64位)配置适当的参数

HBASE_HEAPSIZE 4000 HBase使用的 JVM 堆的大小

HBASE_OPTS "‐server ‐XX:+UseConcMarkSweepGC"JVM GC 选项

HBASE_MANAGES_ZKfalse 是否使用Zookeeper进行分布式管理

  1. 持久化

重启操作系统后HBase中数据全无,你可以不做任何修改的情况下,创建一张表,写一条数据进行,然后将机器重启,重启后你再进入HBase的shell中使用 list 命令查看当前所存在的表,一个都没有了。是不是很杯具?没有关系你可以在hbase/conf/hbase-default.xml中设置hbase.rootdir的值,来设置文件的保存位置指定一个文件夹,例如:file:///you/hbase-data/path,你建立的HBase中的表和数据就直接写到了你的磁盘上,同样你也可以指定你的分布式文件系统HDFS的路径例如:hdfs://NAMENODE_SERVER:PORT/HBASE_ROOTDIR,这样就写到了你的分布式文件系统上了。

  1. 缓冲区大小

hbase.client.write.buffer

这个参数可以设置写入数据缓冲区的大小,当客户端和服务器端传输数据,服务器为了提高系统运行性能开辟一个写的缓冲区来处理它,这个参数设置如果设置的大了,将会对系统的内存有一定的要求,直接影响系统的性能。

  1. 扫描目录表

hbase.master.meta.thread.rescanfrequency

定义多长时间HMaster对系统表 root 和 meta 扫描一次,这个参数可以设置的长一些,降低系统的能耗。

  1. split/compaction时间间隔

hbase.regionserver.thread.splitcompactcheckfrequency

这个参数是表示多久去RegionServer服务器运行一次split/compaction的时间间隔,当然split之前会先进行一个compact操作.这个compact操作可能是minorcompact也可能是major compact.compact后,会从所有的Store下的所有StoreFile文件最大的那个取midkey.这个midkey可能并不处于全部数据的mid中.一个row-key的下面的数据可能会跨不同的HRegion。

  1. 缓存在JVM堆中分配的百分比

hfile.block.cache.size

指定HFile/StoreFile 缓存在JVM堆中分配的百分比,默认值是0.2,意思就是20%,而如果你设置成0,就表示对该选项屏蔽。

  1. ZooKeeper客户端同时访问的并发连接数

hbase.zookeeper.property.maxClientCnxns

这项配置的选项就是从zookeeper中来的,表示ZooKeeper客户端同时访问的并发连接数,ZooKeeper对于HBase来说就是一个入口这个参数的值可以适当放大些。

  1. memstores占用堆的大小参数配置

hbase.regionserver.global.memstore.upperLimit

在RegionServer中所有memstores占用堆的大小参数配置,默认值是0.4,表示40%,如果设置为0,就是对选项进行屏蔽。

  1. Memstore中缓存写入大小

hbase.hregion.memstore.flush.size

Memstore中缓存的内容超过配置的范围后将会写到磁盘上,例如:删除操作是先写入MemStore里做个标记,指示那个value, column 或 family等下是要删除的,HBase会定期对存储文件做一个major compaction,在那时HBase会把MemStore刷入一个新的HFile存储文件中。如果在一定时间范围内没有做major compaction,而Memstore中超出的范围就写入磁盘上了。

最新文章

  1. 彻底搞懂Javascript的“==”
  2. jsf初学解决GlassFish Server 无法启动
  3. JavaSE基础第一篇
  4. Linux 下 MySQL 的彻底卸载和安装配置字符集
  5. 自动脚本工具新版 v2.0
  6. ACM2054_A=B
  7. ExtJs 学习笔记
  8. 嵌入式设备web服务器
  9. QT中代码中与设计器中控件信号与SLOT连接(原来还可以这样连接)
  10. css样式写一个三角形
  11. android账号与同步之发起同步
  12. Android -- 带你从源码角度领悟Dagger2入门到放弃(二)
  13. Java----list常用方法汇总
  14. php中的抽象方法和抽象类,简单明了,一点通
  15. JavaScript实现HTML页面集成QQ空间分享功能
  16. Python之Requests的安装与基本使用
  17. getent passwd 不能访问到 ldap 的用户
  18. 浅谈Linux系统中如何查看进程
  19. python爬虫beautifulsoup4系列2
  20. android KK版本号收到短信后,点亮屏的操作

热门文章

  1. angular 的navigate 各种使用情况
  2. jenkins git ftp 发布.net 项目
  3. 关于几天来研究使用css3动画的一点总结
  4. [转载] java多线程总结(一)
  5. Sublime Text 3利用Snippet创建Getter和Setter
  6. openstack常用命令-neutron篇
  7. 实际操作中遇到的问题--Django中查看已安装的包的相关命令
  8. 开发H5页面遇到的问题以及解决
  9. 【EMV L2】终端风险管理(Terminal Risk Management)
  10. 返回上一页面带数据 getCurrentPages 使用