解密 云HBase 冷热分离技术原理

前言

HBase是当下流行的一款海量数据存储的分布式数据库。往往海量数据存储会涉及到一个成本问题,如何降低成本。常见的方案就是通过冷热分离来治理数据。冷数据可以用更高的压缩比算法(ZSTD),更低副本数算法(Erasure Coding),更便宜存储设备(HDD,高密集型存储机型)。

HBase冷热分离常见解决方案

1.主备集群

备(冷)集群用更廉价的硬件,主集群设置TTL,这样当数据热度退去,冷数据自然只在冷集群有。


优点:方案简单,现成内核版本都能搞
缺点:维护开销大,冷集群CPU存在浪费

1.x版本的HBase在不改内核情况下,基本只能有这种方案。

2.HDFS Archival Storage + HBase CF-level Storage Policy

需要在2.x之后的版本才能使用。结合HDFS分层存储能力 + 在Table层面指定数据存储策略,实现同集群下,不同表数据的冷热分离。


优点:同一集群冷热分离,维护开销少,更灵活的配置不同业务表的策略
缺点:磁盘配比是个很大的问题,不同业务冷热配比是不一样的,比较难整合在一起,一旦业务变动,集群硬件配置是没法跟着变的。

云HBase冷热分离解决方案

上述2套方案都不是最好的方案,对于云上来说。第一套方案就不说了,客户搞2个集群,对于数据量不大的客户其实根本降不了成本。第二套方案,云上客户千千万,业务各有各样,磁盘配置是很难定制到合适的状态。

云上要做 cloud native 的方案,必须满足同集群下,极致的弹性伸缩,才能真正意义上做到产品化。云上低成本,弹性存储,只有OSS了。所以很自然的想到如下架构:

实现这样的架构,最直接的想法是直接改HBase内核:1)增加冷表数据标记 2)根据标记增加写OSS的IO路径。

这样做的缺陷非常明显,你的外部系统(如:备份恢复,数据导入导出)很难兼容这些改动,他们需要感知哪些是冷文件得去OSS哪个位置读,哪些是热文件得去部署在云盘上的HDFS上读。这些本质上都是一些重复的工作,所以从架构设计角度来看必须抽象出一层。这一层能读写HDFS文件,读写OSS文件,感知冷热文件。这一层也就是我最后设计出的ApsaraDB FileSystem,实现了Hadoop FileSystem API。对于HBase,备份恢复,数据导入导出等系统只要替换原先FileSystem的实现即可获得冷热分离的功能。

下面将详细阐述,这套FileSystem设计的细节与难点。

ApsaraDB FileSystem 设计

核心难点A

1.OSS并非文件系统

OSS并不是一个真正意义上的文件系统,它仅仅是两级映射 bucket/object,所以它是对象存储。你在OSS上看到类似这样一个文件:
/root/user/gzh/file。你会以为有3层目录+1个文件。实际上只有一个对象,这个对象的key包含了/字符罢了。

这么带来的一个问题是,你要想在其上模拟出文件系统,你必须先能创建目录。很自然想到的是用/结尾的特殊对象代表目录对象。Hadoop社区开源的OssFileSystem就是这么搞的。有了这个方法,就能判断到底存不存在某个目录,能不能创建文件,不然会凭空创建出一个文件,而这个文件没有父目录。

当然你这么做依然会有问题。除了开销比较大(创建深层目录多次HTTP请求OSS),最严重的是正确性的问题。试想一下下面这个场景:
把目录/root/user/source rename 成 /root/user/target。这个过程除了该目录,它底下的子目录,子目录里的子文件都会跟着变。类似这样:/root/user/source/file => /root/user/target/file。这很好理解,文件系统就是一颗树,你rename目录,实际是把某颗子树移动到另一个节点下。这个在NameNode里的实现也很简单,改变下树结构即可。

但是如果是在OSS上,你要做rename,那你不得不递归遍历/root/user/source把其下所有目录对象,文件对象都rename。因为你没法通过移动子树这样一个简单操作一步到位。这里带来的问题就是,假设你递归遍历到一半,挂了。那么就可能会出现一半目录或文件到了目标位置,一半没过去。这样rename这个操作就不是原子的了,本来你要么rename成功,整个目录下的内容到新的地方,要么没成功就在原地。所以正确性会存在问题,像HBase这样依赖rename操作将临时数据目录移动到正式目录来做数据commit,就会面临风险。

2.OSS rename实则是数据拷贝

前面我们提到了rename,在正常文件系统中应该是一个轻量级的,数据结构修改操作。但是OSS并没有rename这个操作实际上,rename得通过 CopyObject + DeleteObject 两个操作完成。首先是copy成目标名字,然后delete掉原先的Object。这里有2个明显的问题,一个是copy是深度拷贝开销很大,直接会影响HBase的性能。另一个是rename拆分成2个操作,这2个操作是没法在一个事物里的,也就是说:可能存在copy成功,没delete掉的情况,此时你需要回滚,你需要delete掉copy出来的对象,但是delete依然可能不成功。所以rename操作本身实现上,正确性就难以保证了。

解决核心难点A

解决上面2个问题,需要自己做元数据管理,即相当于自己维护一个文件系统树,OSS上只放数据文件。而因为我们环境中仍然有HDFS存储在(为了放热数据),所以直接复用NameNode代码,让NodeNode帮助管理元数据。所以整体架构就出来了:

 

 

ApsaraDB FileSystem(以下简称ADB FS)将云端存储分为:主存(PrimaryStorageFileSystem)和 冷存(ColdStorageFileSystem)。由ApsaraDistributedFileSystem类(以下简称ADFS)负责管理这两类存储文件系统,并且由ADFS负责感知冷热文件。

ApsaraDistributedFileSystem: 总入口,负责管理冷存和主存,数据该从哪里读,该写入哪里(ADFS)。
主存:PrimaryStorageFileSystem 默认实现是 DistributedFileSystem(HDFS)
冷存:ColdStorageFileSystem 默认实现是 HBaseOssFileSystem(HOFS) ,基于OSS实现的Hadoop API文件系统,可以模拟目录对象单独使用,也可以只作为冷存读写数据,相比社区版本有针对性优化,后面会讲。

具体,NameNode如何帮助管理冷存上的元数据,很简单。ADFS在主存上创建同名索引文件,文件内容是索引指向冷存中对应的文件。实际数据在冷存中,所以冷存中的文件有没有目录结构无所谓,只有一级文件就行。我们再看下一rename操作过程,就明白了:

 

 

rename目录的场景也同理,直接在NameNode中rename就行。对于热文件,相当于全部代理HDFS操作即可,冷文件要在HDFS上创建索引文件,然后写数据文件到OSS,然后关联起来。

核心难点B

引入元数据管理解决方案,又会遇到新的问题:是索引文件和冷存中数据文件一致性问题。
我们可能会遇到如下场景:

  • 主存索引文件存在,冷存数据文件不存在
  • 冷存数据文件存在,主存索引文件不存住
  • 主存索引文件信息不完整,无法定位冷存数据文件

先排除BUG或者人为删除数据文件因素,上诉3种情况都会由于程序crash产生。也就是说我们要想把法,把生成索引文件,写入并生成冷数据文件,关联,这3个操作放在一个事物里。这样才能具备原子性,才能保证要么创建冷文件成功,那么索引信息是完整的,也指向一个存在的数据文件。要么创建冷文件失败(包括中途程序crash),永远也见不到这个冷文件。

解决核心难点B

核心思想是利用主存的rename操作,因为主存的rename是具备原子性的。我们先在主存的临时目录中生产索引文件,此时索引文件内容已经指向冷存中的一个路径(但是实际上这个路径的数据文件还没开始写入)。在冷存完成写入,正确close后,那么此时我们已经有完整且正确的索引文件&数据文件。然后通过rename一把将索引文件改到用户实际需要写入到目标路径,即可。

如果中途进程crash,索引文件要么已经rename成功,要么索引文件还在临时目录。在临时目录我们认为写入没有完成,是失败的。然后我们通过清理线程,定期清理掉N天以前临时目录的文件即可。所以一旦rename成功,那目标路径上的索引文件一定是完整的,一定会指向一个写好的数据文件。

为什么我们需要先写好路径信息在索引文件里?因为如果先写数据文件,在这个过程中crash了,那我们是没有索引信息指向这个数据文件的,从而造成类似“内存泄漏”的问题。

 

冷热文件标记

对于主存,需要实现给文件冷热标记的功能,通过标记判断要打开怎样的数据读写流。这点NameNode可以通过给文件设置StoragePolicy实现。这个过程就很简单了,不详细赘述,下面说HBaseOssFileSystem写入优化设计。

HBaseOssFileSystem 写入优化

在说HOFS写设计之前,我们先要理解Hadoop社区版本的OssFileSystem设计(这也是社区用户能直接使用的版本)。

社区版本写入设计

Write -> OutputStream -> disk buffer(128M) -> FileInputStream -> OSS

这个过程就是先写入磁盘,磁盘满128M后,将这128M的block包装成FileInputStream再提交给OSS。这个设计主要是考虑了OSS请求成本,OSS每次请求都是要收费的,但是内网流量不计费。如果你1KB写一次,费用就很高了,所以必须大块写。而且OSS大文件写入,设计最多让你提交10000个block(OSS中叫MultipartUpload),如果block太小,那么你能支持的最大文件大小也是受限

所以要攒大buffer,另外一个因素是Hadoop FS API提供的是OutputStream让你不断write。OSS提供的是InputStream,让你提供你要写入内容,它自己不断读取。这样你必然要通过一个buffer去转换。

这里会有比较大的一个问题,就是性能慢。写入磁盘,再读取磁盘,多了这么两轮会比较慢,虽然有PageCache存在,读取过程不一定有IO。那你肯定想,用内存当buffer不就好了。内存当buffer的问题就是前面说的,有费用,所以buffer不能太小。所以你每个文件要开128M内存,是不可能的。更何况当你提交给OSS的时候,你要保证能继续写入新数据,你得有2块128M内存滚动,这个开销几乎不能接受。

HBaseOssFileSystem 写入设计

我们既要解决费用问题,也要解决性能问题,同时要保证开销很低,看似不可能,那么怎么做呢?

这里要利用的就是这个InputStream,OSS让你提供InputStream,并从中读取你要写入的内容。那么我们可以设计一个流式写入,当我传入这个InputStream给OSS的时候,流中并不一定得有数据。此时OSS调read读取数据会block在read调用上。等用户真的写入数据,InputStream中才会有数据,这时候OSS就能顺利读到数据。当OSS读了超过128M数据时候,InputStream会自动截断,返回EOF,这样OSS会以为流已经结束了,那么这块数据就算提交完成。

所以我们本质只要开发这么一个特殊的InputStream即可。用户向Hadoop API提供的OutputStream中写入数据,数据每填满一个page(2M)就发给InputStream让其可读取。OuputStream相当于生产者,InputStream相当于消费者。这里的内存开销会非常低,因为生产者速度和消费者速度相近时,也就2个page的开销。最后将这整套实现封装成OSSOutputStream类,当用户要写入冷文件时,实际提供的是OSSOutputStream,这里面就包含了这个特殊InputStream的控制过程。

当然实际生产中,我们会对page进行控制,每个文件设置最多4个page。并且这4个page循环利用,减少对GC对影响。所以最后我们得到下面一个环形缓冲的写入模式:

性能对比1:社区版本 vs 云HBase版

因为不用写磁盘,所以写入吞吐可以比社区的高很多,下图为HBase1.0上测试结果。在一些大KV,写入压力更大的场景,实测可以接近1倍。这个比较是通过替换ADFS冷存的实现(用社区版本和云HBase版本),都避免了rename深拷贝问题。如果直接裸用社区版本而不用ADFS那性能会差数倍。

性能对比2:热表 vs 冷表

热表数据在云盘,冷表数据在OSS。

得益于上述优化,加上冷表WAL也是放HDFS的,并且OSS相对HBase来说是大集群(吞吐上限高),冷表的HDFS只用抗WAL写入压力。所以冷表吞吐反而会比热表略高一点点。

不管怎么说,冷表的写入性能和热表相当了,这样的表现已经相当不错了。基本是不会影响用户灌数据,否则使用冷存后,吞吐掉很多,那意味着要更多机器,那这功能就没什么意义了。

总结

这大约是1年多前落地的项目,已经稳定运行很久。之前也有出去分享过,但是没有今天这么细致。现在写出来主要是自我总结下。当设计一个服务去解决某个问题的时候,上下游的关系,可能存在的问题得考虑清楚。在做这个项目最初的时候,想把HBase直接架设在社区版本OssFileSytem上,发现性能不行外,正确性也存在很大风险。不断思考,考虑各种情况后才有了今天这套方案。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/517261.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

再见,工资!2020年6月程序员工资统计,平均14404元,网友:又跌了!

见了鬼!工资竟然又跌了2020 年 6 月全国招收程序员 313739 人。2020 年 6 月全国程序员平均工资 14404 元,工资中位数 12500 元,其中 95% 的人的工资介于 5250 元到 35000 元。怪不得小陈发现最近猎头的“骚扰”电话越来越少了,这…

mysql创建function 报错误1418 - This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in

解决方法: 执行这条sql就可以了: set global log_bin_trust_function_creators1;运行结果: 函数创建成功了

一个实时精准触达系统的自我修养

问题定义 在互联网行业,唯一不变的就是一直在变化。作为技术同学,我们经常会碰到以下几种需求: 当用户收藏的商品降价后及时通知用户,促进双方交易达成;新用户或90天内未成交的用户浏览多个商品后引导用户主动和卖家聊…

vue-datepicker的使用

写这个文章主要是记录下用法&#xff0c;官网已经说的很详细了 npm install vue-datepicker --savehtml代码 <myDatepicker :date"startTime" :option"multiOption" :limit"limit"></myDatepicker> <myDatepicker :date"e…

数据库怎么选择?终于有人讲明白了

作者 | Alex Petrov所有数据库管理系统的主要工作都是可靠地存储数据并使其对用户可用。我们使用数据库作为数据的主要来源&#xff0c;帮助我们在应用程序的不同部分之间共享数据。我们使用数据库&#xff0c;而不是在每次创建新应用程序时寻找存储和检索信息的方法&#xff0…

医疗数据典型特征及架构发展方向研究

前言 医疗健康产业目前呈高速发展状态&#xff0c;处在互联网对医疗行业赋能的关键阶段&#xff0c;由于医疗行业数据的隐私性较强&#xff0c;通过传统方式很难获取公开的医疗健康数据进行研究&#xff0c;根据阿里云天池比赛赛题设置研究及提供的脱敏数据集着手进行分析是比…

分布式事务 GTS 的价值和原理浅析

GTS 今年双 11 的成绩 今年 2684 亿的背后&#xff0c;有一个默默支撑&#xff0c;低调到几乎被遗忘的中间件云产品——GTS&#xff08;全局事务服务&#xff0c;Global Transaction Service&#xff09;&#xff0c;稳稳地通过了自 2014 年诞生以来的第 5 次“大考”。 2019 …

kafka java.net.UnknownHostException: node4 Error connecting to node node4:9092

解决&#xff1a;修改kafka的server.properties文件 vim /kafka安装路径/config/server.properties 去除下面这行配置的注释&#xff0c;并设置对应的ip地址 #advertised.listenersPLAINTEXT://your.host.name:9092 advertised.listenersPLAINTEXT://192.168.92.104:9092 重启…

看全新升级的KubeSphere 3.0 如何助力企业在容器混合云时代乘风破浪?

数据时代&#xff0c;层出不穷的创新型业务对企业IT提出了更高的要求&#xff0c;业务、技术和管理方面的挑战也逐渐显现。对此&#xff0c;越来越多的企业希望能够快速、简单地创建企业应用&#xff0c;敏捷地满足业务创新的需求&#xff0c;同时还能维持极高的企业级服务水平…

5G的7大用途,你知道几个?

阿里妹导读&#xff1a;5G时代悄悄来临&#xff0c;甚至成为街头巷尾都在讨论的话题。相信你一定有过一些疑问&#xff1a;什么是5G&#xff1f;仅仅只是网速更快吗&#xff1f;5G如何做到毫秒级的延迟&#xff1f;网络切片是什么&#xff1f;5G的标准之争是怎么回事&#xff0…

ALive:淘宝双11直播,技术同学却可以“偷懒”?

“疯狂的”淘宝直播间 今年直播又火了&#xff01; 2019年双11淘宝直播带来近 200亿 成交&#xff0c;以天猫双11交易总额2684亿计算&#xff0c;直播已经占总成交额的近 7.45%&#xff01; 今年的变化 除了以往的手淘和猫客&#xff0c;现在 UC 浏览器、新浪微博、支付宝、…

虚拟机安装centos

到官网下载centos系统&#xff1a; https://www.centos.org/download/ 有三种选择&#xff08;DVD IOS&#xff0c;Everything IOS, Minimal IOS(精简版的)&#xff09;&#xff0c;建议使用DVD IOS 安装虚拟机&#xff1a; #选择典型安装&#xff1a; #选择稍后安装&#…

KAFKA SpringBoot2 Nacos 消息异步发送和消费消息(进阶篇)

文章目录一、基础集成1. 技术选型2. 导入依赖3. kafka配置4. auto-offset-reset 简述5. 新增一个订单类6. 生产者&#xff08;异步&#xff09;7. 消费者8. kafka配置类9.单元测试9. 效果图10. 源码地址11.微服务专栏一、基础集成 1. 技术选型 软件/框架版本jdk1.8.0_202spri…

看懂别人的代码,只是成为高效程序员的第一步!

作者 | SeattleDataGuy译者 | 弯月&#xff0c;责编 | 屠敏出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;在为面试做准备的时候&#xff0c;很多软件工程师都花费了大量时间做编程题和完善简历。最终在找到一份工作后&#xff0c;无论是在创业公司、Google、亚马…

响应速度不给力?解锁正确缓存姿势

阿里妹导读&#xff1a;响应时间长&#xff0c;遇到性能瓶颈时&#xff0c;开发者第一个想到的总是性能优化。《什么技能产品经理不会提&#xff0c;但技术人必须懂&#xff1f;》讲到了什么时候需要使用缓存。但缓存的用法是什么&#xff1f;一旦缓存使用不当&#xff0c;或稍…

Spring Boot2 集成 jasypt 3.0.4 配置文件敏感信息加密

文章目录1. 导入依赖2. yml中添加配置文件3. 加解密工具类4. 敏感信息替换5. 编译打包6. 启动项目1. 导入依赖 <!--敏感信息加密--><dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifa…

技术直播:1小时突击Java工程师面试核心(限免报名)

后疫情时代&#xff0c;连程序员这个多金的职业也遭受到了一定程度的打击。从各大招聘网站和多次面试经历中&#xff0c;相信大家已经意识到&#xff0c;面试官对程序员技能体系和项目经验考核似乎更严苛了。你在面试中常常为什么苦恼呢&#xff1f;简历撰写&#xff1f;数据算…

重塑云上的 Java 语言

音乐无国界&#xff0c;但是音乐人有国界。 云原生亦如此。虽没有限定的编程语言&#xff0c;但应用所使用的编程语言已经决定了应用部署运行的行为。 Java 诞生于20年前&#xff0c;拥有大量优秀的企业级框架&#xff0c;践行 OOP 理念&#xff0c;更多体现的是严谨以及在长…

5分钟带你看懂 GCanvas渲染引擎的演进

本文内容大纲&#xff1a; 1、轻量级图形渲染引擎与应用 2、渲染引擎演进与优化之路 3、渲染引擎未来的发展方向 GCanvas 的定位是遵循 w3c 标准的跨平台的轻量级图形渲染引擎。有清晰的定位和目标&#xff0c;并且紧贴现有的业务&#xff0c;为业务提供丰富表现形式。 GCa…

免费技术直播:唐宇迪带你一节课了解机器学习经典算法

常常有小伙伴在后台反馈&#xff1a;机器学习经典算法有哪些&#xff1f;自学难度大又没有效果&#xff0c;该怎么办&#xff1f;CSDN为了解决这个难题&#xff0c;联合唐宇迪老师为大家带来了一场精彩的直播【一节课掌握机器学习经典算法-线性回归模型】。本次直播将帮大家了解…