CN117891796A - 一种适用于多读少写场景的hdfs海量小文件存储方法 - Google Patents
一种适用于多读少写场景的hdfs海量小文件存储方法 Download PDFInfo
- Publication number
- CN117891796A CN117891796A CN202311773617.2A CN202311773617A CN117891796A CN 117891796 A CN117891796 A CN 117891796A CN 202311773617 A CN202311773617 A CN 202311773617A CN 117891796 A CN117891796 A CN 117891796A
- Authority
- CN
- China
- Prior art keywords
- file
- data
- metadata
- files
- small
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Pending
Links
- 238000000034 method Methods 0.000 title claims abstract description 58
- 230000006870 function Effects 0.000 claims abstract description 28
- 238000010276 construction Methods 0.000 claims abstract description 19
- 238000012217 deletion Methods 0.000 claims abstract description 17
- 230000037430 deletion Effects 0.000 claims abstract description 17
- 238000005516 engineering process Methods 0.000 claims abstract description 9
- 238000005315 distribution function Methods 0.000 claims description 10
- 238000004806 packaging method and process Methods 0.000 claims description 6
- 230000001174 ascending effect Effects 0.000 claims description 3
- 238000012986 modification Methods 0.000 abstract description 9
- 230000004048 modification Effects 0.000 abstract description 9
- 238000013461 design Methods 0.000 description 6
- 230000000694 effects Effects 0.000 description 4
- 230000008569 process Effects 0.000 description 4
- 230000008901 benefit Effects 0.000 description 3
- 230000009286 beneficial effect Effects 0.000 description 2
- 230000007547 defect Effects 0.000 description 2
- 238000011161 development Methods 0.000 description 2
- 238000010586 diagram Methods 0.000 description 2
- 238000013507 mapping Methods 0.000 description 2
- 230000007246 mechanism Effects 0.000 description 2
- 238000012545 processing Methods 0.000 description 2
- 230000003068 static effect Effects 0.000 description 2
- 238000012546 transfer Methods 0.000 description 2
- 230000001186 cumulative effect Effects 0.000 description 1
- 238000013523 data management Methods 0.000 description 1
- 238000013500 data storage Methods 0.000 description 1
- 239000012634 fragment Substances 0.000 description 1
- 230000010354 integration Effects 0.000 description 1
- 238000012423 maintenance Methods 0.000 description 1
- 238000004321 preservation Methods 0.000 description 1
- 238000011084 recovery Methods 0.000 description 1
Classifications
-
- Y—GENERAL TAGGING OF NEW TECHNOLOGICAL DEVELOPMENTS; GENERAL TAGGING OF CROSS-SECTIONAL TECHNOLOGIES SPANNING OVER SEVERAL SECTIONS OF THE IPC; TECHNICAL SUBJECTS COVERED BY FORMER USPC CROSS-REFERENCE ART COLLECTIONS [XRACs] AND DIGESTS
- Y02—TECHNOLOGIES OR APPLICATIONS FOR MITIGATION OR ADAPTATION AGAINST CLIMATE CHANGE
- Y02D—CLIMATE CHANGE MITIGATION TECHNOLOGIES IN INFORMATION AND COMMUNICATION TECHNOLOGIES [ICT], I.E. INFORMATION AND COMMUNICATION TECHNOLOGIES AIMING AT THE REDUCTION OF THEIR OWN ENERGY USE
- Y02D10/00—Energy efficient computing, e.g. low power processors, power management or thermal management
Abstract
本发明提出了一种适用于多读少写场景的HDFS海量小文件存储方法,用以解决现有HDFS存储小文件导致NameNode占用率高以及访问效率低的技术问题。本发明的步骤为:构建阶段:将小文件合并成较大的数据文件并为每个数据文件构建一级索引和二级索引;使用阶段:若是查询操作则查询索引返回结果,若是更新、删除和添加操作,则统一转换为添加,实现更新、删除、添加小文件操作。本发明采用两种索引技术结合的一级索引,既能保证高效的访问,又能协助实现小文件的修改、更新以及删除操作;在小文件访问速度上提升明显,在归档构建的速度上有所提升;具有更新、删除、添加小文件的功能,且效率较高。
Description
技术领域
本发明涉及分布式、海量小文件存储、HDFS分布式文件系统的技术领域,尤其涉及一种适用于多读少写场景的HDFS海量小文件存储方法。
背景技术
分布式技术是一种计算机系统设计和开发的方法,旨在通过将计算和数据存储分散在多个计算节点上,以提高系统的性能、可扩展性和容错性。海量小文件存储是指处理大量数量的小文件的存储需求,如图片、音频、视频、日志等。海量小文件存储面临存储空间利用率低、文件系统性能下降和数据管理复杂等挑战。HDFS分布式文件系统:HDFS(HadoopDistributed File System)是一个开源的分布式文件系统,用于存储和处理大规模数据集。采用了分布式存储的方式,将数据分片存储在多个计算节点上,以提高系统的容错性和性能。HDFS具有高度可扩展性,可以处理大量数据,并且能够适应节点的故障和新增;通过数据的冗余备份和自动的数据恢复机制,保证了数据的可靠性和持久性。
Hadoop是Apache开发的分布式基础计算框架,是对谷歌云计算集群思想的开源实现。由于是开源的,所以没有高额的许可费,可以运行在廉价的硬件上,充分利用集群中的资源,这使得Hadoop得到了广泛的应用。HDFS(Hadoop Distributed File System)是Hadoop的核心模块之一,为整个框架提供底层的海量文件存储功能。HDFS采用主从式架构,NameNode(名称节点)作为主节点,负责管理整个分布式文件系统的元数据信息。DataNode(数据节点)作为从节点,负责对数据进行本地存储。然而,HDFS存储结构的设计有利于大文件的高效存储,但在处理海量小文件时,HDFS的存储与访问效率会大幅下降。海量的小文件会产生大量的元数据,这些元数据全部存放在NameNode节点的内存空间中,使得系统存储文件的能力达到瓶颈。此外,海量小文件导致小文件访问时间开销急剧增加,使得整个系统的文件访问效率降低。
目前针对HDFS小文件存储问题的主要解决方案是基于归档的解决方案,指的是将小文件合并成较大的文件并为小文件建立索引后存储,并向用户提供访问接口。上述方案主要有两种:
1.将小文件合并成大文件后构建索引,然后引入外部系统(例如,HBase、Mysql、Redis)存储小文件的索引信息或小文件数据。这种方案能够方便的为用户提供小文件的修改和更新接口,使得方案能够应用于多读少写的场景。但引入外部系统通常需要进行系统集成和配置,这可能增加了整个系统的复杂性。不同系统之间的接口和数据传输的兼容性问题可能需要额外的开发和调试工作,增加了系统的维护成本和风险。
2.为小文件构建的索引直接存储在HDFS中,不需要引入外部系统,降低了系统的复杂性,但由于HDFS采用的是一次写入,多次读的设计理念,这使得HDFS并不支持随机写入。HDFS2.X版本添加了对一个文件的追加操作,因此许多解决方案仅支持向用户提供添加小文件的操作接口,但并不支持小文件的修改和更新操作。这使得目前的许多方案不能很好的应对多读少写的应用场景,仅能适用于类似于日志系统的应用场景。
申请号为201910242789.4的发明专利公开了一种HDFS存储小文件的方法,通过“打包-构建索引-上传”的方式,来访问HDFS中的小文件,具体步骤如下:i.文件保存:1)将小文件上传至一个中转平台,文件以日期目录存储,每个文件都上传至当天日期的目录下;2)编写脚本,设置定时任务,将当天之前创建的目录打包成tar.gz包并上传至HDFS;3)编写gz解析程序,获取tar.gz包中文件的偏移量和长度;4)设计HBase rowkey,将文件名和gz路径存放到rowkey中;ii.文件查询获取:5)根据文件的日期和文件名,先计算出HBaserowkey,再到HBase中获取该文件的偏移量和长度;6)通过偏移量和长度调用HDFS去读取文件。上述发明提高了访问HDFS中的小文件的效率,节省了资源消耗。但是上述发明的索引存于HBase中,采用方式是小文件合并,不能支持删除、修改,若已经打包成tar.gz的小文件在后续某一时间需要更改或删除,上述专利并没有提供相应的方案。
发明内容
针对现有HDFS存储小文件导致NameNode占用率高以及访问效率低的技术问题,本发明提出一种适用于多读少写场景的HDFS海量小文件存储方法,能够有效降低NameNode内存负载和提高小文件合并的效率;不引入外部系统,能够向用户提供小文件的添加、删除和更新的操作方式,更能适应实际的需求。
为了达到上述目的,本发明的技术方案是这样实现的:一种适用于多读少写场景的HDFS海量小文件存储方法,其步骤如下:
步骤一、构建阶段:将小文件合并成较大的数据文件并为每个数据文件构建一级索引和二级索引;
步骤二、使用阶段:若是查询操作则查询索引返回结果,若是更新、删除和添加操作,则统一转换为添加,实现更新、删除、添加小文件操作。
优选地,所述构建阶段的实现方法为:
(1)预处理:根据HDFS数据块大小计算出数据文件的数量,确定元数据文件存放的小文件元数据的最大个数;
(2)小文件合并:将用于合并的小文件集合分成多个集合,为每个集合创建一个专用线程,将分配给它们的小文件合并到相应的数据文件中;
(3)索引构建:接收小文件的数据项的偏移量和长度并转换为小文件元数据信息临时存储,直到所有线程结束;根据哈希函数将所有元数据信息分配给不同的元数据文件:采用最小完美哈希和键值对两种索引技术结合构建一级索引,采用可扩展哈希函数为每个一级索引构建二级索引。
优选地,根据所有小文件总的大小和HDFS数据块大小划分计算数据文件个数的方法为:获取所有文件的大小并求和,检查用户是否设置数据文件最大尺寸,若设置,获取用户设置的数据文件最大尺寸,否则获取HDFS默认的数据块大小;
元数据文件存放的小文件元数据的最大个数为向上取整(所有小文件的大小总和/HDFS数据块大小)或者用户自定义设置;
通过配置文件设置元数据文件和数据文件最大尺寸,计算得出元数据文件个数,小文件的元数据信息被分散存放在不同的元数据文件中。
优选地,所述小文件合并的实现步骤为:
1)根据数据文件个数将海量小文件划分为多个集合,每个集合总大小不超过HDFS数据块大小;
2)为每一个集合建立一个线程,以并发的方式将小文件合并成数据文件;
3)将小文件的信息传递给构建索引阶段。
优选地,所述步骤2)的实现方法为:获取划分后集合的数量;根据集合数量,创建等量的线程数;每个线程负责一个集合,将集合中的小文件合并成数据文件;
一个数据文件包含多个小文件,元数据文件记录了小文件具体存放在哪个数据文件中以及在数据文件中的存放位置;每个小文件在数据文件中是以数据项的形式存放的,每一个数据项的大小都相等;每个小文件内容转换成数据项写入数据文件中。
优选地,所述小文件的信息包括哈希值、数据文件ID、起始位置、数据项的尺寸,临时存储在内存中,等待线程结束,通过函数调用;数据项包含小文件名的哈希值、小文件内容的大小、小文件的内容;
每个小文件内容转换成数据项写入数据文件中的实现方法为:顺序读取小文件;获取当前小文件的名字、尺寸和内容;根据文件名计算哈希值,将哈希值、尺寸、内容封装成一个实例,将实例写入对应的数据文件中。
优选地,所述构建一级索引的步骤如下:
11)收集每个线程产生的小文件的元数据信息;
12)根据分发函数将元数据信息分发至不同的元数据文件中;
13)使用最小完美哈希函数和键值对为每个元数据文件构建一级索引;
所述采用可扩展哈希函数为每个一级索引构建二级索引的步骤如下:根据一级索引文件的个数计算出global depth的值;构建directory数据结构,其中键是小文件名哈希值二进制形式的后global depth位,值是一级索引文件的文件名。
优选地,所述元数据信息由字段:数据文件的文件名、小文件名的哈希值、数据项的偏移值、数据项的大小、操作码组成;元数据项包含的属性包括:小文件存储在哪个数据文件中的数据文件名、小文件名哈希值、小文件在数据文件中的偏移位置、小文件在数据文件中存储的大小以及元数据项以什么操作方式添加至元数据文件中。
所述分发函数是用于元数据信息分发至不同的元数据文件中的哈希函数,且:
其中,n表示小文件的总数,m表示每个元数据文件的最大项目数,fnhash是小文件名的哈希值;
通过分发函数计算出数据文件的ID;一级索引文件ID和元数据文件ID一致;
global depth的值通过向上取整(log_2(一级索引文件个数))得到。
优选地,更新是直接调用包含俩个参数文件名和文件内容的添加接口,删除时根据文件名查询索引,若存在,调用文件名和空值的添加接口;
转换成添加操作的数据包括:一级索引数据、元数据以及小文件内容数据;即小文件内容包括新的小文件和修改内容后的小文件添加至正确的数据文件中,构建新的元数据项,新的元数据项记录操作涉及的小文件相关信息,将元数据项添加至正确的元数据文件中;随后一级索引重新指向新的元数据项;
每次进行更新、添加和删除操作时,将元数据文件对应的一级索引文件内容全部加载到内存中,再进行操作,然后将结果重新写入一级索引文件中;
将数据文件分为包含多个数据文件的只读数据文件和只存在一个的可读可写数据文件,当可读可写数据文件的大小即将超过HDFS数据块时,转化为只读数据文件,并创建新的可读可写文件,新的可读可写文件的ID=之前的可读可写文件ID+1;
当小文件元数据项过多时,应用可扩展哈希技术中的分裂操作将超过HDFS数据块大小的元数据文件分裂成两个新的元数据文件,应用元数据文件冗余删除并重定向;在遍历元数据项重新分发至新的两个元数据文件中时判断元数据项是否被一级索引指向,如果没有被指向,则说明是无用的冗余数据直接抛弃;遍历结束后新的元数据文件会得到不存在相同小文件名哈希值的元数据项,采用最小完美哈希函数对两个元数据文件重新构建一级索引。
遍历每个元数据项,根据元数据项记录的哈希值访问动态一级索引,如果不存在,则说明没有被修改或删除过,保留;若存在,则获取其一级索引指向的元数据项,若一级索引指向的元数据项中的操作码为“DELETE”则抛弃,若一级索引指向的元数据项中记录的数据文件ID大于当前的元数据项记录的数据文件ID,则说明当前的元数据项为旧项,抛弃;否则保留。
优选地,元数据文件冗余删除的方法为:读取元数据文件中的数据项,创建临时元数据项列表,对于每个元数据项和偏移量:如果元数据项的operateCode等于“DELETE”则抛弃此元数据项,否则从元数据项中获取文件名的哈希值,从动态一级索引中获取索引项,并判断索引项的偏移量是否大于偏移量,如果索引项的偏移量大于偏移量则返回重新确定元数据项和偏移量,否则将元数据项添加到临时元数据项列表;判断是否有下一个元数据项和偏移量,如果是则返回重新确定元数据项和偏移量,否则根据临时数据项列表构建一级索引,将临时数据项列表写入元数据文件中;
数据文件冗余删除的方法为:将当前的可读可写数据文件设置状态为只读,并根据ID+1创建新的可读可写文件;设置一个变量tmpID=0,并根据变量tmpID创建一个临时数据文件tmpID.tmpData;获取所有的只读文件ID,按照ID升序排序;遍历数组IDS;根据ID.data文件名调用HDFS读取文件的API,读取至内存中的数据封装成数据项集合;遍历每个数据项;根据数据项记录的哈希值,访问动态一级索引,如果不存在,则说明没有被修改或删除过,将数据项写入tmpID.tmpData文件中;若存在,则获取一级索引指向的元数据项,若一级索引指向的元数据项中的操作码为“DELETE”则抛弃;若一级索引指向的元数据项中记录的数据文件ID大于当前正在读取的数据文件ID,则当前的数据项为旧项,抛弃;否则写入tmpID.tmpData文件中;当数组IDS中的ID遍历完毕后,将所有后缀为.tmpData的文件修改后缀为.data后缀;
向tmpID.tmpData写入数据时,当写入的数据总尺寸加上即将写入的数据的尺寸大于数据文件最大尺寸时,tmpID=tmpID+1,再创建tmpID.tmpData文件。
与现有技术相比,本发明的有益效果:基于HDFS无法随机写入的机制之上,从而实现了小文件的修改、更新以及删除操作,能够更好的应用于多读少写的场景。具体包括:
1.采用两种索引技术结合的一级索引,既能保证高效的访问,又能协助实现小文件的修改、更新以及删除操作。
2.将数据文件划分为只读数据文件和可读可写数据文件,既能保证每个数据文件不超过HDFS数据块大小,从而提高访问效率,又能协助实现小文件的修改、更新以及删除操作。
3.系统因小文件的修改、更新和删除会产生许多旧数据,从而降低了存储的利用率,本发明设计了一种可以删除冗余数据的方法,保证系统对存储的利用率不会随着系统的使用而降低。
相比较之前的归档方案,本发明在小文件访问速度上提升明显,在归档构建的速度上有所提升;相比于之前方案,本发明具有更新、删除、添加小文件的功能,并且效率较高。
附图说明
为了更清楚地说明本发明实施例或现有技术中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本发明的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。
图1为本发明的流程图。
图2为本发明合并小文件为更大的数据文件的流程图。
图3为本发明构建一级索引文件的流程图。
图4为本发明构建二级索引的流程图。
图5为本发明一级索引的结构图。
图6为本发明数据文件的结构图。
图7为本发明元数据文件冗余去除的流程图。
图8为本发明数据文件冗余去除的流程图。
图9为本发明访问效果对比图。
图10为本发明更新效果对比图。
图11为本发明存储效果对比图。
具体实施方式
下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有付出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。
如图1所示,一种适用于多读少写场景的HDFS海量小文件存储方法,其步骤如下:
步骤一、构建阶段:将小文件合并成较大的数据文件并为每个数据文件构建索引。
构建阶段步骤如下:
(1)预处理:根据HDFS数据块大小计算出数据文件(多个小文件合并形成)的数量,计算出一个元数据文件能够存放的小文件元数据的最大个数,向上取整(所有小文件的大小总和/HDFS数据块大小)或者是用户自定义设置大小。
根据所有小文件总的大小和HDFS数据块大小划分计算数据文件个数,获取所有文件的大小并求和,检查用户是否设置数据文件最大尺寸,若设置,获取用户设置的数据文件最大尺寸,否则获取HDFS默认的数据块大小(HDFS2.x版本为128MB)。默认根据HDFS数据块大小,用户也可自行定制,提供配置文件,用户可通过配置文件设置元数据文件(存放小文件元数据信息)和数据文件(存放小文件内容)最大尺寸,计算得出元数据文件个数,小文件的元数据信息被分散存放在不同的元数据文件中,因此需要为每个元数据文件设置最大尺寸。数据文件个数和元数据文件个数都至少有一个。
(2)小文件合并:将用于合并的小文件集合分成多个集合,这确保了每个部分的累积大小不会超过预定义的阈值。随后,为每个集合创建一个专用线程,负责将分配给它们的小文件合并到相应的数据文件中。
如图2所示,是合并小文件的概述图,步骤如下:
1)根据数据文件个数将海量小文件划分为多个集合,顺序读取文件的尺寸,累加求和,结果接近最大尺寸为一组,然后开启下一组。每个集合总大小不超过HDFS数据块大小,HDFS会将文件切分为多个数据块,多个数据块分散存放于不同的datanode节点中,读取文件时会向多个datanode节点发送请求,总读取时间取决于最慢的。
2)为每一个集合建立一个线程,以并发的方式将小文件合并成数据文件。具体地,获取划分后集合的数量;根据集合数量,创建等量的线程数;每个线程负责一个集合,将集合中的小文件合并成数据文件通过多线程加快小文件合并效率。合并海量小文件为多个较大的数据文件。数据文件存放小文件具体内容。一个数据文件包含多个小文件,元数据文件记录了小文件具体存放在哪个数据文件中以及在数据文件中存放的位置。
3)将小文件的相关信息传递给构建索引阶段。
小文件的相关信息包括哈希值、数据文件ID(存放于哪个数据文件中)、起始位置(在数据文件中存放的位置)、尺寸(最终以数据项形式存储,所以是数据项的尺寸),临时存储在内存中,等待线程结束,通过函数调用。
每个小文件内容不是直接写入数据文件中,而是转换成数据项写入数据文件中,具体实现方法为:顺序读取小文件;获取当前小文件的名字、尺寸和内容;根据文件名计算哈希值,将哈希值、尺寸、内容封装成一个实例,将此实例写入对应的数据文件中(假如此时执行此操作的线程是1,则会写入ID为1的数据文件中。每个小文件在数据文件中是以数据项的形式存放的,每一个数据项的大小都相等。数据项包含以下属性:小文件名的哈希值、小文件内容的大小、小文件的内容。
(3)索引构建:从小文件构建阶段接收数据项的偏移量和长度并将其转换为小文件元数据信息并临时存储它们,将其封装成一个实例,临时存放于内存中,直到所有线程结束。之后,索引构建是根据哈希函数将所有元数据信息分配给不同的元数据文件。
采用两种索引技术结合的一级索引,两种索引技术为:最小完美哈希和键值对,最小完美哈希占用空间小仅O(n log w)bits,时间复杂度为O(1),即需要查询的小文件,以文件名哈希值作为key,仅需要O(1)复杂度即可定位其元数据在元数据文件中的位置,但缺点是映射集合中元素个数必须明确,对于多读少写场景,大部分很少写几乎不写,因此采用最小完美哈希可以极大减少空间占用同时具有O(1)的查询效率。键值对(例如JAVA HashMap类,优点是O(1)查询时间复杂度,不依赖于映射集合中元素的具体个数,可以实时添加元素和删除元素,缺点是比较占用空间),因此适合少写的场景。
如图3所示,是构建一级索引的概述图,它的步骤如下:
1.收集每个线程产生的小文件的元数据信息。
元数据信息由字段:数据文件的文件名、小文件名的哈希值、数据项的偏移值、数据项的大小、操作码组成。对于字符串中的每个字符,计算出它的Unicode编码,对于字符串的第i个字符,将它的Unicode编码乘以31^(n-1),其中n是字符串的长度,i是第i个字符的位置(从左到右,从0开始计数),将每个字符的贡献相加,得到最终的哈希值。在数据文件中存放的起始位置,追加写入前,获取目前数据文件的长度即为将要写入的数据项的起始位置。获取当前数据项写入前的数据文件尺寸,数据项写入后获取数据文件尺寸,两者相减即为数据项的大小。根据用户调用接口获取,用户调用存储接口,则操作码为”STORE”,其他同理。元数据项包含的属性有:小文件存储在哪个数据文件中的数据文件名,小文件名哈希值,小文件在数据文件中的偏移位置,小文件在数据文件中存储的大小,元数据项是以什么操作方式(添加、删除、更新)添加至元数据文件中。
2.根据分发函数,将元数据信息分发至不同的元数据文件中。
其中分发函数是用于元数据信息分发至不同的元数据文件中的哈希函数,公式如下:
其中,n表示小文件的总数,m表示每个元数据文件的最大项目数,根据元数据文件最大尺寸/元数据尺寸得到,是固定大小,每个元数据尺寸均相同。fnhash是小文件名的哈希值。通过上述分发函数,可以计算出数据文件的ID,从而可以将元数据信息分发至相应的元数据文件中。
3.为每个元数据文件构建一级索引。
使用最小完美哈希函数和键值对构建一级索引。一级索引文件ID和元数据文件ID一致,而分发函数是可扩展哈希技术中的哈希函数,因此,而可扩展哈希技术用于构建二级索引,因此通过二级索引计算出ID,即可得到一级索引文件。
构建二级索引:采用可扩展哈希函数为每个一级索引构建二级索引,可以仅用O(1)的时间复杂度,即可定位要查询的小文件在哪个元数据文件中。
结合可扩展哈希函数的二级索引如图4所示,其构建步骤如下:
1.根据一级索引文件的个数计算出对应的global depth的值,通过向上取整(log_2(一级索引文件个数))得到。
2.构建directory数据结构,其中键是小文件名哈希值二进制形式的后globaldepth位,值是一级索引文件的文件名。键的作用是快速查询到指向的元数据文件ID,根据键获得的目录bucket就是数据文件和元数据文件ID。
步骤二、使用阶段:实现更新,删除,添加小文件操作的。
使用阶段步骤如下:(1)用户执行相应的操作。(2)若是查询操作则查询索引返回结果,若是更新、删除和添加操作,则统一转换为添加。更新:直接调用添加接口(包含俩个参数文件名和文件内容)即可。删除:根据文件名查询索引,若存在,调用添加接口(文件名,空值)。
实现小文件追加、删除和更新的关键在于将这些操作转换成HDFS的追加操作。而需要转换成追加操作的数据主要是三种:一级索引数据、元数据以及小文件内容数据。大致思路是:通过重定向方式实现上述三种操作。即小文件内容(包括新的小文件和修改内容后的小文件)添加至正确的数据文件中,将小文件名作为输入,通过可扩展哈希映射至对应的数据文件,随后调用HDFS的文件追加数据api,将其写入。随后构建新的元数据项,新的元数据项记录此次操作涉及的小文件相关信息,然后将此元数据项添加至正确的元数据文件中。随后一级索引重新指向新的元数据项。将小文件名哈希值写入的数据文件ID,以及在数据文件中的起始位置作为参数,创建出一个实例。随后将此实例写入对应的元数据文件(配套的元数据文件和数据文件ID相同,只是后缀不同)中,并记录此次写入位置。调用动态一级索引(例如Java中的HashMap,其键值对形式为<文件名哈希值,元数据项在元数据文件中的起始位置>)重定向。例如<10101,54>-><10101,99>。
由于一级索引也是存放在HDFS中,而HDFS并不支持随机写入,所以每次进行更新、添加和删除操作时,必须将元数据文件对应的一级索引文件内容全部加载到内存中,再进行操作,然后将结果重新写入一级索引文件中。当小文件数据不多时,效率尚可接受,当面对海量小文件时,加载一个元数据文件的整个索引信息是非常耗时的,为此一级索引采用两种技术结合的方式,如图5所示,静态一级索引(采用最小完美哈希函数构建的索引)和动态一级索引(采用键值对构建的索引)。在一级索引构建阶段以及元数据文件大小超过HDFS数据文件大小的分裂阶段,采用最小完美哈希函数构建,它的优点是可以不用加载全部的索引数据至内存中,因此访问速度快,但缺点是构建的元数据集合中的元数据项必须是唯一的并且一旦构建完成不可更改,将其称为静态一级索引。另一个技术则是采用键值对数据结构作为一级索引,会频繁的加载进内存中,将其称为动态一级索引,它用于更新、删除和添加操作时元数据信息的重定向。由于系统是为多读少写场景服务,因此采用键值对数据结构保存的一级索引数量并不多,从而避免了加载一个元数据文件的整个索引信息。
数据文件将其划分为两类,如图6所示,一种是只读数据文件,它包含多个数据文件。一种是可读可写数据文件,它每时每刻只存在一个。当可读可写数据文件的大小即将超过HDFS数据块时,将其转化为只读数据文件,该方法记录了每个数据文件的类型,因此,直接将此数据文件记录的类型更改为只读即可。并创建新的可读可写文件,新的可读可写文件的ID=之前的可读可写文件ID+1。将ID+1.data作为文件名,调用HDFS创建文件的api,通过此种方式,保证了数据文件大小不会超过HDFS数据块大小,避免了HDFS访问某个小文件时需要跨越多个节点读取该小文件的完整内容。
当小文件元数据项过多时,也要保证元数据文件不能超过HDFS数据块大小,因此应用可扩展哈希技术中的分裂操作将超过HDFS数据块大小的元数据文件分裂成两个新的元数据文件,应用元数据文件冗余删除并重定向。在遍历元数据项重新分发至新的两个元数据文件中时会判断该元数据项是否被一级索引指向,如果没有被指向,则说明是无用的冗余数据可直接抛弃。遍历每个元数据项,根据元数据项记录的哈希值,访问动态一级索引,如果不存在,则说明没有被修改或删除过,保留;若存在,则获取其一级索引指向的元数据项,若一级索引指向的元数据项中的操作码为“DELETE”则抛弃,若一级索引指向的元数据项中记录的数据文件ID大于当前的元数据项记录的数据文件ID,则说明当前的元数据项为旧项,抛弃,否则保留。遍历结束后新的元数据文件会得到不存在相同小文件名哈希值的元数据项,此时采用最小完美哈希函数对两个元数据文件重新构建一级索引。
系统因小文件的修改、更新和删除会产生许多旧数据,从而降低了存储的利用率。当系统运行一定时间时,系统就会存在许多的冗余数据,该冗余数据指的是旧的元数据项和旧的小文件内容。使用重定向的方式只是实现了逻辑删除,其旧数据依旧存在于HDFS中,因此必须定期对旧数据进行清除。元数据文件和数据文件冗余去除流程图如图7、图8所示。
如图7所述,元数据文件冗余删除的方法为:
读取元数据文件中的数据项,创建临时元数据项列表,对于每个元数据项和偏移量:如果元数据项的operateCode等于“DELETE”则抛弃此元数据项,否则从元数据项中获取文件名的哈希值,从动态一级索引中获取索引项,并判断索引项的偏移量是否大于偏移量,如果索引项的偏移量大于偏移量则返回重新确定元数据项和偏移量,否则将元数据项添加到临时元数据项列表。动态一级索引是键值对,键为哈希值,值为此文件的元数据项存放的起始位置。因此调用HDFS读取文件api,从起始位置读取获取其指向的最新内容的元数据项,元数据项记录的右偏移值。判断是否有下一个元数据项和偏移量,如果是则返回重新确定元数据项和偏移量,否则根据临时数据项列表(临时在内存中存放保留的元数据项,采用的数据结构为列表,例如Java的ArrayList)构建一级索引(就是图3步骤),将临时数据项列表写入元数据文件中,遍历列表,调用HDFS写文件API一个一个的写。
如图8所示,数据文件冗余删除的方法为:
1.将当前的可读可写数据文件设置状态为只读,并根据其ID+1创建新的可读可写文件。该步骤是为了避免在去除冗余过程中,新的文件会写入当前的可读可写文件中,会与去除冗余过程发生冲突,因此设置当前可读可写数据文件为只读,并创建新的可读可写文件。
2.设置一个变量tmpID=0,并根据tmpID创建一个临时数据文件tmpID.tmpData。该步骤是将去除冗余过程中,存储可以保留下来的小文件。
3.获取所有的只读文件ID(数组IDS[]),按照ID升序排序。
4.遍历数组IDS。
5.根据ID.data文件名,调用HDFS读取文件的API,读取至内存中的数据封装成数据项集合。
6.遍历每个数据项。
7.根据数据项记录的哈希值,访问动态一级索引,如果不存在,则说明没有被修改或删除过,将其数据项写入tmpID.tmpData文件中。
8.若存在,则获取其一级索引指向的元数据项,若一级索引指向的元数据项中的操作码为“DELETE”则抛弃。
9.若一级索引指向的元数据项中记录的数据文件ID大于当前正在读取的数据文件ID,则说明当前的数据项为旧项,抛弃。否则写入tmpID.tmpData文件中。
其中向tmpID.tmpData写入数据时,可能会超出数据文件最大尺寸。当写入的数据总尺寸加上即将写入的数据的尺寸大于数据文件最大尺寸时,tmpID=tmpID+1,再创建tmpID.tmpData文件。
当数组IDS[]中的ID遍历完毕后。将所有后缀为.tmpData的文件修改后缀为.data后缀。
本发明采用的也是小文件合并方法,但不引入任何外部系统,小文件合并结果直接存储于HDFS中,小文件的元数据信息直接存储于HDFS中,索引信息直接存储于HDFS中。HDFS不支持随机写入,但支持随机读取。HDFS支持覆盖写入(将原始内容全部覆盖)和追加写入(不覆盖原始内容,新内容写至原始内容之后)。早期版本的HDFS不支持任何的文件更新操作,一旦一个文件创建、写完数据、并关闭之后,这个文件就再也不能被改变了。Hadoop1.x版本一直都不支持文件的append功能,一直到Hadoop 2.x版本,append功能才被添加到Hadoop Core中,允许向HDFS文件中追加写数据。以此为基础之上,实现存储、删除、修改。实现方式为:索引架构设计如图4和图5所示,数据文件(小文件合并结果)架构设计,如图6所示。
横坐标为小文件数据集(分别是十万,二十万,三十万,四十万)。纵坐标为时间,单位Milliseconds。时间越低越好。其中,SequenceFile、MapFile、HAR均为HDFS原生提供的。HPF:为论文:Hadoop Perfect File:A fast and memory-efficient metadata accessarchive file to face small files problemin HDFS。Proposed Method为本发明方法。HDFS即原生。本发明的效果对比:根据横坐标小文件数据集,抽取百分之5的文件随机进行访问,得出的时间,如图9所示,时间越低效率越高,可以看出本发明的访问效率较高。根据横坐标小文件数据集,抽取百分之5的文件进行更新,得出的时间,如图10所示,时间越低效率越高,可以看出本发明的更新效率较高,HDFS更新是先读取原始内容至内存中,修改再全部覆盖写入,早期版本的HDFS不支持任何的文件更新操作,一旦一个文件创建、写完数据、并关闭之后,这个文件就再也不能被改变了,如图11所示,在本发明构建好的归档文件基础上,使用存储接口对一千个文件的数据集进行存储,可以看出本发明的存储效率高。HDFS也是对一千个数据集进行存储,得出的时间,时间越低效率越好。
以上所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。
Claims (10)
1.一种适用于多读少写场景的HDFS海量小文件存储方法,其特征在于,其步骤如下:
步骤一、构建阶段:将小文件合并成较大的数据文件并为每个数据文件构建一级索引和二级索引;
步骤二、使用阶段:若是查询操作则查询索引返回结果,若是更新、删除和添加操作,则统一转换为添加,实现更新、删除、添加小文件操作。
2.根据权利要求1所述的适用于多读少写场景的HDFS海量小文件存储方法,其特征在于,所述构建阶段的实现方法为:
(1)预处理:根据HDFS数据块大小计算出数据文件的数量,确定元数据文件存放的小文件元数据的最大个数;
(2)小文件合并:将用于合并的小文件集合分成多个集合,为每个集合创建一个专用线程,将分配给它们的小文件合并到相应的数据文件中;
(3)索引构建:接收小文件的数据项的偏移量和长度并转换为小文件元数据信息临时存储,直到所有线程结束;根据哈希函数将所有元数据信息分配给不同的元数据文件:采用最小完美哈希和键值对两种索引技术结合构建一级索引,采用可扩展哈希函数为每个一级索引构建二级索引。
3.根据权利要求2所述的适用于多读少写场景的HDFS海量小文件存储方法,其特征在于,根据所有小文件总的大小和HDFS数据块大小划分计算数据文件个数的方法为:获取所有文件的大小并求和,检查用户是否设置数据文件最大尺寸,若设置,获取用户设置的数据文件最大尺寸,否则获取HDFS默认的数据块大小;
元数据文件存放的小文件元数据的最大个数为向上取整(所有小文件的大小总和/HDFS数据块大小)或者用户自定义设置;
通过配置文件设置元数据文件和数据文件最大尺寸,计算得出元数据文件个数,小文件的元数据信息被分散存放在不同的元数据文件中。
4.根据权利要求2或3所述的适用于多读少写场景的HDFS海量小文件存储方法,其特征在于,所述小文件合并的实现步骤为:
1)根据数据文件个数将海量小文件划分为多个集合,每个集合总大小不超过HDFS数据块大小;
2)为每一个集合建立一个线程,以并发的方式将小文件合并成数据文件;
3)将小文件的信息传递给构建索引阶段。
5.根据权利要求4所述的适用于多读少写场景的HDFS海量小文件存储方法,其特征在于,所述步骤2)的实现方法为:获取划分后集合的数量;根据集合数量,创建等量的线程数;每个线程负责一个集合,将集合中的小文件合并成数据文件;
一个数据文件包含多个小文件,元数据文件记录了小文件具体存放在哪个数据文件中以及在数据文件中的存放位置;每个小文件在数据文件中是以数据项的形式存放的,每一个数据项的大小都相等;每个小文件内容转换成数据项写入数据文件中。
6.根据权利要求5所述的适用于多读少写场景的HDFS海量小文件存储方法,其特征在于,所述小文件的信息包括哈希值、数据文件ID、起始位置、数据项的尺寸,临时存储在内存中,等待线程结束,通过函数调用;数据项包含小文件名的哈希值、小文件内容的大小、小文件的内容;
每个小文件内容转换成数据项写入数据文件中的实现方法为:顺序读取小文件;获取当前小文件的名字、尺寸和内容;根据文件名计算哈希值,将哈希值、尺寸、内容封装成一个实例,将实例写入对应的数据文件中。
7.根据权利要求5或6所述的适用于多读少写场景的HDFS海量小文件存储方法,其特征在于,所述构建一级索引的步骤如下:
11)收集每个线程产生的小文件的元数据信息;
12)根据分发函数将元数据信息分发至不同的元数据文件中;
13)使用最小完美哈希函数和键值对为每个元数据文件构建一级索引;
所述采用可扩展哈希函数为每个一级索引构建二级索引的步骤如下:根据一级索引文件的个数计算出global depth的值;构建directory数据结构,其中键是小文件名哈希值二进制形式的后global depth位,值是一级索引文件的文件名。
8.根据权利要求7所述的适用于多读少写场景的HDFS海量小文件存储方法,其特征在于,所述元数据信息由字段:数据文件的文件名、小文件名的哈希值、数据项的偏移值、数据项的大小、操作码组成;元数据项包含的属性包括:小文件存储在哪个数据文件中的数据文件名、小文件名哈希值、小文件在数据文件中的偏移位置、小文件在数据文件中存储的大小以及元数据项以什么操作方式添加至元数据文件中;
所述分发函数是用于元数据信息分发至不同的元数据文件中的哈希函数,且:
其中,n表示小文件的总数,m表示每个元数据文件的最大项目数,fnhash是小文件名的哈希值;
通过分发函数计算出数据文件的ID;一级索引文件ID和元数据文件ID一致;
global depth的值通过向上取整(log_2(一级索引文件个数))得到。
9.根据权利要求1或8所述的适用于多读少写场景的HDFS海量小文件存储方法,其特征在于,更新是直接调用包含俩个参数文件名和文件内容的添加接口,删除时根据文件名查询索引,若存在,调用文件名和空值的添加接口;
转换成添加操作的数据包括:一级索引数据、元数据以及小文件内容数据;即小文件内容包括新的小文件和修改内容后的小文件添加至正确的数据文件中,构建新的元数据项,新的元数据项记录操作涉及的小文件相关信息,将元数据项添加至正确的元数据文件中;随后一级索引重新指向新的元数据项;
每次进行更新、添加和删除操作时,将元数据文件对应的一级索引文件内容全部加载到内存中,再进行操作,然后将结果重新写入一级索引文件中;
将数据文件分为包含多个数据文件的只读数据文件和只存在一个的可读可写数据文件,当可读可写数据文件的大小即将超过HDFS数据块时,转化为只读数据文件,并创建新的可读可写文件,新的可读可写文件的ID=之前的可读可写文件ID+1;
当小文件元数据项过多时,应用可扩展哈希技术中的分裂操作将超过HDFS数据块大小的元数据文件分裂成两个新的元数据文件,应用元数据文件冗余删除并重定向;在遍历元数据项重新分发至新的两个元数据文件中时判断元数据项是否被一级索引指向,如果没有被指向,则说明是无用的冗余数据直接抛弃;遍历结束后新的元数据文件会得到不存在相同小文件名哈希值的元数据项,采用最小完美哈希函数对两个元数据文件重新构建一级索引;
遍历每个元数据项,根据元数据项记录的哈希值访问动态一级索引,如果不存在,则说明没有被修改或删除过,保留;若存在,则获取其一级索引指向的元数据项,若一级索引指向的元数据项中的操作码为“DELETE”则抛弃,若一级索引指向的元数据项中记录的数据文件ID大于当前的元数据项记录的数据文件ID,则说明当前的元数据项为旧项,抛弃;否则保留。
10.根据权利要求9所述的适用于多读少写场景的HDFS海量小文件存储方法,其特征在于,元数据文件冗余删除的方法为:读取元数据文件中的数据项,创建临时元数据项列表,对于每个元数据项和偏移量:如果元数据项的operateCode等于“DELETE”则抛弃此元数据项,否则从元数据项中获取文件名的哈希值,从动态一级索引中获取索引项,并判断索引项的偏移量是否大于偏移量,如果索引项的偏移量大于偏移量则返回重新确定元数据项和偏移量,否则将元数据项添加到临时元数据项列表;判断是否有下一个元数据项和偏移量,如果是则返回重新确定元数据项和偏移量,否则根据临时数据项列表构建一级索引,将临时数据项列表写入元数据文件中;
数据文件冗余删除的方法为:将当前的可读可写数据文件设置状态为只读,并根据ID+1创建新的可读可写文件;设置一个变量tmpID=0,并根据变量tmpID创建一个临时数据文件tmpID.tmpData;获取所有的只读文件ID,按照ID升序排序;遍历数组IDS;根据ID.data文件名调用HDFS读取文件的API,读取至内存中的数据封装成数据项集合;遍历每个数据项;根据数据项记录的哈希值,访问动态一级索引,如果不存在,则说明没有被修改或删除过,将数据项写入tmpID.tmpData文件中;若存在,则获取一级索引指向的元数据项,若一级索引指向的元数据项中的操作码为“DELETE”则抛弃;若一级索引指向的元数据项中记录的数据文件ID大于当前正在读取的数据文件ID,则当前的数据项为旧项,抛弃;否则写入tmpID.tmpData文件中;当数组IDS中的ID遍历完毕后,将所有后缀为.tmpData的文件修改后缀为.data后缀;
向tmpID.tmpData写入数据时,当写入的数据总尺寸加上即将写入的数据的尺寸大于数据文件最大尺寸时,tmpID=tmpID+1,再创建tmpID.tmpData文件。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202311773617.2A CN117891796A (zh) | 2023-12-21 | 2023-12-21 | 一种适用于多读少写场景的hdfs海量小文件存储方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202311773617.2A CN117891796A (zh) | 2023-12-21 | 2023-12-21 | 一种适用于多读少写场景的hdfs海量小文件存储方法 |
Publications (1)
Publication Number | Publication Date |
---|---|
CN117891796A true CN117891796A (zh) | 2024-04-16 |
Family
ID=90646048
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202311773617.2A Pending CN117891796A (zh) | 2023-12-21 | 2023-12-21 | 一种适用于多读少写场景的hdfs海量小文件存储方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN117891796A (zh) |
-
2023
- 2023-12-21 CN CN202311773617.2A patent/CN117891796A/zh active Pending
Similar Documents
Publication | Publication Date | Title |
---|---|---|
US11182356B2 (en) | Indexing for evolving large-scale datasets in multi-master hybrid transactional and analytical processing systems | |
CN103020315B (zh) | 一种基于主从分布式文件系统的海量小文件存储方法 | |
US7818346B2 (en) | Database heap management system with variable page size and fixed instruction set address resolution | |
US11461304B2 (en) | Signature-based cache optimization for data preparation | |
US20170109378A1 (en) | Distributed pipeline optimization for data preparation | |
US20100293332A1 (en) | Cache enumeration and indexing | |
CN103595797B (zh) | 一种分布式存储系统中的缓存方法 | |
CN113377868B (zh) | 一种基于分布式kv数据库的离线存储系统 | |
JPH10501086A (ja) | 記憶プレーン編成及びそれに基づく記憶システム | |
CN106570113B (zh) | 一种海量矢量切片数据云存储方法及系统 | |
CN111881107B (zh) | 支持多文件系统挂载的分布式存储方法 | |
US20170109389A1 (en) | Step editor for data preparation | |
JP6598997B2 (ja) | データ準備のためのキャッシュ最適化 | |
Tao et al. | LHF: A new archive based approach to accelerate massive small files access performance in HDFS | |
Changtong | An improved HDFS for small file | |
US10387384B1 (en) | Method and system for semantic metadata compression in a two-tier storage system using copy-on-write | |
CN112965939A (zh) | 一种文件合并方法、装置和设备 | |
KR20090007926A (ko) | 플래시 메모리에 저장된 데이터의 인덱스 정보 관리 장치및 방법 | |
US20230222165A1 (en) | Object storage-based indexing systems and method | |
CN113138859A (zh) | 一种基于共享内存池的通用数据存储方法 | |
WO2022121274A1 (zh) | 一种存储系统中元数据管理方法、装置及存储系统 | |
CN117891796A (zh) | 一种适用于多读少写场景的hdfs海量小文件存储方法 | |
CN115114294A (zh) | 数据库存储模式的自适应方法、装置、计算机设备 | |
Kvet | Database Block Management using Master Index | |
Klein et al. | Dxram: A persistent in-memory storage for billions of small objects |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination |