HashData实战案例:使用Alluxio构建云原生分析型MPP数据库
本文将介绍北京一家初创企业HashData构建基于云原生的MPP平台的过程。该企业利用对象存储作为数据持久层,Alluxio作为云中的数据编排层,终构建了一个原生云高性能MPP共享的体系架构。
HashData是由一群来自Pivotal、Teradata、IBM、Yahoo!等开源数据人士于2016年创立的。它的旗舰产品HashData WareHouse(HDW),是为云环境构建的数据仓库服务,具有完全兼容的Greenplum分析接口。HDW独特的多集群共享数据库体系架构,在性能、并发性、灵活性和易用性方面取得了很大突破。和许多传统MPP系统采用的非共享体系架构(计算与存储紧耦合)不同,HDW采用了具有解耦和独立对象存储的共享体系架构。这种体系架构的主要挑战在于性能。与传统的块存储相比,对象存储通常性能较低。在本文中,我们将进一步分析HDW如何利用Alluxio作为数据编排层,以消除对象存储带来的性能损失,同时受益于对象存储的可伸缩性和成本效应。
常用链接
- Alluxio项目官网
- Alluxio在各大厂用例
- 关注Alluxio微信公众号:Alluxio_China
为什么使用对象存储服务
如今,对象存储服务(OSS)在原生云架构中一直很重要。正如这篇博客所提出的,它提供了更高的可用性、弹性和耐久性,而且成本更低。越来越多的产品和服务支持OSS作为他们的持久文件系统。
- 节省成本
根据我们的观察,对于许多拥有100 TB+数据的用户来说,他们的成本主要来自存储成本,而不是计算成本。一个主要原因是计算完全随需应变,而存储容量在删除数据之前无法回收。因此,当客户考虑各种数据分析选项时,存储成本是一个重要因素。下表为中国全栈ICT服务及解决方案(包括公共云服务)供应商QingCloud在PEK3区域的块存储和对象存储的价格对比。OSS的成本大约是单副本块存储的1/4,多副本块存储的1/5。
弹性也会影响存储成本。虽然块存储支持在线扩展,但是弹性计算机(即将扩展的块存储卷连接到它)在扩展期间会导致HDW集群短暂停机。因此,客户通常会保留额外的块存储容量,以避免在短时间内再次扩展,从而导致成本更高。
总之,基于OSS的数据仓库解决方案的存储成本大约是使用传统块存储成本的1/10。
- 系统灵活性
让我们来看一个典型的数据分析场景,尤其是在物联网和电信行业:随着时间的推移,越来越多的数据生成并被导入到数据仓库系统中。通常,由于应用程序需求或管理策略的原因,这些数据需要保存18或36个月。此外,所有数据必须随时可查询,例如在线分析;另一方面,大多数单个查询(如果不是全部的话)只涉及整个数据存储的一小部分(例如,近一周或近一个月,或2016年9月至2016年10月之间生成的数据)。换句话说,计算资源的需求是稳定的,而存储资源的需求则在不断增长。在传统的非共享架构下,为了解决这个问题,我们需要对集群进行扩展(例如增加更多的worker节点),因为挂载到弹性计算机上的块存储的容量有上限。在这种扩展场景中,新增的计算资源完全是浪费,更不用说集群扩展是一个容易出错且耗时的过程。
与传统MPP解决方案的刚性相反,HDW的数据存储容量几乎是无限的。存储层扩展对于计算层是完全透明的。实际上,从HDW用户的角度来看,没有存储扩展概念。用户可以继续将数据导入到HDW集群中,并处理目标数据来支持他们的业务决策。
- 内置表
如上所述,HDW继承了Greenplum数据库丰富的数据分析功能。其中一个惊人的功能是通过外部表访问对象存储中的原生数据。虽然外部表有一定的特点,但是与外部表相比,HDW基于OSS的内置表还进一步具有以下优势:
- 内置表支持更新/删除和索引操作。重要的是,内置表完全支持ACID事务。这些特征外部表都不支持。
- 内置表可以实现更好的数据压缩。目前,外部表支持三种常见的数据格式:TXT、CSV和ORC。根据我们的观察,为了简单起见,与ORC相比,客户通常更喜欢带有ZIP压缩算法的TXT/CSV。使用内置表,我们可以使用更复杂的编码策略(例如字典编码和变长编码)和压缩算法(例如zstd)。
- 内置表具有更好的查询性能。内置表的数据布局样式(无论是存储在内存中还是在磁盘上),都为HDW的执行引擎进行了高度优化。
使用Alluxio加速OSS访问
尽管对象存储为大数据系统提供了很多好处,但是与块存储相比,它具有更低的I/O性能。一方面,虽然随着对象存储技术的不断发展,目前大多数对象存储服务只能够为每个HTTP连接提供100MB/s左右的GET吞吐量和40MB/s的PUT吞吐量。当启用多线程GET、多线程上传和数据压缩时,总体I/O吞吐量可以匹配数据库执行器的处理吞吐量。另一方面,OSS本身不是瓶颈的时候,在一个公有云环境中,HDW集群所在软件定义网络(SDN)的总带宽通常存在一个上限,这会在HDW集群访问对象存储中的数据时限制I/O性能。其次,客户需要为每个OSS HTTP请求付费。第三,HDW支持各种索引算法,包括B树、位图和GiST。客户可以利用这些索引算法,通过扫描索引来加速查询,并在数万亿元组上实现亚秒级查询时间。另一个查询场景是查询低维度表。对于这些情况,OSS的吞吐量虽然不是性能瓶颈,但是其访问延迟确是一个很大的瓶颈问题。
为了解决上述问题,我们选择了Alluxio作为智能缓存层来加速I/O性能。Alluxio,原名Tachyon,是世界上个用于云计算分析和人工智能的数据编排技术。它连接了计算框架和存储系统,使存储层的数据更接近计算框架,允许应用程序通过公共接口连接到多个存储系统,使得数据更易于访问。Alluxio的内存的分层架构使得它能够比现有解决方案快几个数量级的速度访问数据。
结合使用HDW和Alluxio,缓存数据被平均分区到每个worker节点上。每个HDW片段都将数据缓存到它的本地Alluxio worker中。Alluxio主节点与HDW主节点被部署在一起。所有用户都是通过Alluxio接口操作数据。HDW的高层存储架构如下图所示。
Alluxio在大数据生态系统中扮演者重要的角色。它与许多开源大数据系统共享类似的技术栈,包括基于Java或JVM的轻量级事务模型,这使得Alluxio与它们完美匹配。然而,仍然有许多分布式系统采用完全不同的构建理念。在接下来的部分中,我们将分享在利用Alluxio构建原生云MPP数据库时学到的经验。
- C/C++原生客户端
Alluxio提供几种编程语言绑定,包括Java、Go和Python,还通过HTTP代理支持所有其它语言的REST接口。虽然开源项目liballuxio通过使用JNI调用原生Java客户端能够提供C/C++ Alluxio接口,但是目前还没有官方的C/C++原生客户端。为了提高系统性能、稳定性、灵活性和易维护性,我们决定为Alluxio实现一个原生C/C++客户端,而不是直接使用liballuxio。
在HashData中,我们构建了一个C/C++客户端liballuxio2,它通过RPC调用来和Alluxio服务器交互。在Alluxio不同组件之间的交互过程是基于thrift/protobuf/netty。liballuxio2作为一个原生客户端,采用了thrift/protobuf提供的Alluixo统一数据交换格式。目前,liballuxio2支持Alluxio-1.5.0版本。
- 统一对象存储SDK
Alluxio作为底层文件系统(UFS)支持各种对象存储服务,包括S3、Azure Blob Store、GCS等,并提供了一个框架,用户可以通过该框架轻松地扩展它来支持新的对象存储。但是,我们采用了不同的方法,理由如下:
- 不同的对象存储服务支持不同的访问优化策略,以获得更高的读写性能,包括多线程上传和流水线下载。构建一个C/C++原生OSS库是利用这些优化机会的更好方法。
- 作为一家初创企业,HashData希望支持本地公共云提供商提供的各种对象存储服务,而不仅仅是上述的跨国巨头。统一的C/C++ OSS客户端库可以大大减少研发工作,使得开发人员不必担心异构对象存储服务的复杂性。
- Alluxio客户端可以使用委托/非委托模式来控制UFS操作的处理位置。在非委托模式下,Alluxio C/C++原生客户端负责OSS读写操作。Alluxio服务器只需要维护元数据和基于缓存I/O流的块。
我们已经构建了一个统一C/C++原生库来支持本地和全球云平台的对象存储服务,并且将它集成到liballuxio2库中。用户仍然可以选择委托模式来保留Alluxio服务器执行的OSS操作。
- 分层存储
Alluxio支持分层存储,以便管理除内存以外的其它存储类型。目前,Alluxio支持三种存储类型/层,包括MEM(内存)、SDD(固态驱动器)和HDD(硬盘驱动器)。
在开始时,我们保持默认的分层设置,例如数据首先缓存到MEM层,并在上层填满后迁移到SSD/HDD。但是,当我们开始使用大量数据进行压力测试时,如果MEM层中的所有文件都是打开的,那么缓存的数据就不能被删除。对于典型的HDW工作负载,MEM层的容量(为了节省成本,我们通常不会为EC机器分配太多内存)不足以缓存目标数据。因此,我们将默认的写入层更改为SSD。更关键的是,在数据超出本地磁盘容量的情况下,HDW数据库内核会告诉C/C++原生Alluxio客户端liballuxio2不要缓存哪些运行查询的数据。许多复杂的Alluxio读/写/缓存策略都是由HDW数据库内核动态决定的。
- 事务提交
作为关系数据库管理系统(RDBMS),HDW完全支持ACID分布式事务。与许多基于HDFS的大数据分析系统(原子写是利用HDFS原子重命名特性实现的)不同的是,HDW对事务的支持是建立在数据库内核里的。只有当所有打开供写的文件都成功地持久化在对象存储上时,事务才成功提交;否则事务将中止,并清除所有开放可写的文件(包括数据)。
为了保证数据持久性,所有的Alluxio写操作都直接写到对象存储中,而不需要缓存。
基准测试
我们使用TPC基准(TPC-H)测试来评估我们的解决方案。TPC-H是一个决策支持基准测试集,由一组面向业务的即时查询和并发数据修改组成。查询和填充数据库的数据具有广泛的行业相关性。
这个基准测试的目的不是显示HDW对TPC-H查询的运行速度有多快,而是显示Alluxio提升I/O性能的有效性。因此,在接下来的基准测试中,我们将HDW的执行引擎设置为与开源Greenplum引擎完全相同,而不是私有的。此外,这项评估大约是在一年前进行的,使用的是基于Alluxio的HDW的个稳定版本,它具有与Greenplum-5.0版本相同的数据库内核版本。
- 配置
- 数据集大小:100GB
- 集群:1个主节点,8个子(计算)节点
- 主节点:QingCloud超高性能实体,2个CPU,4GB内存
- 子节点:QingCloud超高性能实体,4个CPU,8GB内存
- Alluxio:1.5.0版本,每个工作节点内存为2GB
场景
- Greenplum 5.0:我们选择这个版本的开源Greenplum作为基准。
- HashData:HDW读取的目标数据是从远程对象存储缓存到Alluxio层的。
结果
根据我们的观察,OSS的I/O吞吐量至少比本地磁盘低3倍。然而,从这个测试结果来看,只有大约30%的性能下降。这是因为TPC-H是一个OLAP查询基准,它包含比I/O密集型任务更多的CPU密集型任务。通常,冷读只发生在次接触数据时。使用Alluxio缓存系统,冷读操作的数量大大减少。如图3所示,使用Alluxio缓存读取的HDW性能与传统的非共享MPP相同,同时支持使用对象存储的所有优点。
结论
在本文中,我们展示了通过精心设计的存储和缓存层,原生云数据仓库可以利用Alluxio消除对象存储的性能损失,同时享受其可伸缩性和成本效应。
原文链接:https://zhuanlan.zhihu.com/p/89550472
相关文章