摘要: # 前言 时间回到2011年,Hadoop作为新生事物,在阿里巴巴已经玩得风生水起,上千台规模的"云梯"是当时国内名声显赫的计算平台。 这一年,Hadoop的好兄弟HBase由毕玄大师带入淘宝,开启了它的阿里之旅。
前言
时间回到2011年,Hadoop作为新生事物,在阿里巴巴已经玩得风生水起,上千台规模的"云梯"是当时国内名声显赫的计算平台。
这一年,Hadoop的好兄弟HBase由毕玄大师带入淘宝,开启了它的阿里之旅。从最初的淘宝历史交易记录,到去年的支付宝消费记录存储在线历史存储统一;从蚂蚁安全风控的多年存储演进,到HBase、TT、Galaxy的大数据激情迭代;HBase在阿里经历过年轻的苦涩,释放过青春的活力,也付出过成长的代价。几代人的不懈努力下,五年陈的HBase开始表现出更成熟、更完善、更丰富的一面,成为公司内部被广泛使用的存储产品之一。
经过阿里集团内部的锤炼,集团将这个技术红利输送给广大阿里云客户。现已推出云数据库HBase产品,支持海量的PB级的大数据存储,适用于高吞吐的随机读写的场景。目前免费公测中,查看申请
本篇会系统性的阐述HBase的定位、建设思路,其中相关内容可能并未深入展开,后续会有专项介绍,请大家随时关注云栖社区相关文章。
概述
HBase是一个开源的非关系型分布式数据库(NoSQL),基于谷歌的BigTable建模,是一个高可靠性、高性能、高伸缩的分布式存储系统,使用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群。
HBase最初是以Hadoop子项目的形式进行开发建设,直到2010年5月才正式成为Apache的顶级项目独立发展。伴随着互联网时代数据的澎湃增长,HBase作为基础存储系统得到了快速发展与应用,大批知名商业公司(Facebook、Yahoo、阿里等)不自主地加入到了HBase生态建设队伍,成为Apache最活跃的社区之一。
HBase的能力特点,可以简单概括为下表,基于这些能力,其被广泛应用于海量结构化数据在线访问、大数据实时计算、大对象存储等领域
阿里从2011年初开始步入HBase的发展、建设之路,是国内最早应用、研究、发展、回馈的团队,也诞生了HBase社区在国内的第一位Committer,成为HBase在中国发展的积极布道者。过去的几年时间,阿里累积向社区回馈了上百个Patch, 在诸多核心模块的功能、稳定性、性能作出积极重大的贡献,拥有多位Committer,成为推动HBase的长远发展的重要力量之一。
阿里是一家综合生态型公司,内部庞大业务矩阵高速发展,在基础存储方面,需要更好的功能灵活性、基础设施适应性、服务稳定性、效率成本。
因此,阿里HBase团队发展维护了HBase的内部分支,其基于阿里巴巴/蚂蚁金服的环境和业务需求,对社区HBase进行深度定制与改进,从软件系统、解决方案、稳定护航、发展支撑等全方位提供一站式大数据基础存储服务。
HBase在阿里的使用
Ali-HBase作为阿里巴巴大厦的基础存储设施,全面服务于淘宝、天猫、蚂蚁金服、菜鸟、阿里云、高德、优酷等各个领域,满足业务对于大数据分布式存储的基本需求。
在刚刚过去的2016年双11,HBase承载访问量达到了上百GB/秒(写入)与上百GB/秒(读取),相当于全国人民一秒收发一条短信,在业务记录、安全风控、实时计算、日志监控、消息聊天等多个场景发挥重要价值。面对如此规模的业务体量,阿里巴巴团队对于如何基于HBase打造稳定、高效、易用的存储服务,形成了一套完善的产品体系与实践经验,其整体大图如下:
总体上,我们以定制的软件内核为中心,建设质量平台、运维平台、业务平台和数据流设施四大内容,以支持业务对于基础数据服务的全方位需求。
接下来,本文会围绕可用性、数据流、性能优化等方面介绍最近的一些具体工作,希望能够给相关领域的同学带来一点帮助。
高可用建设
服务持续可用是互联网系统的显著特征,但由于物理环境、软件Bug的不确定性,要做到系统的高可用往往不是一件容易的事,尤其是对于有状态的存储系统而言。今天,我们统一使用SLA(服务等级协议)去衡量一个分布式系统的可用性,比如SLA达到99.99%的系统,其全年的不可用时间小于52.6分钟;99.999%的系统,其全年的不可用时间小于5.25分钟,达到这个能力的系统一般可以称之为高可用。
面对断电、断网、硬件故障等物理机房的不可靠性,任何一个高可用系统必须通过双机房,甚至多机房部署的方式进行容灾。对于存储系统,这就要求数据能够在机房间冗余复制,并保证各个机房的数据对上层应用的一致性。所以,高可用建设是我们过去很长时间的重要工作。
集群异步复制
Apache HBase从0.92版本开始支持Replication功能,它会实时地、异步地将一个HBase集群中的增量数据复制(推送方式)到另一个HBase集群,当主集群故障不可用时,应用可以切换访问到备集群,从而实现数据与服务的机房容灾。关于HBase Replication的基本原理,读者可以从社区官方Book中获得详细内容,本文便不再阐述。
下面的篇幅,将主要介绍阿里在使用Replication过程中的经验与改进,期望能和在类似场景工作的同学有所共鸣。
复制效率
由于在线业务的可用性要求,阿里HBase很早便开始使用Replication功能去部署双机房容灾,迎之而来的第一个大问题是数据复制的效率,尤其异地远距离部署(比如上海与深圳跨城复制)时更加严重,表现为数据复制的吞吐小于客户端写入主集群的吞吐,数据不断积压,延迟逐渐增大,只能等待凌晨低峰期逐渐消化。我们对此进行深入分析,着重优化了以下几点,才得以保障跨城集群复制也能稳定保持在秒级内。
提升源端发送效率
HBase Replication的基本数据复制过程是源端串行读取HLog的内容,发送到目标端机器,由目标端解析HLog并写入数据写。我们发现,因为源端的串行读取、发送HLog,当集群写入吞吐大的时候,会存在严重的性能瓶颈,为此,我们重构了这一块逻辑,将HLog的读取与发送解耦,并且发送由单线程优化为多线程,使得整体的源端发送能力大幅提升。提升目标端Sink效率
在Replication的默认实现中,源端会按照HLog的原始写入顺序进行回放。为了提升目标端的写入效率,我们将所有待发送的HLog先进行排序,使得同表同Region的数据都能合并处理,同时将目标端的数据写入尽量并行化。热点辅助
尽管做了以上两点后,集群间的数据复制能力大大增强,但是个别服务器仍然会由于负载过大,而产生一定的复制延迟。从本质上来说,这是因为HBase的服务器分配了更多的资源服务于来自客户端的写入请求,当某个服务器成为集群中的写入热点并高负载工作时,这个节点的数据复制基本很难再消化庞大的写吞吐。这是一个曾困扰我们很久的问题,你可以用一些运维的方式去解决。比如开启更多的线程数,但这并不能总有效。因为服务于客户端的线程数,要远远大于Replication的线程数。再比如从热点服务器移走Region,降低吞吐与负载,但热点并不保证是恒定的,可能会跳跃在各个服务器,我们也开发了新的基于历史监控的负载均衡算法,以尽可能地让请求均衡。
很多时候,通过运维管理手段能够控制影响、化解问题,但当你需要维护上百个集群时,一点一滴的运维要求慢慢堆积成很高的壁垒。所以,我们尝试改进系统能力,用自动、一劳永逸地方式去解决热点下的数据复制积压问题。面对热点的基本思路是散列,在这个具体场景上,我们打破原先的自生产自推送的设计,利用整个集群的能力,使得热点服务器上积压的数据(HLog文件),能够由集群中的其他空闲服务器进行消化。
配置在线调整
配置的在线调整不仅能极大提升运维幸福感,而且对于系统改进可以产生更加敏捷的反馈。这并不新鲜,但这是一项十分重要的能力,我们在系统改进的道路上也对其特别重视。HBase的Replication功能会有很多参数,我们将其全部优化为可在线调整,给日常的服务支撑带来了很大的价值。
多链路
业务多地多单元部署是阿里技术架构的一项重要特征,这要求基础存储具备数据链路的灵活流动性。今天,阿里HBase会在多地部署多集群,集群间数据相互流动,以满足单元化业务的需求。
在支持数据多链路的生产应用上,我们总结了以下几个要点
表级别链路
当一个HBase集群启用多个数据链路后,我们期望自由设置表的数据可以被复制到其中的一个或多个链路,使得整个数据的流动更加灵活。为此,我们增加了一种特性,通过设置表的属性,以决定该表的数据流向哪些链路,使得整个数据流动图可以由业务架构师任意设计,十分灵活。此外,当需要在集群间热迁移数据时,它也能带来十分重大的作用。 整体效果如下,以表为单位数据可以任意流动:
链路可视
当数据可以在多个集群任意流动后,一个很迫切的需求是链路拓扑以及复制状况的可视。为此,我们强化了Replication的信息层,不仅源端保留它到多个目标的链路信息,而且每个目标端也会保留多个源端到它的链路信息,从而我们可以从任意一个集群绘制整个链路拓扑图。同时,我们极大丰富Replication的运行状况信息,并将之汇聚到HBase的Master节点,由其统一汇总展现,从中我们可以清晰得到数据是否积压、复制的性能瓶颈、节点间的均衡情况、具体的延迟时间等信息,其中复制的延迟时间是一个十分关键的信息。 基本信息如图
循环复制
在数据多链路下,会产生一些循环复制的场景。比如集群A->B->C->A,这是一个简单的链接式复制,当数据流过某个集群时,HBase Replication会在数据中添加该集群ID的信息,以防止同一条数据被多次流经同一个集群,基于这个设计,即使复制链路存在环,数据也不会产生无限循环流动。但是,仍然有一个效率问题不得不提,对于A<->B<->C<->A这样一个数据链路,我们发现客户端写入到A集群的数据,在B集群和C集群上会被复制写入两次,一次通过A->B链路写入,另一次通过A->C->B链路写入。所以,为了避免这种写入放大,需要在链路部署上防止产生这种环。在过去实践的一些场景,发现这种环状链路不得不存在,所以系统层面,我们也对Replication做了相关优化,以去除这种写入放大。链路隔离
当源集群配置了多个数据链路后,我们总是期望这些链路之间相互隔离,不会因为一个链路的积压影响其他链路。在大多数时候,这一切都如预期工作,但当集群故障时,糟糕的事情发生了,我们发现一个异常链路会阻塞全部链路的复制恢复,究其原因,是因为在数据复制的恢复期间,很多资源是所有链路共享的。所以,这些资源的链路解耦成为我们的工作,同时,也好好对数据复制的宕机恢复速度进行了优化。
数据的一致性
今天,大多数生产系统会使用异步方式去实现集群间的数据复制,因为这样效率更高、逻辑更清晰。这意味着,集群间数据是最终一致模型,当流量从主切换到备,从备上无法访问完整的数据,因为复制存在滞后,并且当主集群永久不可恢复,数据也会存在部分丢失。
为了满足业务场景的强一致需求,我们采用了两种方式。
第一种,异步复制下的强一致切换。虽然备集群的数据集滞后于主集群,但是在主集群网络健康的情况下,仍然可以保障切换前后数据的强一致。
其基本过程如下,首先让主集群禁止数据写入,然后等待主集群的数据全部复制备集群,切换流量到备集群。这里存在两个依赖,一个是集群的写入控制功能(支持禁止来自客户端的数据写入),另一个是复制延迟的确定性,虽然数据是异步复制的,但是我们将数据的复制时间点明确化,即该时间点之前写入的数据已经完全复制到了备集群。
第二种,数据复制使用同步的方式。即当数据写入返回客户端成功后,能保证数据在主备集群均已写入,从而即使主集群完全不可恢复,数据在备集群中也能保证完整。
为了满足类似场景的需求,阿里HBase研发了同步方式的集群间数据复制,具体内容可参考下一节。
冗余与成本
数据在集群间的冗余复制,给系统的可用性带来了数量级的提高,但同时也意味着更大的成本开销,在保证可用性下如何优化成本是一个需要重点思考的问题,阿里HBase在这方面投入了较大精力的尝试,具体内容将在接下来的"性能与成本"章节进行介绍。
集群同步复制
上文提到,HBase集群可以使用异步方式的数据复制来构建双机房容灾,当主集群故障不能提供服务时,就会切换请求到备集群,保障系统整体高可用。然而,异步复制模式下存在的问题是:在服务切换后,由于主备集群间的数据并非强一致,存在部分数据无法通过备集群获取或者访问到的内容过旧。也就是说,如果应用对于数据访问具有强一致要求,现有的异步复制设计,无法在主集群故障时,仍然保证系统的高可用。
为此,阿里HBase团队投入研发集群同步复制功能,使得主集群不可用时,备集群的数据能达到和主集群完全一致,业务可以无感知的切换到备集群。相比于异步复制,同步复制会带来的额外的开销,但整个写入吞吐/性能的影响,在我们的设计中,做到了尽量的相近。其整体功能点如下:
数据强一致性保证。数据写入主备集群,主集群不可用后,备集群可以恢复所有在主集群写入成功的数据
高性能。主备集群HLog写入采用异步并行的方式写入,对写入性能影响微弱
列族级粒度。列族级别的配置,支持同集群下同个表的不同列簇可以使用不同的复制方式,同步或异步。
同异步复制共存。任何情况下,同步复制表的任何操作不会影响异步表的读写。
灵活切换。备集群不可用,同步复制可以一键切换为异步复制,不阻塞主集群写入。
关于数据的强一致,我们进行了如下定义:
返回应用成功,则一定主备都写成功
返回应用错误,则未决(主备是否成功不能确定)
数据一旦读取成功,则主备永远均可读,不会出现主读成功切换至备后读不到或者备读得到主读不到的情况
任何情况下,保证主备集群的最终一致性
我们遵从简单、高效的原则去设计同步复制功能,简单意味着该功能与原核心逻辑保持最大程度的隔离,能够快速达到生产稳定性要求,并能很好地降级成异步复制;高效意味着主备必须并行写,这在错误处理上增加了不少的难度。整体实现方案如下:
客户端向主集群写入数据的时候,会并行写入两份Log,一份是本地HLog文件,另一份是备集群的HLog文件,我们称之为RemoteLog.两者皆成功,才返回客户端成功。
RemoteLog仅在故障切换后,用以回放数据。正常运行时,不做任何使用,备集群的数据仍然通过现有的异步复制链路写入。同时,可以通过停写RemoteLog,把同步复制降级成异步复制。
HBase数据的多版本特性,使得基于HLog的操作回放具有幕等性,所以,在故障切换后,RemoteLog中的数据回放会存在一定的重复,但不会影响数据正确性。
主备集群存在Active和Standby状态,只有Active状态的集群才能接受客户端的数据写入
在备集群切换为Active状态之前,会对RemoteLog全局上锁,从而防止客户端写入数据到主集群返回成功。这也意味着,主备集群在任何时刻,只有一个处于Active状态,不会有脑裂发生。
RemoteLog会定期由主集群清理,主集群服务器的一个HLog文件对应一个或多个RemoteLog,所以当主集群的HLog文件中的数据被完全复制到备集群后,相应的RemoteLog就可以被删除。
其基本结构如图
在这里,主备角色是不对等的,我们通过部署进行分配。其中,主->备使用同步复制模式,一旦流量切换到备后,备->主使用异步复制模式。
由于主备双Log的并发写入,使得同步复制的性能能够与异步复制接近,在实际使用中,我们观察到客户端写入响应时间增加小于10%。最后,我们列举一些应用同步复制容灾的场景,以供大家参考。
基于状态变更数据的场景。HBase中提供了CheckAndMutate接口,用以支持条件写入/更新/删除,其含义是当某一条件达成时,才执行该写操作。这意味着查询到的数据必须是强一致的,不然就会写入错误的数据。比如,对于一笔交易记录,其状态只能从“已付款”变更为“已发货”,而不能从其他状态变更为“已发货”,所以在数据更新时需要做状态的条件判断。
日志/消息的顺序订阅。对于日志/消息产品而言,订阅数据的完整性是其最核心的保证,也就是说通过HBase进行Scan的时候,必须保证能扫描到范围内的每一行数据。如果切换后,主备数据存在不一致,则会出现scan过程中跳过某些数据,造成订阅少数据。
流计算。由于流计算不停地基于中间结果和新的数据流进行迭代处理,作为存储中间结果的数据库,必须时刻具备数据的强一致,才能保证数据计算结果的正确性。
总结
集群间的数据复制是HBase用来构建机房容灾、提供高可用性的重要武器,阿里HBase通常使用异步复制方式部署,着重改进其在复制效率、多链路、一致性等方面的能力。同时,也研发了一种高效的同步复制方式,以满足数据强一致场景的容灾需求。
数据传输管道设施
数据流动的诉求
在大数据的发展背景下,没有一个系统可以处理所有的场景。因此,打通各个系统之间的数据通道,让数据在在线存储、实时分析、离线计算中高速流动,形成闭环,是打造大数据平台、挖掘数据价值的关键一环。
HExporter系统
HBase作为一款高吞吐的在线数据存储系统,我们希望其能高效、准确地吐出数据,以满足业务对数据计算分析的多元化需求,这是我们建设HExporter系统的出发点。
HBase业务的数据规模飞速增长,单个业务数据量达到10T,百T级别非常常见,且越来越多的业务要求同步数据到离线计算系统进行计算。同时大部分离线计算任务是周期型,比如按天为单位进行计算,因此数据要按时间分区进行同步并保证单调性,这需要一个高效的时间分区增量方式的数据导出方案来应对日益增长的需求。这是我们建设HExporter系统的场景。
基于以上出发点和场景,我们期望建设一个实时的、高效的HBase数据管道设施,使得写入到HBase系统的数据可以方便地传输复制到其他异构系统,
让数据因为流动、计算、加工而产生新的价值。为此,阿里HBase团队投入研发HExporter系统,其整体上具备以下能力:
实时性。数据可以秒级复制到其他异构系统
准确性。保证数据在HBase与其他系统间的最终一致性
高吞吐。支持调整缓冲等级和压缩等级,从而协调数据生产端和数据消费端的能力,达到最大的吞吐量。在实际应用中,HExporter可以有效使用95%的网络带宽并保持稳定运行。
容灾性。HBase主备容灾模式下,数据能够正常传输。
时间确定性。明确标注同步时刻,该时刻之前写入的数据都已经传输完成。基于此,保证计算系统对某个时间分区的完整数据进行计算。
可降级。支持按表取消数据传输。
监控告警。支持传输延迟的监控与告警。
HExporter系统的整体架构如下:
HExporter的数据是由HBase系统“推送”过来的,其利用了HBase系统本身的内部数据复制机制,模拟了备库的角色。HBase的RegionServer将自身的数据打包,随机发送到HExporter的采集节点。每一个数据包随机的选择采集节点,因此采集节点之间是完全对等的,可以动态的增加节点来提高HExporter的接收能力,它是水平可扩展的。为了支持主备模式下的HBase,HExporter需要同时采集主备集群,保证客户端写入HBase的数据不会因为主备间的网络中断而延迟采集。此时需要解决数据去重的问题:HExporter在收到数据包时,会检查数据包的标记,这个标记表示了数据是否来自于最源端(客户端写入的集群),如果不是则直接抛弃这个数据包。
大部分离线计算任务是周期型,比如按天为单位进行计算,数据要按时间分区进行同步,因此消费数据时必须能够获取时间信息。HExporter提供两个维度的时间供消费方使用:业务时间(数据的生成时间)和存储时间(数据写入HBase的时间)。
同步时间点指的是一个时刻,在该时刻之前写入HBase的数据都已经被HExporter采集。由于数据的推送是随机的,因此到达采集节点的数据在时间上是乱序的,同步时间点利用HBase在Zookeeper上记录的日志信息计算每个RegionServer的同步时间点,最后选择所有RegionServer同步时间点中的最小值记为集群的同步时间点。由于同步时间点的计算是保障数据有序的关键,必须能够容忍宕机等问题。在HExporter的设计中,每一个采集节点都可以计算同步时间点,所有节点竞争同一个锁(依赖Zookeeper实现),从而获得这一轮计算同步时间点的权利。只要有一个采集节点存活,同步时间点的计算就可以正常工作。
目前,HExporter作为阿里HBase系统的基础数据传输管道设施,每天有上百TB的数据被传输到离线计算平台、在线分析引擎、搜索引擎等系统,这些系统协力配合满足应用丰富多样的数据需求。
性能与成本
数据冗余的背后
前面章节提到,我们使用数据在集群间的冗余复制来提高系统可用性,对于主备容灾,这意味着我们需要花费一倍的额外成本来换取高可用,能不能降低开销成为高可用能力是否可以普及的重要门槛。
跨集群分区数据复制
HBase使用HDFS作为其文件存储系统,底层数据存储默认使用三副本冗余以保障数据的可靠性,这也意味着HBase内部的HLog、Flush、Compaction过程会产生三份数据流量和存储空间,包括网络和磁盘。如果HBase的底层副本数能够从3降低为2,很大程度上可以减少近1/3的成本,但是2个副本在实际运行中的数据丢失率仍然是不小的。所以,对于数据可靠性有要求的环境,三副本是最基本的要求。但是,当我们部署主备容灾后,全局拥有了六个副本,能否降低单个集群的副本为两个,全局从六个副本降低成四个副本,这成为资源优化的重要入口。
为了容忍单集群在两副本下的数据丢失,我们需要建立跨集群的分区数据复制机制,使得当某一个集群数据文件丢失时,可以快速地从另一个集群进行恢复。为了适用于更多的场景,比如集群迁移、一键建站,我们在设计上会更加通用,支持将某个表的指定范围数据高效、准确地复制到指定集群,整体功能可以概括如下:
简单。可以通过一个接口或者命令执行复制,并在系统UI上实时显示进度。
快速。整个复制任务会进行拆分,并由不同节点完成,大大提高速度。
容错和灾难恢复。复制过程中任何出错和宕机都能自我恢复。
在实现上,其类似于分布式任务调度,每一个提交的复制作业,会按照RowKey范围拆成多个子任务,并且子任务的起止范围是Region的子集,由Master派发给集群中的服务器,并保证失败后的重新派发。任务调度中的相关数据,统一存储在zookeeper上,从而保证宕机情况下作业的可恢复性。数据的具体复制根据情况会采用完全拷贝和部分复制两种方式,如果文件内容的RowKey范围是子任务的子集,则将其完全拷贝到指定集群;不然,则使用部分复制的方式,在拷贝期间过滤掉无效的数据。
详细系统架构如下:
图中的部分角色说明:
DataMigrationManager: DMM,运行于HBase Master,负责接收复制作业、切割作业为多个子任务、派发子任务、监听完成情况等。
DataMigrationWorker: DMW, 运行于HBase Regionserver,负责完成子任务的数据复制到指定集群。
Job: 一次数据复制作业,由用户提交,内容包括表名,Rowkey范围以及指定目标集群的地址信息。
Task: Job分割后的子任务,多个子任务的Rowkey范围拼接后组成完整的复制作业的Key范围。
在拥有跨集群分区数据复制能力后,双集群双副本的运行方式得以应用普及,这能有效降低容灾成本。
同时,我们的集群迁移、表迁移能力大大增强,在不限流下单节点可以达到70MB/秒,更重要的是这变成了一项能力、一个接口服务,而不是一堆运维操作,大大提升运维效率。
多集群多活服务
对于通常的双集群容灾部署,同一时间只有单个集群提供服务,使得另一个集群在大部分时间内处于资源闲置。为了改善这一情况,阿里HBase使用了以下几种方式:
业务对于数据无强一致要求,同个业务的部分客户端访问主集群,部分客户端访问备集群。这种方式对于业务应用部署存在一定的负担,使其数据库地址管理复杂化。
交叉部署访问,支持数据的强一致要求。一般我们会把类似场景的多个业务部署在同个集群中,通过交叉部署,在同一时间,使得一些业务访问主集群,另一些业务访问备集群,从而同时发挥两个集群的资源。
客户端支持同时访问双集群。我们通过改造HBase的客户端,使其支持同时访问双集群,这不仅可以提升集群的资源使用率,还大大降低了访问毛刺,因为任何超过一定时间的请求都会被重发到另一个集群。
我们经常使用上述一二的方式去优化双集群容灾下的资源使用,并且取得很不错的效果。
现阶段,由于业务场景对请求稳定性的更高要求,我们开发了“客户端支持同时访问双集群”的功能,以规避单节点抖动(如网络、磁盘、GC、锁竞争、热点)的影响,减少应用访问HBase的响应毛刺。从实际测试使用看,开启该功能后,整体毛刺比例下降达到一个数量级以上,有效去除HBase请求服务时间不稳定的影响。
更多性能工作
在过去的几年,阿里HBase投入了很大的精力去进行系统的性能优化,包括Region级二级索引、Bucket Cache、Small Scan、Reversed Scan等很多重要优化已经反馈给社区,并在开源伙伴的一起努力下,不断更新迭代,读者可以从社区了解具体的原理与实现。
刚刚过去的2016年双11,可以说是HBase的一场圣战,面对巨大峰值流量从容应战的背后是我们在性能优化上的很多新型武器。
异步API
一直以来,HBase只能使用同步API方式访问服务,使得吞吐型场景应用端大量线程阻塞在HBase接口,严重影响性能,而异步的思想并不陌生。
在去年双11后,阿里HBase开发实现了一套全新的异步API,使得客户端不需要阻塞等待到服务端返回结果,通过回调函数执行请求成功或失败后的业务逻辑,大大提升请求吞吐。我们将其应用于监控、安全、日志等场景,整体写入吞吐可以提升1至3倍。
前缀BloomFilter
HBase利用BloomFilter过滤不必要的文件来提高HBase数据读的性能,其效果只支持Get不支持Scan;在实际使用场景中,有很多业务Scan操作会扫描具有相同前缀的行,比如物流详情场景,其Rowkey结构是:物流单号+时间戳,一个物流商品会经历多个状态,每有一次状态转移需要写入一行数据,这些状态正常在10个左右,通过Scan的方式可以查询一个物流单号下的所有状态。针对这个场景我们设计了前缀BloomFilter,在业务Scan的起止范围存在公共前缀下,使得Scan操作也可以使用BloomFilter来过滤文件,大大提升了查询效率;菜鸟物流详情开启前缀BloomFilter后,查询性能提升一倍,做到大促不扩容,轻松hold住今年大促6.57亿包裹的物流详情查询。HLog压缩
HLog从0.92版本开始支持字典压缩,但其与Replication复制冲突,使得其一直无法真正地被使用,而大量在线业务使用宽表结构,几十个字段的场景比比皆是,HLog的压缩将有效提升写入能力。为此,阿里HBase重构了HLog的压缩机制,与HBase Replication功能完美兼容运行,在消费记录、数据总线、库存对账等多个业务线获得良好效果,提升写入20%。内置计算
数据的聚合、校正、清洗是数据库系统常见的计算场景,通过外部客户端进行数据的扫描、计算、更新是我们常用的传统方式。当面对TB级以上规模的时候,这种方式不仅效率低下,而且对本身的数据服务性能影响巨大。
阿里HBase一直在探索一种高效、环保的能力去解决我们对于数据基本计算的需求,几经业务理解与抽象,最终找到一种基于coprocessor的数据库内置计算方案。它不仅可以提供基本的Count、Avg、Sum、PV、UV等分析聚合能力,也可以提供常见的格式转换、内容校正、字段清洗等数据管理能力。
其基本原理是,我们在HBase的Flush、Compaction、查询返回等路径添加coprocessor的hook,并开发很多通用的coprocessor插件,使得HBase服务端能够在Compaction、Flush期间就完成数据计算工作,这不仅促使计算结果快速输出,也大大减少数据存储IO,大大提升整体性能。
2016年,凭借这个能力,多个几百TB规模业务在一周以内完成字段清洗、格式转换,并且全程对业务在线访问无影响。凭借这个能力,很多秒级生产的指标数据,应用可以零成本聚合成小时级、日级等粗粒度指标,并对HBase系统减少50%以上的访问压力。
未来发展
随着2016天猫双十一的GMV定格在1207亿,HBase的大促目标圆满完成,然而完美的结果只是开始,阿里HBase团队追求卓越的心永远不会变,推陈出新也永远不会停。在未来的日子里,我们将会重点攻破以下难题。
GC的挑战
HBase作为JAVA性存储系统,大容量的内存堆使得YoungGC、FullGC的停顿成为我们一直以来挥之不去的痛苦。探究GC的原理机制,我们明确HBase内部的写缓冲Memstore和读缓存BlockCache是造成GC停顿的最大源头,正在尝试用全新研发的完全自管理内存的Map以替换JDK自带的Map,从而消除GC的影响。SQL
我们正在尝试提供SQL方式访问HBase。它会增加数据类型,降低用户的开发理解门槛,促进异构系统之间的数据流动效率;它会增加全局二级索引,使得多条件查询更加高效;它会简化查询表达,使得性能优化更加普及;它会增加通用的热点解决方案,帮助用户免去复杂的散列逻辑。容器部署
我们正在尝试将HBase部署运行于Docker之上,使得整体运维更加敏捷,集群伸缩更加自如,资源使用更加充分。
本文为云栖社区原创内容,未经允许不得转载。
评论
查看更多