内容简介:TaoCloud团队原创:随着新技术的持续发展,全球数据量将继续高速增长,据分析机构预测,中国数据量增长最为迅速,预计到2025年将增加到48.6ZB。其中视频监控是数据增长的重要推动因素之一,为了支持大规模的视频监控与分析,对于存储系统来说,提出了新的要求和挑战。由于数据规模的不断增大,相比于传统存储而言,分布式存储的地位显得越来越重要。GlusterFS是一个开源的分布式文件系统,它是一个自由软件。与其他分布式文件系统(如Ceph、HDFS、FastDFS等)相比,GlusterFS具有独特的设计,例如
TaoCloud团队原创: http://www.taocloudx.com/index.php?a=shows&catid=4&id=113
随着新技术的持续发展,全球数据量将继续高速增长,据分析机构预测,中国数据量增长最为迅速,预计到2025年将增加到48.6ZB。其中视频监控是数据增长的重要推动因素之一,为了支持大规模的视频监控与分析,对于存储系统来说,提出了新的要求和挑战。由于数据规模的不断增大,相比于传统存储而言,分布式存储的地位显得越来越重要。
问题引入
GlusterFS是一个开源的分布式文件系统,它是一个自由软件。与其他分布式文件系统(如Ceph、HDFS、FastDFS等)相比,GlusterFS具有独特的设计,例如无元数据中心、用户态堆栈式设计、全局统一命名空间等,具有强大的横向扩展能力、良好的可靠性和出色的性能,可广泛应用于各类非结构化数据的存储与共享环境,例如流媒体、数据分析以及其他数据和带宽密集
型业务。
然而,在实际环境测试时,我们发现开源的GlusterFS在某种视频监控应用场景下表现的并不是十分出色,当然GlusterFS的这种表现是和具体应用相关的。测试的场景如下:
业务系统的多个应用服务器访问同一个GlusterFS存储集群,每个应用服务器上运行一套应用软件,应用软件与GlusterFS存储相关的模块主要有两个,一个负责写(单线程),另一个负责读(单线程)。每个应用服务器写入存储的文件数量与其连接的摄像头数量相关,具体是一个摄像头对应两个文件,一个视频数据文件,一个帧文件,数据文件大小为1GB左右,帧文件为几KB,例如一台应用服务器连接100个摄像头,则写线程要处理200个文件。每30分钟,会有一台或几台应用进行文件切换动作,所谓文件切换就是关闭其正在写入的所有文件,然后打开同样数量的新文件,再继续进行数据写入。文件切换动作只由写线程处理,在此期间,没有进行文件切换的应用服务器仍然向存储写入数据。
使用开源GlusterFS构建一个基于EC的GlusterFS文件系统,采用POSIX访问协议,在上述场景下测试遇到如下情况:向存储中写入和读取数据性能良好,只是应用软件在进行文件切换动作时的时延较高(相对于应用软件要求标准),从而导致应用软件的自身任务(写请求)积压较多,给用户的体验不好,并且存在丢失数据的风险。
问题分析与方案提出
对于存储系统性能而言,一般可以通过throughput、IOPS和latency三个指标来衡量。对于上述测试情况,GlusterFS文件系统的读写性能可以较好的满足应用程序,但是在关闭和创建文件这些元数据操作上时延较高,即主要体现在latency指标方面。
在经过充分测试和仔细分析后,我们发现其影响因素是两方面的,一方面应用软件使用单线程执行文件切换操作,并且关闭旧文件与打开新文件是顺序执行的,并发度较低,这是应用软件整体时延较大的原因之一。
另一方面,对于GlusterFS来说,有如下几方面影响因素:
(1)无元数据中心架构,导致不擅长处理创建和关闭文件等元数据操作。
(2)Fuse-bridge模块处理文件查找的机制,会触发多次的GlusterFS内部通信。
(3)EC卷模式,客户端应用的一个文件请求通过一个EC模块会被分为多个请求(具体与配置的冗余度相关),分别发送到一个EC子卷对应的每个brick服务进程,并在所有应答都返回到EC模进行聚合后,才会返回应答给客户端应用,相比没有冗余的哈希卷增大了应用访问时延。
(4)GlusterFS内部的锁机制,io-threads、EC、RPC通信等模块中存在一定程度的锁竞争情况。
(5)基于POSIX协议的数据访问路径较长,对于创建文件请求没有缓存可用,需要真正发送到存储节点brick上,并在处理完成后返回。
(6)GlusterFS的posix模块处理创建文件请求时的额外操作较多,例如多次stat调用、设置扩展属性、设置属主属组、设置acl、创建硬链接、可能还需要创建二级目录等。
总结一下,以上两方面共同作用,导致应用程序文件切换的时延较高,然而从应用程序方面优化往往是不现实的,因此,需要从GlusterFS存储方面寻找解决方案。
针对上述应用场景和影响因素分析,在应用软件不做调整的情况下,为了满足应用软件的时延要求,基于目前GlusterFS的系统架构和工作原理,综合考虑优化工作的有效性和复杂性,我们提出了GlusterFS文件预分配方案。
文件预分配方案的思路是在每个GlusterFS客户端程序内部维护一定数量的预先创建的文件,当应用程序打开新文件时,使用预先创建的文件信息应答应用程序,并在GlusterFS客户端程序内部记录实际文件与预先创建的文件之间的对应关系,这样以来应用打开新文件(时延主要因素)不受GlusterFS内部锁竞争、数据访问路径较长、通信网络状况和存储端磁盘繁忙状况这些因素的影响,时延会非常低,从而大大降低了应用进行文件切换动作的总时延。
文件预分配方案架构
首先看下原生GlusterFS的总体(外部)架构和内部架构,然后给出引入文件预分配后的内部架构(外部架构与原生GlusterFS相同),通过两者比较,更加有助于理解GlusterFS文件预分配方案。
GlusterFS总体架构如图4所示,主要由存储服务器(GlusterFS Brick)、客户端(GlusterFS Client)和存储网关(NFS/Samba以及API)构成。该架构中没有元数据服务组件,采用完全对等的设计,对其强大扩展能力和出色的性能有重要意义。
-
存储服务器
存储服务器主要提供基本的数据存储功能,其上运行的glusterfsd进程负责处理来自其他组件的数据请求。最终的文件数据通过统一的调度策略分布在不同的存储服务器上,数据以原始格式直接存储在服务器的本地文件系统上,如EXT4、XFS和ZFS等。
-
客户端
由于没有元数据服务器,GlusterFS将更多的功能放到了客户端,包括数据卷管理、I/O调度、文件定位、数据缓存等功能。客户端上运行glusterfs进程,它实际是glusterfsd的符号链接,只是运行的同一程序的不同代码逻辑,利用FUSE模块将GlusterFS文件系统挂载到本地文件系统之上,实现POSIX兼容的方式来访问存储服务器上的数据。
-
存储网关
即NAS网关,利用GlusterFS提供的API访问存储服务器。对于没有运行GlusterFS原生客户端的客户应用,可以基于NFS/CIFS标准协议,通过存储网关访问存储服务器上数据。
如图5所示,GlusterFS内部软件架构是模块化堆栈式设计。模块称为translator,是GlusterFS提供的一种强大机制,借助这种良好定义的接口可以高效简便地扩展文件系统的功能。每个translator都是一个动态库,运行时根据配置动态加载。每个模块实现特定基本功能,GlusterFS中所有的功能都是通过translator实现,比如I/O Cache、read ahead、write behind、distribute(DHT)、disperse(EC)、client、server和posix等。
客户端和存储服务器均有自己的存储软件栈(由一些translator组成),整体上构成了一棵translator功能树。模块化和堆栈式的架构设计,极大降低了系统设计复杂性,简化了系统的实现、升级以及系统维护。
基于上述对GlusterFS总体架构和内部软件架构的介绍,再来看引入文件预分配后的GlusterFS内部软件架构(如图6),则比较容易理解其实现原理,主要是增加了一个预分配(pre-allocation)模块。
文件预分配功能主要是通过在GlusterFS原生客户端软件堆栈中新增加一个预分配模块来实现。具体位置在meta模块(位于客户端堆栈的顶端,是fuse-bridge模块之下的第一个模块,客户端初始化时自动加载)之下,客户端挂载时可以选择加载与否。在预分配模块中,通过预先创建文件并维护其相关信息,以及维护与应用实际要创建的文件之间的对应关系,来加速应用程序创建文件,从而降低其文件切换时延。
实现剖析
首先概括介绍文件预分配实现总体实现,然后介绍引入文件预分配后的数据访问路径,其次说明几个主要场景的处理过程,最后进行简要总结。
-
预分配模块组成部分
GlusterFS文件预分配功能主要由预分配模块实现,预分配模块位于GlusterFS客户端堆栈。该模块遵循GlusterFS模块的实现模板,主要实现了lookup、create、open、writev、flush、fstat、fsetattr、fsetxattr、fgetxattr、fm_setxattr、fsync等接口,同时创建了两个线程,create线程和rename线程,分别用于实现文件预先创建和文件重命名功能。
预分配模块的内部维护3个双向链表,new链表、inuse链表和purge链表,依次保存预先创建且未被使用的文件信息、预先创建且已使用(与应用实际文件存在对应关系)的文件信息和已使用并且数据写入完成的文件信息(需要重命名的文件)。另外,预分配模块在客户端创建一个数据库,用于持久化保存预分配的文件信息和文件映射关系信息,也便于异常情况的处理。如图7所示,凸显了预分配模块的主要组成部分。
-
文件预分配数据访问路径
一次完整的数据访问流程如下:
1) 应用程序发出文件请求到客户端的VFS层。
2) 客户端的VFS层通过FUSE转发请求到GlusterFS客户端进程。
3) GlusterFS客户端进程收到请求后,从fuse-bridge模块开始,依次经过客户端堆栈所有已经加载的模块(包括预分配模块),如果预分配模块检测到当前是创建文件请求,则在处理请求后直接返回应答,不再向下层转发请求;否则最后经过client模块,然后通过网络通信发送到存储服务端。
4) GlusterFS服务端进程收到请求后,从server模块开始,依次经过服务端堆栈所有已经加载的模块,最后到posix模块,然后通过C库函数或系统调用发送到服务端VFS层。
5) 服务端VFS层收到请求后,发送给具体底层文件系统进行处理,处理之后,应答信息按照原路径返回到应用程序,至此一次客户端请求结束。
-
客户端进程初始化场景
1) 客户端使用mount命令挂载GlusterFS存储。
2) GlusterFS客户端进程启动并加载所有模块,包括预分配模块,并与GlusterFS存储端进程交互,完成初始化工作。
3) 预分配模块初始化时创建create线程和rename线程,在init函数中初始化本地数据库。在等待客户端进程初始化完成后(fuse_first_lookup函数返回),create线程创建一定数量的文件,并进入睡眠状态,等待唤醒。在客户端进程初始化完成后,rename线程同样也进入睡眠状态,等待唤醒。
4) 客户端进程准备就绪,等待处理应用程序请求。
-
文件预创建场景
本方案有两个时机会触发create线程进行文件预创建,一个是在客户端进程初始化时,另一个是当预先创建的文件已经使用了阈值的70%时。一般处理流程如下:
1) Create线程构造文件创建的请求,通过GlusterFS的同步创建文件接口(syncop_create)向预分配模块的下一层发送请求。
2) 该文件创建请求传输到GlusterFS服务端,并得到处理后返回应答。
3) Create线程收到创建文件应答,然后在内存中记录下该文件相关信息。
4) 将新创建的文件信息保存到到new链表,同时保存到数据库进行持久化。
5) 重复执行步骤1)到4),直到创建的文件达到阈值,然后create线程进入睡眠状态并等待唤醒。
-
处理应用请求场景
1) 客户端进程在fuse-bridge模块接收到应用请求,对其进行解析,并发往下一层。
2) 在预分配模块接收到上层请求,根据具体请求类型,进行相关处理,或者直接发往下一层;当需要具体处理时(如create请求),则从new链表中找到一个预分配文件,将其信息返回给应用程序,同时记录并持久化该预分配文件与实际文件的对应关系,并将该预分配文件从new链表转移到inuse链表。如果预创建的文件达到阈值的70%,则需要通知create线程进行相应的处理。
3) create线程收到通知后,执行具体操作(create),操作完成后继续进入睡眠,等待下次唤醒。
4) 客户端进程在fuse-bridge模块接收到服务端或者预分配模块的应答后,将请求的执行结果返回给应用程序。
5) 客户端进程继续等待处理应用程序请求。
-
文件重命名场景
1) 预分配模块接收到上层create请求,计算相邻两次create请求之间的时间间隔,如果间隔时间超过重命名时间间隔阈值,则将所有已经使用的预先创建文件移动到purge链表,并通知rename线程进行处理。
2) Rename线程遍历purge链表,将其中的每一个预分配的文件进行重命名。
3) 对每一个文件重命名后,rename线程同时将其在数据库中的记录删掉。
4) 处理完链表中的所有文件后,rename线程进入睡眠状态并等待唤醒。
-
客户端进程退出场景
1) 客户端卸载(umount)GlusterFS存储。
2) 客户端进程进入退出流程处理,从fuse-bridge模块开始到client模块,依次调用本层的退出清理函数,释放申请的资源,其中预分配模块负责通知create线程和rename线程退出。
3) 重命名线程关闭与数据库的连接,释放数据库相关资源。
4) 所有客户端模块处理完后,客户端进程调用exit退出进程。
方案验证
使用视频监控模拟程序进行测试,在同等环境下测试多次,开源GlusterFS和本文方案实际测试300个文件切换的时延对比结果如下:
小结
本文介绍的GlusterFS文件预分配方案,主要为了解决特定视频监控场景下的文件切换时延问题。从理论分析和实际测试结果上看,效果还是比较显著的。如果读者遇到类似的问题,不妨考虑一下本文的方案。
文件预分配方案能够大大降低本文所述场景下的文件切换时延,但也存在一定的要求和限制,要求是需要特别熟悉应用程序的访问模式,而限制则是一个客户端正在写入文件时,在另一个客户端访问不到该文件,直到该文件写入完成并被重命名后才能访问到,这也是下一步的优化方向。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 操作系统学习笔记-11:内存分配(一):连续分配
- 操作系统学习笔记-12:内存分配(二):非连续分配
- PHPKafka 1.1.1 发布,支持消费者分区分配策略之粘性分配等功能
- Go:内存管理分配
- 多机任务分配机制
- Allocations分析内存分配
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning ARKit for iPhone and iPad
Wallace Wang / Apress / 2018-11-5 / USD 39.99
Explore how to use ARKit to create iOS apps and learn the basics of augmented reality while diving into ARKit specific topics. This book reveals how augmented reality allows you to view the screen on ......一起来看看 《Beginning ARKit for iPhone and iPad》 这本书的介绍吧!