原文:http://yanbohappy.sinaapp.com/?p=434
2013年马上就要过去了,总结下这一年HBase在这么一年中发生的主要变化。影响最大的事件就是HBase 0.96的发布,代码结构已经按照模块化release了,而且提供了许多大家迫切需求的特点。这些特点大多在Yahoo/Facebook/淘宝/小米等公司内部的集群中跑了挺长时间了,可以算是比较稳定可用了。
1,Compaction优化
HBase的Compaction是长期以来广受诟病的一个feature,很多人吐槽HBase也是因为这个特征。不过我们不能因为HBase有这样一个缺点就把它一棒子打死,更多的还是希望能够驯服它,能够使得它适应自己的应用场景。根据业务负载类型调整compaction的类型和参数,一般在业务高峰时候禁掉Major Compaction。在0.96中HBase社区为了提供更多的compaction的策略适用于不同的应用场景,采用了插件式的架构。同时改进了HBase在RegionServer端的存储管理,原来是直接Region->Store->StoreFile,现在为了支持更加灵活多样的管理StoreFile和compact的策略,RS端采用了StoreEngine的结构。一个StoreEngine涉及到StoreFlusher, CompactionPolicy, Compactor, StoreFileManager。不指定的话默认是DefaultStoreEngine,四个组件分别是DefaultStoreFlusher, ExploringCompactionPolicy, DefaultCompactor, DefaultStoreFileManager。可以看出在0.96版之后,默认的Compaction算法从RatioBasedCompactionPolicy改为了ExploringCompactionPolicy。为什么要这么改,首先从compaction的优化目标来看:compaction is about trading some disk IO now for fewer seeks later,也就是compaction的优化目标是执行Compaction操作能合并越多的文件越好,如果合并同样多的文件产生的IO越小越好,这样select出来的列表才是最优的。
主要不同在于:
- RatioBasedCompactionPolicy是简单的从头到尾遍历StoreFile列表,遇到一个符合Ratio条件的序列就选定执行compaction。对于典型的不断flush memstore形成 StoreFile的场景是合适的,但是对于bulk-loaded是不合适的,会陷入局部最优。
- 而ExploringCompactionPolicy则是从头到尾遍历的同时记录下当前最优,然后从中选择一个全局最优列表。
关于这两个算法的逻辑可以在代码中参考对应的applyCompactionPolicy()函数。其他CompactionPolicy的研究和开发也非常活跃,例如Tier-based compaction (HBASE-6371,来自Facebook) 和stripe compaction(HBASE-7667)
吐槽:HBase compaction为什么会问题这么多,我感觉缺少了一个整体的IO负载的反馈和调度机制。因为compaction是从HDFS读数据,然后再写到HDFS中,和其他HDFS上的负载一样在抢占IO资源。如果能有个IO资源管理和调度的机制,在HDFS负载轻的时候执行compaction,在负载重的时候不要执行。而且这个问题在Hadoop/HDFS里同样存在,Hadoop的资源管理目前只针对CPU/Memory的资源管理,没有对IO的资源管理,会导致有些Job受自己程序bug的影响可能会写大量的数据到HDFS,会严重影响其他正常Job的读写性能。
http://blog.cloudera.com/blog/2013/12/what-are-hbase-compactions/
http://www.slideshare.net/cloudera/hbasecon-2013-compaction-improvements-in-apache-hbase
2,Mean Time To Recovery/MTTR优化
目前HBase对外提供服务,Region Server是单点。如果某台RS挂掉,那么直到该RS上的所有Region被重新分配到其他RS上之前,这些Region是的数据是无法访问的。对这个过程的改进主要包括:
- HBASE-5844 和 HBASE-5926:删除zookeeper上Region Server/Master对应的znode,这样就省的等到znode 30s超时才发现对应的RS/Master挂了。
- HBASE-7006: Distributed Log Replay,就是直接从HDFS上读取宕机的WAL日志,直接向新分配的RS进行Log Replay,而不是创建临时文件recovered.edits然后再进行Log Replay
- HBASE-7213/8631: HBase的META表中所有的Region所在的Region Server将会有两个WAL,一个是普通的,一个专门给META表对应的Region用。这样在进行recovery的时候可以先恢复META表。
3,Bucket Cache (L2 cache on HBase)
HBase上Regionserver的内存分为两个部分,一部分作为Memstore,主要用来写;另外一部分作为BlockCache,主要用于读。Block的cache命中率对HBase的读性能影响十分大。目前默认的是LruBlockCache,直接使用JVM的HashMap来管理BlockCache,会有Heap碎片和Full GC的问题。
HBASE-7404引入Bucket Cache的概念可以放在内存中,也可以放在像SSD这样的适合高速随机读的外存储设备上,这样使得缓存的空间可以非常大,可以显著提高HBase读性能。Bucket Cache的本质是让HBase自己来管理内存资源而不是让Java的GC来管理,这个特点也是HBase自从诞生以来一直在激烈讨论的问题。
4,Java GC改进
MemStore-Local Allocation Buffers通过预先分配内存块的方式解决了因为内存碎片造成的Full GC问题,但是对于频繁更新操作的时候,MemStore被flush到文件系统时没有reference的chunk还是会触发很多的Young GC。所以HBase-8163提出了MemStoreChunkPool的概念,也就是由HBase来管理一个ChunkPool用来存放chunk,不再依赖JVM的GC。这个ticket的本质也是由HBase进程来管理内存分配和重分配,不再依赖于Java GC。
5,HBase的企业级数据库特性(Secondary Index, Join和Transaction)
谈到HBase的企业级数据库特性,首先想到的就是Secondary Index, Join, Transaction。不过目前这些功能的实现都是通过外围项目的形式提供的。
华为的hindex (https://github.com/Huawei-Hadoop/hindex)是目前看到的最好的Secondary Index的实现方式。主要思想是建立Index Table,而且这个Index Table的Region分布跟主表是一致的,也就是说主表中某一Region对应的Index Table对应的Region是在同一个RS上的。而且这个索引表是禁止自动或者手动出发split的,只有主表发生了split才会触发索引表的split。
这个是怎么做到的呢?本质上Index Table也是一个HBase的表,那么也只有一个RowKey是可以索引的。这个索引表的RowKey设计就比较重要了,索引表的RowKey=主表Region开始的RowKey+索引名(因为一个主表可能有多个索引,都放在同一个索引表中)+需要索引的列值+主表RowKey。这样的索引表的RowKey设计就可以保证索引表和主表对应的Region是在同一台RS上,可以省查询过程中的RPC。每次Insert数据的时候,通过Coprocessor顺便插入到索引表中。每次按照二级索引列Scan数据的时候,先通过Coprocessor从索引表中获取对应的主表的RowKey然后就行Scan。在性能上看,查询的性能获得了极大提升,插入性能下降了10%左右。
Phoenix也通过另外建一张表的方式实现二级索引。https://github.com/forcedotcom/phoenix/wiki/Secondary-Indexing
Phoenix也实现了一大一小两个表的Join操作。还是老办法把小表broadcast到所有的RS,然后通过coprocessor来做hash join,最后汇总。感觉有点画蛇添足,毕竟HBase设计的初衷就是用大表数据冗余来尽量避免Join操作的。现在又来支持Join,不知道Salesfore的什么业务需求这个场景。
关于Transaction的支持,目前最受关注的还就是Yahoo的Omid (https://github.com/yahoo/omid/)。不过貌似大家对这个feature的热情还不是特别高。
http://sigops.org/sosp/sosp11/posters/summaries/sosp11-final12.pdf
6,PrefixTreeCompression
由于HBase的KeyValue存储是按照Row/Family/Qualifier/TimeStamp/Value的形式存储的,Row/Family/Qualifier这些相当于前缀,如果每一行都按照原始数据进行存储会导致占据存储空间比较大。HBase 0.94版本就已经引入了DataBlock Encode的概念(HBASE-4218),将重复的Row/Family/Qualifier按照顺序进行压缩存储,提高内存利用率,支持四种压缩方式FAST_DIFF\PREFIX\PREFIX_TRIE\DIFF。但是这个feature也仅仅是通过delta encoding/compression降低了内存占用率,对数据查询效率没有提升,甚至会带来压缩/解压缩对CPU资源占用的情况。
HBASE-4676:PrefixTreeCompression是把重复的Row/Family/Qualifier按照Prefix Tree的形式进行压缩存储的,可以在解析时生成前缀树,并且树节点的儿子是排序的,所以从DataBlock中查询数据的效率可以超过二分查找。
http://zjushch.iteye.com/blog/1843793
7,其他变化
- HBASE-5305:为了更好的跨版本的兼容性,引进了Protocol Buffer作为序列化/反序列化引擎使用到RPC中(此前Hadoop的RPC也全部用PB重写了)。因为随着HBase Server的不断升级,有些Client的版本可能还比较旧,所以需要RPC在新旧版本之间兼容。
- HBASE-6055 HBASE-7290:HBase Table Snapshot。创建snaphost对HBase集群没有性能影响,只是生成了snaphost对应的metadata而不会去拷贝数据。用户可以通过创建snaphost实现backup和disaster recovery,例如用户在创建一个snaphost之后可能会误操作导致一些表出现了问题,这样我们可以选择回滚到创建snaphost的那个阶段而不会导致数据全都不可用。也可以定期创建snapshot然后拷贝到其他集群用于定时的offline processing。
- HBASE-8015: 在0.96中,ROOT表已经改名为hbase:namespace,META则是hbase:meta。而且hbase:namespace是存在zookeeper上的。这个namespace类似于RDBMS里的database的概念,可以更好的做权限管理和安全控制。HBase中table的META信息也是作为一种Region存放在Region Server上的,那么META表的Region和其他普通Region就会产生明显的资源竞争。为了改善META Region的性能,360的HBase中提出了专属MetaServer,在这个Region Server上只存放META Region
- HBASE-5229:同一个Region内的跨行事务。一次操作中涉及到同一个Region中的所有写操作在获取到的相关Row的所有行锁(按照RowKey的顺序依次取行锁,防止死锁)之后事务执行。
- HBASE-4811:Reverse Scan。过去被问到说如何反向查找HBase中的数据,常常被答道再建一张反向存储的表,而且LevelDB和Cassandra都支持反向扫描。HBase反向扫描比正向扫描性能下降30%,这个和LevelDB是差不多的。
- Hoya — HBase on YARN。可以在一个YARN集群上部署多个不同版本、不同配置的HBase instance,可以参考 https://github.com/hortonworks/hoya
展望2014年,HBase即将release 1.0版本,更好的支持multi-tenancy, 支持Cell级别的ACL控制。
8,总结
- Cloudera/Hortonworks/Yahoo/Facebook的人从系统和性能等多方面关注
- Salesfore/huawei的人貌似更关注企业级特性,毕竟他们面对的客户都是电信、金融、证券等高帅富行业
- 来自国内的阿里巴巴/小米/360等公司更加关注系统性能、稳定性和运维相关的话题。国内互联网行业用HBase更加关注的是如何解决业务问题。
- 越来越多的公司把它们的HBase集群构建在云上,例如Pinterest所有的HBase集群都是在AWS上,国外的start up环境太好了,有了AWS自己根本不用花费太多的资源在基础设施上。
- 传统的HBase应用是online storage,实时数据读取服务。例如支付宝用HBase存放用户的历史交易信息服务用户查询,中国联通也使用HBase存储用户的上网历史记录信息用于用户的实时查询需求。现在HBase也向实时数据挖掘的应用场景中发展,例如wibidata公司开源的kiji (http://www.kiji.org/)能够在HBase上轻松构建实时推荐引擎、实时用户分层和实时欺诈监控。
相关推荐
《HBase in Action》是一本专门介绍HBase的入门书籍,旨在帮助读者深入理解并掌握分布式列式数据库HBase的核心概念和技术。HBase是构建在Hadoop生态系统之上,专为处理大规模数据而设计的一种非关系型数据库(NoSQL...
标题和描述中提到的《HBase实战》(HBase in Action)是一本专著,专注于HBase的实用开发案例和原理讲解。HBase是Apache软件基金会旗下的一个开源、非关系型、分布式数据库系统,它是基于Google的Bigtable论文构建的...
HBase实战(HBase In Action) 中文版 PDF
HBase In-Memory Compaction HBase In-Memory Compaction是HBase存储系统中的一种高性能的存储机制,它基于Log-Structured-Merge(LSM)树设计,通过将数据存储在内存中,减少磁盘I/O操作,提高写入吞吐量和读取...
《HBase in Action》同样是一本关于HBase的实战书籍,作者通过实际应用案例,展示了如何在各种场景下有效地使用HBase。这本书不仅涵盖了HBase的基础知识,还深入讨论了高级特性,如复杂查询、实时数据处理和数据备份...
这本书出版于2013年,而此时使用的HBase版本是0.92,这个版本在当时是较新且被广泛使用的。 2. 关键标签 文件中提供的标签“HBase database hadoop”指向了HBase数据库和Hadoop生态系统之间的紧密关系。HBase是建立...
《HBase in Action》是一本深入探讨HBase的实战型书籍,旨在帮助读者理解并掌握分布式大数据存储系统HBase的核心概念和技术。HBase是构建在Hadoop之上的NoSQL数据库,特别适合处理大规模、实时的数据存储和检索。...
HBase在不同版本(1.x, 2.x, 3.0)中针对不同类型的硬件(以IO为例,HDD/SATA-SSD/PCIe-SSD/Cloud)和场景(single/batch, get/scan)做了(即将做)各种不同的优化,这些优化都有哪些?如何针对自己的生产业务和...
《HBase in Action》是一本由Nick Dimiduk和Amandeep Khurana撰写的关于HBase实践的书籍,该书旨在帮助读者深入理解HBase的工作原理及其实战应用。 **章节概述**: - **第一部分:HBase基础** - **第1章:介绍...
总的来说,"HBase in action"是一本系统介绍HBase的实用指南,适合那些希望了解如何使用HBase进行大规模数据存储和处理的开发者和数据工程师。该书不仅仅是对HBase概念和特性的介绍,还包含了大量的实践案例和操作...
With the increasing use of NoSQL in general and HBase in particular, knowing how to build practical applications depends on the application of design patterns. These patterns, distilled from extensive...
Herein you will find either the definitive documentation on an HBase topic as of its standing when the referenced HBase version shipped, or it will point to the location in Javadoc or JIRA where the ...
HBase in action 的中文版,hadoop数据储存组件