Tachyon是一个以内存为核心的开源分布式存储系统,也是目前发展最迅速的开源大数据项目之一。Tachyon为不同的大数据计算框架(如Apache Spark,Hadoop MapReduce, Apache Flink等)提供可靠的内存级的数据共享服务。此外,Tachyon还能够整合众多现有的存储系统(如Amazon S3, Apache HDFS, RedHat GlusterFS, OpenStack Swift等),为用户提供统一的、易用的、高效的数据访问平台。
大数据的处理绝对是占内存的,而大数据的处理对速度的追求是无止境的,内存的速度和磁盘的速度不是一个数量级的,随着技术的发展内存的价格越来越低、内存的容量越来越大,这就让数据存在内存有了可行性。伴随着这种趋势,基于内存计算大数据框架出现了,如采用分布式计算模式的Spark。Spark相比于MapReduce大大提升了大数据的计算性能,然而还是有很多问题是在计算机框架层面难以解决的:
(1)数据共享问题。一个集群可能运行着多个计算框架和多个应用,比如说一个集群上有可能运行着Spark,同时还运行着Hadoop,在现在的情况下他们两个之间的数据共享是通过HDFS的。也就是说如果一个Spark的应用结果的输出是另外一个MapReduce任务输入的话,中间结果就必须要通过写入和读取HDFS才能实现,大家知道HDFS的读写首先是一个磁盘的IO,另外由于它的备份策略,默认它有三份的备份,这样又会引入网络的IO,这是一个很低效的过程;
(2)缓存数据丢失问题。像Spark这样的计算框架它的内存管理模块和计算执行器是在同一个JVM里面的,如果它的执行器发生一些异常导致执行出现错误,从而导致JVM退出的话,那么缓存在JVM堆空间中的数据就会同时丢失掉,这样的话就会导致缓存数据丢失;
(3)GC问题。因为现在大部分的大数据的计算框架都是运行在JVM上的,GC的开销就是一个不可避免的问题。对于像Spark这样一个基于内存的计算框架而言,GC的问题尤其突出,它会把大量的数据缓存在JVM堆空间里面,这些数据是计算时需要用到的数据,GC是没办法清除掉的,每一次full GC都会对这些数据做一个全局的扫描,这是很耗时间的,而且随着计算时间的增长和堆内存数据的增加,GC的开销会越来越大。
从分析中可以发现,现有的基于内存的计算框架缺乏脱离于JVM的内存管理模块。此时基于内存的分布式存储系统Tachyon就应时而生。
Tachyon的设计思想主要有两个:(1)基于内存的OffHeap的分布式存储,就是一定要把数据存储在JVM堆空间之外,这样的话能够避免GC;(2)通过在存储层保存数据的Lineage实现容错,这是在Spark中引入的思想,Lineage记录了源数据以及源数据经过什么样的计算得到的当前数据,Tachyon将这些本来是在计算层才关心的信息放到了存储层。Tachyon仅仅保存一份数据在内存中,内存是很宝贵的资源。而HDFS它为了实现容错在磁盘上默认保存了三份,那么如果Tachyon某一个节点是没有这份数据的时候,它会通过网络去读。因为在远端的结点上数据也是在内存中间的,因此远端读取没有磁盘的IO只有网络的开销,所以说也是很高效的。当数据丢失的时候,Tachyon会根据数据的Lineage进行数据的恢复,这个过程有点像Spark中的数据重算,但是它比Spark走的更远。因为Spark中的重算是在程序运行时的操作,当程序运行的时候发现某个节点挂掉了,它会重新计算来管不着数据,问题是如果整个Job已经结束之后,数据再发生丢失就没有办法了,Tachyon可以解决这个问题。因为Tachyon在存储层存储了整个数据的依赖关系,包括了这个数据是由什么样的框架,通过什么样的执行过程生成的,当数据丢失的时候Tachyon会重新启动这些应用然后生新成这些数据,实现数据恢复。
1、在生态系统中的位置
如上图所示,Tachyon在整个大数据处理软件栈中的位置,最下层是存储层(如S3、HDFS等),上层有Spark、Hadoop等计算框架,Tachyon相当于是在计算层和存储层之间的cache层,所以说Tachyon并不是要代替任何存储系统,它的作用是加快计算层对存储层的访问速度。
2、Tachyon的基本架构
从上面的架构图可以看出Tachyon的架构是传统的Master/Slave架构。主要包括4个组件:Tachyon Master、Tachyon Worker、Tachyon Client及底层的存储系统(Underlayer Storage System)。每个组件的功能如下:
(1)TachyonMaster主要负责管理两类重要信息:①记录管理整个集群中所有数据的元数据信息,包括Tachyon命名空间的组织结构、所有数据的基本信息(数据的大小、数据的位置等)等;②监管整个Tachyon系统的状态,包括整个系统的存储容量的使用情况、所有Worker的运行情况;
(2)TachyonWorker主要负责管理每个节点上的内存数据。Tachyon Worker中所有的内存数据都是存储在Ramdisk上的,Ramdisk是把一段内存映射成一个block设备,Tachyon就可以以内存的速度进行读写了,所以说Worker以块为粒度进行存储和管理,如:为新的数据块分配空间、将热数据块从SSD或HDD移至内存、实时或定期备份数据块到底层存储系统;同时,Tachyon Worker定时向Tachyon Master发送心跳(heartbeat)以告知自身的状态信息,Master会根据Worker汇报的信息给Worker发送命令;
(3)Tachyon Client是上层应用访问Tachyon数据的入口。访问过程可以包括如下几步:①Client向Master询问数据文件的基本信息,包括文件位置,数据块大小等;②Client尝试从本地Worker中读取对应数据块,若本地不存在Worker或者数据块不在本地Worker中,则尝试从远程Worker中读取;③若数据还未被缓存到Tachyon中,则Client会从底层存储系统中读取对应数据。此外,Tachyon Client会向所有建立连接的Tachyon Master和Tachyon Worker定时发送心跳以表示仍处于连接租期中,中断连接后Tachyon Master和Tachyon Worker会回收对应Client的临时空间;
(4)Tachyon 底层存储系统既可以被Tachyon用来备份数据,也可以作为Tachyon缓存数据的来源,上层应用在使用Tachyon Client时也能直接访问底层存储系统上的数据。底层存储系统保证了Tachyon Worker在发生故障而崩溃后不会导致数据丢失,同时也使得上层应用在迁移到Tachyon的同时不需要进行底层数据的迁移。目前Tachyon支持的底层存储系统有HDFS,GlusterFS,Amazon S3,OpenStack Swift以及本地文件系统,且能够比较容易地嵌入更多的现有存储系统;
在实际部署时, Tachyon Master通常部署在单个主节点上(Tachyon也支持多个节点上部署Tachyon Master,并通过使用ZooKeeper来防止单点故障);将Tachyon Worker部署在多个从节点;Tachyon Client和应用相关,可以位于任何一个节点上。
3、Tachyon的工作原理
首先是它的通讯机制,Tachyon使用thrift进行通讯,可以通过配置Master Client和Worker之间的接口自动生成。还有就是Heartbeat通讯,是为了在Tachyon各组件之间保持连接关系,Master和Worker也会通过Heartbeat交换信息,Worker会把自己节点上最近增加的数据或者是数据的改变提交给Master,Master会根据Worker提供的文件信息去修改Master上的元数据,Master也会返回给Worker一些信息。如果Worker提供给Master的文件信息的元数据在Master已经没有了,Master就会告诉Worker删掉该文件。如果Worker有一段时间没有和Master通讯,Master就会认为Worker已经和他断开连接,当Worker又和Master通讯的时候,Master就会告诉Worker需要重新注册,把节点上所有的文件信息重新发给Master。Worker也有自检措施,如果它检测到和Master通讯超时,会重新向Master注册。Client和Master Worker之间都是有连接的,Client发送给Master的Heartbeat,Master暂时没有处理。Client和Worker之间的通讯就是为了维持Client和Worker之间的关系,如果Worker检查到Client连接超时,Worker就会释放掉分配给Client的资源。
1、支持多种部署方式
作为大数据系统中的存储层,Tachyon为用户提供了不同的启动模式、对资源管理框架的支持、以及目标运行环境,能够部署多种大数据平台环境中:
Tachyon里文件的组织方式,首先介绍Worker上的组织方式,Worker有两种文件系统,一种是Ramdisk,即内存文件系统;另一种是底层文件系统,最常用的是HDFS。在内存文件系统里面,文件是以Block的方式存储的。在底层文件系统上以整个文件的方式存储的。在内存文件系统上文件名是BlockID,而在底层文件系统里文件名是FileID。Tachyon的元数据的组织,大家可以看到这是一个树状的结构,每个节点都是一个Inode,Inode记录了文件的信息,所有的文件都从根节点开始的,根据路径的名字可以一步一步的找到。如果Inode代表一个目录,它会记录自己目录里面所有的子目录和文件,如果Inode代表一个文件,它会记录这个文件所有的Block,以及这个文件是不是在底层文件系统上有一个备份,以及备份的文件在的路径。
Tachyon的层次化存储充分利用了每个Tachyon Worker上的本地存储资源,将Tachyon中的数据块按不同热度存放在了不同的存储层中。目前Tachyon所使用的本地存储资源包括MEM(Memory,内存)、SSD(Solid State Drives,固态硬盘)和HDD(Hard Disk Drives,磁盘)。在Tachyon Worker中,每一类存储资源被视作一层(Storage Tier),每一层又可以由多个目录(Storage Directory)组成,并且用户可以设置每个存储目录的容量。
在读写Tachyon数据时,分配器(Allocator)负责为新的数据块选择目标存储目录,替换器(Evictor)负责将冷数据从内存剔至SSD和HDD,同时将热数据从SSD和HDD提升至内存中。目前分配器所使用的分配策略包括Greedy、MaxFree和RoundRobin。替换器所使用的替换策略包括Greedy、LRU/PartialLRU、LRFU。额外地,Tachyon还为用户提供了Pin功能,支持用户将所需要的数据始终存放在内存中。关于如何配置Tachyon层次化存储,可以进一步参考Tachyon官方文档。
3、灵活的读写机制
为了充分利用多层次的存储资源和底层存储系统,Tachyon为用户提供了不同的读写类型(ReadType/WriteType)API,用于灵活控制读写数据时的行为方式,不同的读写类型及其含义如表1所示
除了上述的读写类型外,Tachyon还提供了另一套控制方式:TachyonStorageType和UnderStorageType,用于分别控制在Tachyon存储和底层存储系统上的读写行为,具体取值及其含义如表2所示。实际上,这种控制方式是Tachyon-0.8之后新增的,控制粒度更细,功能也更多,因此推荐用户采用这种方式控制读写行为。
4、文件系统的容错机制
Tachyon的数据容错有两种:(1)元数据容错,就是Master节点上的数据容错;(2)内存数据容错,就是Worker上的数据容错。元数据的容错和HDFS是很像的,通过日志实现的。Image存储了元数据,Editlog记录了最近对元数据的修改记录。而内存数据容错是Tachyon的特有的,例如:Fileset A通过一个Spark Job生成了Fileset B,Fileset C通过另一个Spark Job生成了Fileset D,同时File set C和File set D又通过一个Mapreduce Job生成了Fileset E,这样一个数据生成的过程会在Tachyon中被保存下来,如果Fileset E丢失了,而Fileset B和Fileset D都存在,那么Tachyon就会重启Mapreduce job通过Fileset B和Fileset D重新生成Fileset E,如果Fileset B和Fileset E也都不存在了,那么Tachyon就会重新起用Spark Job生成 FilesetB 和 Fileset D, 最后再启动Mapreduce Job由FilesetB和Fileset D生成Fileset E。
5、HDFS兼容接口
6、WebUI管理界面
综上所述:
现在回顾一下我之前讲的现有的基于内存的计算框架所面临的三个问题,在有了Tachyon之后这个问题是怎么得到解决的?数据共享问题,Spark和Hadoop可以通过Tachyon去存储中间结果数据,如果MapReduce需要Spark的输出结果,可以直接读取Tachyon获得,而不需要访问HDFS。缓存数据丢失的问题,Spark可以将RDD缓存在Tachyon中,这样当Spark的应用Crash的时候这些缓存的数据是不会丢失的。第三个是GC的开销,这个显而易见的,由于数据在Tachyon中,GC不会管理这部分数据。
Tachyon怎么和现有的大数据处理框架集成的呢?首先是Mapreduce,MapReduce是没有和Tachyon做任何集成的,如果要在MapReduce里面使用Tachyon的话,就要把Tachyon当做外来的包或者是库来引用。第一种方法是把Tachyon的jar包放在Hadoop的Class path里面,第二种是放在Hadoop的Lib的目录里,第三种是作为应用程序的一部分,分发出去。另外还需要对Hadoop做一些配置,需要配置Tachyon文件系统,这样MapReduce就可以直接通过Tachyon加载和写入数据,使用方法和HDFS一样。Spark已经集成了Tachyon,如果在Spark中间使用Tachyon的话,只需要对Spark做一些简单的配置就可以了,在SparkConf里面配置Tachyon Master的URI,这样Spark就可以把所有的RDD的数据缓存在Tachyon中,通过设置RDD的Storagelevel为OFF_HEAP,Spark就会自动的把RDD放在Tachyon里面。如果Spark要通过Tachyon去加载和写入数据的话,就需要在像在Mapreduce中一样配置Tachyon的文件系统,这样的话Spark就可以像读写HDFS一样从Tachyon里面去读写数据。
1、Tachyon官网
2、《SPARK/TACHYON:基于内存的分布式存储系统》-史鸣飞(英特尔亚太研发有限公司大数据软件部工程师)
3、Tachyon--以内存为核心的开源分布式存储系统