文件流和文件访问冲突的问题

为轮子而生 2015-03-09 09:49:14
在做一个云计算项目,数据文件很大也很多,每个有几十M(通常有上千个文件),所以不可能将数据放到内存里。服务器在进行运算的时候使用FileStream对数据文件进行读写,这样的话过程倒是很顺利,但还涉及到多客户端数据获取的问题:
客户端每次会请求获取指定的文件数据,而且不一定是什么时间,他们如果直接下载文件,会造成访问冲突,因为服务器正在用文件流控制数据文件;如果服务器直接用Socket将数据传给客户端,又有可能影响正在进行的读写工作(因为对于客户端请求的数据,服务器也要通过文件流获取)。
请问有什么方案可以既不影响服务器对文件的读写,又可以同时让多个客户端获取到数据呢?
...全文
247 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
应该发生“重复使用 FileStream --> 应该测试到绝不回发生“重复使用 FileStream
  • 打赏
  • 举报
回复
引用 4 楼 tcmakebest 的回复:
客户端只是读取数据的话,用下面的方式打开文件,应该可以打开被其他程序正在操作的文件: FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
其实当有多个客户端都需要读同一个文件时,如果只有一个FileStream,大致并不会降低什么性能。因为读过的内容就放到Cache了,应该发生“重复使用 FileStream 去做缓慢的事情”的现象。而不同文件是并发的不同 FileStream。
  • 打赏
  • 举报
回复
也就是说,如果有点闲钱,不要在windows传统的磁盘文件系统上埋头“研究”。找几种时髦的文件系统或者数据库产品,试试看能不能用来管理你们的这一堆文件。
  • 打赏
  • 举报
回复
引用 10 楼 rocmemory 的回复:
[quote=引用 9 楼 Z65443344 的回复:] 为什么不用数据库,而是自己弄好多好多文件?
因为这个计算项目涉及多层次的矢量数据,用数据库完全满足不了,我们的算法不需要对数据进行检索,是直接以序列方式进行定位的。还是很感谢你的回复[/quote] 数据库其实是个好的概念!但是这个“数据库”不应该是传统的关系数据库。 实际上把一个文件迅速打散成一堆chunk进行管理,然后用一定的数据结构,实现你的大块数据的操作,这会比windows磁盘系统的效率高许多倍。有许多开源的高速缓存文件系统,你就可以说它是数据库跟文件系统的综合体。作为文件,它可以以流的方式随机存取了;但是它如果自动分布式集群存储、自动进行版本管理(每一次修改仅需要合并一小部分内容)、自动按照比文件系统更复杂的数据结构而存储,自动容错(例如当Master服务器宕机时),自动给你按照散列值建立索引,自动进行多点备份,等等,看上去又是非常高级的“库”。
为轮子而生 2015-03-10
  • 打赏
  • 举报
回复
引用 9 楼 Z65443344 的回复:
为什么不用数据库,而是自己弄好多好多文件?
因为这个计算项目涉及多层次的矢量数据,用数据库完全满足不了,我们的算法不需要对数据进行检索,是直接以序列方式进行定位的。还是很感谢你的回复
於黾 2015-03-10
  • 打赏
  • 举报
回复
为什么不用数据库,而是自己弄好多好多文件?
为轮子而生 2015-03-10
  • 打赏
  • 举报
回复
引用 3 楼 sp1234 的回复:
嗯,更正一下。chunk数据是放在缓存系统中,而FileStream放到“池”中而不是缓存里。所谓池,它其实就是一个简单的Dictionary<string, MyFileStream> 集合,用来查找每一个文件对应的 FileStream,并且可以定期(例如当内存不足时)清理那些超过(比如说)5分钟都没有访问过的记录。
一个文件可以被多个FileStream同时打开并进行操作吗? 能否给一些简单的代码示例? 我做的是WinForm应用程序 我的服务器程序使用filestream打开一个文件后,客户端再对这个文件进行下载时就会发生资源错误的问题,直到这个stream被close。我想知道有什么办法既不用让服务器程序Close这个文件流,又能让客户端进行下载呢?
为轮子而生 2015-03-10
  • 打赏
  • 举报
回复
但是我的服务器程序使用filestream打开一个文件后,客户端再对这个文件进行下载时就会发生资源错误的问题,直到这个stream被close
tcmakebest 2015-03-09
  • 打赏
  • 举报
回复
客户端只是读取数据的话,用下面的方式打开文件,应该可以打开被其他程序正在操作的文件: FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
  • 打赏
  • 举报
回复
嗯,更正一下。chunk数据是放在缓存系统中,而FileStream放到“池”中而不是缓存里。所谓池,它其实就是一个简单的Dictionary<string, MyFileStream> 集合,用来查找每一个文件对应的 FileStream,并且可以定期(例如当内存不足时)清理那些超过(比如说)5分钟都没有访问过的记录。
  • 打赏
  • 举报
回复
当客户端要下载文件某个磁盘块时,它首先要在缓冲里找chunk数据,如果有就直接返回了。然后它要在缓冲里找FileStream对象,如果找到就用这个对象lock加锁(与其它线程同步),然后读取自己需要读取的chunk数据(读取完毕不要关闭FileStream),然后将数据放到缓存里,然后输出给客户端。如果找不到FileSteam对象,那么就创建一个(如果出错,可能需要重试20次),然后放入缓存系统,然后对其lock之后读取chunk数据、缓存、并输出,同样也不关闭FileStream。 总之,在服务器端,同一个文件的读写使用的FileStream只能有一个,放到Cache中供服务器进程的各个线程共用。
  • 打赏
  • 举报
回复
首先,客户端读取文件(的某个磁盘块),它不是什么“使用FileStream对数据文件进行读写”,而是访问服务器上的服务——或者至少是一个重写了的Stream——去读写。因此即使有1000个客户端并发读取同一个文件,在服务器端也自有一个“池子”中的一个FileSteam被调用。 其次,当客户端需要读取某个磁盘块的时候(我们可以规定每一个chunk的大小都是一样的,或者一个磁盘块必须是固定大小的chunck的组合),服务器可以先查询一下Cache里边是不是已经有这些chucnk的数据了。如果有了,那就不需要读取文件了。另外这些“chunk的缓存单元”依赖于文件,当设置缓存依赖项的具体文件被修改时则自动被清除。

110,571

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧