现在的场景是,在创建完对象后会产生一个二进制文件,相当于有多少对象就会有多少个二进制文件,二进制文件存储在云端,前端要根据这个二进制文件来进行模型的渲染,在删除对象的时候,会把云端的二进制文件同步进行删除,同时释放用户的存储空间。
现在是如果对象比较多的情况下,比如有一千个对象,那么相当于云端存储着一千个这样的二进制文件,那么从前端向云端对象存储获取数据的话相当于需要获取一千次才能拿到完整的数据,前端同事觉得请求会特别多。
然后领导就提了个这样的需求,他希望把所有对象产生的二进制文件放在一个二进制文件中,这个情况如果不涉及到删除倒还好说,但是涉及到删除的话,应该是没有办法删除二进制文件中的一个片段吧?包括后续继续创建对象,要把这个对象产生的数据追加到这个总的二进制文件中,那么在删除某个对象的时候岂不是要是别出这个对象在这个总的二进制文件中的位置,然后重写一份总的二进制文件把除了那个要删除的对象以外的所有数据都写进来,同时每个对象还需要一些额外的属性用来标识它们在二进制文件中的位置,在产生新的文件后,还要把后续所有对象的这个属性都修改为新的位置。如果被删除的对象所处位置在总二进制文件的前面,那相当于对几乎所有对象都要进行修改。
我目前觉得这个需求有点难搞,从我的视角来看,带来的问题远比能解决的问题多得多,甚至并不能解决原有的问题,对此想请教下各位大佬,对于这种情况各位有什么看法,可以分别从前端视角和后端视角给一些看法和建议。
1
NessajCN 2023-11-15 09:19:24 +08:00
你得先说一下用什么库或方法创建的这些文件
|
2
Nitroethane 2023-11-15 09:25:54 +08:00 1
感觉你这个是伪需求啊?「现在是如果对象比较多的情况下,比如有一千个对象,那么相当于云端存储着一千个这样的二进制文件,那么从前端向云端对象存储获取数据的话相当于需要获取一千次才能拿到完整的数据,前端同事觉得请求会特别多」:把你的接口改造成允许一个请求获取多个二进制文件呢?比如你的接口里 file_id 指定要下载的二进制文件的 ID ,把 file_id 改成数组类型,即一次可以指定多个文件 ID ,这样就可以实现批量下载,而且请求也不会很多。
|
3
Chad0000 2023-11-15 09:29:26 +08:00
把所有对象产生的二进制文件放在一个二进制文件中。
Sqlite ? |
4
paopjian 2023-11-15 09:38:28 +08:00 1
还奇怪的需求啊,为什么要请求一千次,打包一次返回来不就好了?而且你们也太耿直了,点删除就删除文件了?有要求把所有数据保存半年的.
|
5
cxtrinityy 2023-11-15 09:40:40 +08:00 via Android
关键是解决根本问题前端觉得请求过多,以前写过上传的代码,用 multipart/form-data 一次性上传多个文件,搜了下,multipart/related 好像能实现对应的一次性下载多个文件。
PS:当时用 httpurlconnection ,手撸的这个请求的 http 头和内容,感觉自由性挺高,应该不是特别难实现 |
6
tool2d 2023-11-15 09:41:15 +08:00 1
如果我是你,会另外写一个服务器大文件缓存通道,1000 个文件根据 hash 特性,合并成几个文件后给前端下载。
删除还是走原来的逻辑,不去动。 |
7
seers 2023-11-15 09:47:41 +08:00 via Android
oss 提供打包下载功能啊,你云端生成完了打包一个下过来
|
9
AboPlus OP @Nitroethane 目前前端是直接发请求到存储桶拿数据,目前没有经过后端服务,我考虑下走接口
|
10
AboPlus OP @paopjian !!!好的大哥,我们这边后端就四个人,目前没有大佬,好多想法思考的都不太成熟,好多好的方案都是从 V 站上请教来的
|
12
paopjian 2023-11-15 11:06:55 +08:00 1
前端对于大量小图标有雪碧图 处理,图片合到一个大图片里, 你们可以有一个后台代码逻辑把常用的文件打包到一起,如果前端有删除操作,那先在前端略过处理,服务器再定期重新打包.
用户的存储使用容量不应该是和文件大小强绑定的,而应该是和逻辑绑定,并且允许一定超量 |
13
jones2000 2023-11-15 11:08:42 +08:00 1
参考 sqlite , 所有数据都是存一个文件里面。
|
14
sofukwird 2023-11-15 11:12:41 +08:00 via Android
文件索引保存在数据库里,然后只给前端返回文件索引
你这是个 xy 问题,最好把实际需求说出来 |
15
sofukwird 2023-11-15 11:16:13 +08:00 via Android 1
看漏了,原来是模型文件,打包到一个文件里是正确的需求
增删改的时候重新生成一个文件就好 |
16
sofukwird 2023-11-15 11:17:20 +08:00 via Android
二进制文件就用压缩包,压缩包是可以删除文件的
|
17
tool2d 2023-11-15 11:28:10 +08:00
md5("filename1.bin + filename2.bin + filename3.bin") = e676e2aa0a8ebd318835b01ee4b5d21e.bin
md5("filename1.bin + filename3.bin") = b02959106f2595f908b13eacf582ebab.bin "大佬请教下,合并后的文件涉及到删除的时候不还是需要对合并后的文件进行处理吗,把被删除的数据移除掉" 我个人来说用 md5 作为合并文件名,就不涉及部分删除。因为只要小文件变动了,前端下载访问的 url 都不一样。 如果大文件长时间没人访问,会自己清空数据。 |
18
chnwillliu 2023-11-15 11:28:54 +08:00 via Android
好比一个 PSD 文件,里面包含多个图层,每个图层有自己的像素信息,前端增删改,保存后它就是一个 PSD 二进制文件啊。
所以你只需要设计一个二进制文件格式,定义好结构 |
19
InDom 2023-11-15 11:34:02 +08:00 1
假设文件是 1...100 个文件,
前端请求一个就是 file/1 如果获取特定 10 个文件,files/1,2,3,4,5,6,10,11,15,20... 后段根据请求合并这些文件,作为一个返回给前端,如果会重复就以 hash 缓存 |
20
chnwillliu 2023-11-15 11:39:40 +08:00 via Android 1
最简单的就是直接把包含所有模型的文件夹 zip 成一个文件,前端发一个请求然后用 in-memory 的 file system 直接 unzip 成 folder, 操作完了要写回去就再 zip 回去。
不知道你这 1000 多个模型,一共有多大。 |
21
0TSH60F7J2rVkg8t 2023-11-15 11:44:15 +08:00 1
有云端对象存储,就不要合并一个 bin 文件啊,一个文件,你修改删除全是问题,怎么恢复合并又是问题。实际上,你只需要在数据库里保留所有二进制文件的云端位置,和文件信息,读取的时候从数据库拉,删除的时候,数据库软删除,前端不操作对象存储,服务器跑个定时任务,把软删除的数据库条目读出来,去云端对象存储里删除释放空间 就行了。
|
22
okakuyang 2023-11-15 13:26:09 +08:00 1
建议同一项目的模型文件用 zip 压缩成一个或者多个。
估计你单个模型体积挺小的,这时候要考虑到云端存储规则有没有隐形一条,最小文件实体的大小。比如你单个文件体积小于 2.5MB ,但是云存储依旧按照 2.5MB 收费。 如果没有立即删除文件的需求的可以只在数据库里标记删除。 前端获取文件的时候用分片下载,虽然逻辑会写的麻烦一点,但是能够有效减少云存储的访问次数,可以省点钱。 |
23
hanyu2pomelo 2023-11-15 13:28:56 +08:00
用 mmap 可以解决吧
|
24
AboPlus OP @sofukwird 直接操作压缩包,删除压缩包内的文件吗?好像是个好方法,那么剩下的就是解决如何处理云端压缩包中的文件的问题了!谢谢大佬!
|
25
AboPlus OP @tool2d 意思是存在两份数据,一份数据是一个个的小文件,一份数据是将小文件合并后的大文件,是这个意思吗,然后任何一个小文件变动,都是需要重新 md5 出来一份新的大文件,是这样吗
|
26
AboPlus OP @chnwillliu 数据量不太好估计,因为可能不止 1000 个模型
|
27
aecra 2023-11-15 14:09:07 +08:00 via Android
请求多没啥问题,开 HTTP2 就看带宽多大了,你这修改一下就改大文件是因为带宽比请求数量廉价吗?小文件还能使用缓存呢
|