架构设计问题

来源:2-6 编码实战:实现文件下载接口

奥特之星

2019-06-18

有三个问题想请教老师:

一 在加入对象存储后,为什么还要先上传到服务所在硬盘,再转移到对象存储?
我能想到的是可能是考虑服务解耦,这样TransferService可以有,也可以没有。
但是上传到本机硬盘这个操作会使服务有状态化,当有多个UploadService时,还要引入NFS/NAS等共享存储来解决,那不如直接存储到对象存储?


然后下面都属于我头疼了很久很久的问题,垃圾文件删除呢?我个人认为它是网盘最重要最难的功能了?

二 上传文件废弃后的清理问题?
课程中这个项目名字虽然为仿百度云盘,但是很遗憾不包括文件系统(文件夹,文件,嵌套关系)的管理。我在设计中是希望文件系统独立为FileSystemService,跟UploadService分开。 这样json请求与文件请求做到服务划分。前端首先向UploadService上传文件,文件成功后拿着文件id去向FileSystemService添加文件。

1 这里引入了问题就是如果前端只发了上传文件请求,没有添加文件请求,那这个时候这个文件成了垃圾文件。怎么去删?我能想出很多很多种设计,在redis创建个上传任务来管理?又或在两个Services前面加个SuperFileSystemService来调用2个服务,这样又不能把json与文件请求分离了?所以想听老师的解决办法是什么?

2 问题,回到课程中,项目里mpupload会引入上传废弃文件的情况,这个的清理应该需要写一个长驻或定期运行的脚本,来扫描这个上传目录,删除大于7天还在的文件吧?

三 用户删除文件后的清理问题?
课程依然回避了这个最难的问题,不管是有没有文件系统的网盘系统,用户在删除自己文件后,因为对象存储中的文件与用户数据表中引用是1对n的关系,当n=0时,如何删除对象存储中的文件?在唯一hash表(tbl_file)中做引用计数吗?再写一个长驻或定期运行的脚本,来扫描这个tbl_file,删除引用计数为0的文件?计数很难,一处逻辑做不好计数就乱了。但总比扫描用户文件表hash做减法要快吧? 所以想听老师的解决办法是什么?


千言万语汇成一句话,是不是像百度网盘、115网盘或者其它公司,都不做原始文件删除的啊?这样存储根本顶不住啊?

写回答

4回答

xiaomo

2019-06-19

3)文件计数的确很容易出问题,按我经验暂时还没接触过会对每个文件进行计数的网盘项目,海量文件下做这个引用计数感觉有些得不偿失。用户发起的文件删除请求,一般都是先做标记删除;只有确认是用户独有的文件才可能会进行物理删除。另外可能会涉及到产品业务一些逻辑,比如网盘有这么一个服务是支持文件独立存储的,也就是用户与其他用户的文件是隔离存储的,那么里面的文件就可以按用户请求来删除。

所以汇总来讲,很少会有删除文件的场景。另外业务层面上讲,不怎么用的文件,或者是以后基本都不会用到的文件,可以使用廉价方式来进行存储,而不是首先就考虑删除。比如阿里oss或aws s3,也是分级的,有标准存储,也有归档存储(成本低,但是读取效率低)。

2
1
奥特之星
遗憾不能同时采纳三个回答,谢谢老师耐心解答,解开了许久的困惑。
2019-06-19
共1条回复

xiaomo

2019-06-19

另外一般需要考虑删除文件的场景,可能是一些存储容量比较小的私有云存储,可能能存几百万个文件?这种级别的场景,定期(比如每天凌晨跑一次)扫描一遍文件表和用户文件表找出垃圾文件然后进行删除,应该也不会太花时间。没必要用到文件计数,直接现算,按理也是可行的。

最后,我认为网盘更重要的功能是保证用户文件不丢失,而不是删除文件降低存储成本呢。

2
0

xiaomo

2019-06-19

2)按你说的FileSystemService和UploadService,其实FileSystemService就相当于客户端直传ceph或oss吧(不知道是不是和第八章最后讲到直传oss类似,可以参考一下,上传调度和上传传输分开)。如果上传了文件,但是没有将文件关联到用户表中,确实会产生无用文件。一般可以在申请上传的时候就会记录一条状态,比如可以写到rabbitmq中,然后通过异步的任务定期检查这些状态,是否已经完成关联操作了。如果超过一定时间,可以选择去删除已上传的文件。

但是也有不这么做的理由,理论上这种几率不大,所以允许保留这么一部分文件;另外可能也有其他用户会上传到相同的文件,那么原有的无用文件也就可以进行关联操作了。另外因为有临时存储的概念,如果没有进行用户关联的文件,是不会转入最终的对象存储的,而会在临时存储里就因为关联超时而被删除。

另外,据以往经验网盘一般不会删除原始文件,除非是一些敏感文件。像经历过的百PB级文件存储,要删除的文件比例实在微乎其微。

1
0

xiaomo

2019-06-19

同学你好,

1) 的确是这样,传输节点应该是无状态的。临时存储的作用主要一个是为了快速响应用户上传,不需要等待二次传输;一个是用户文件冲突问题,可能多个用户同时上传同一个文件,这个时候是需要支持每个用户的文件都上传完成的,最后再决定将哪个文件写入最终存储。

一般生产环境,应该用局域网内的分布式存储作为临时存储,比如在与上传节点同一个网络内搭建一个ceph集群,文件先写ceph, 后面再写到公有云。

因为临时存储的存储规模一般不会很大,所以需要定时清理文件(转移完成的就可删除),腾出空间。

如果是直接写最终的对象存储,比如oss, 那建议是客户端直接写oss, 然后客户端/oss/我们的后台三方进行数据同步。

1
0

Go实战仿百度云盘-实现企业级分布式云存储系统

紧随“云时代”技术潮流,分布式云存储系统,做第一代云程序员

1077 学习 · 494 问题

查看课程