首先说一下是 Python 技术栈,现在需求是有大量的文件不断生成在一个目录下(文件几 k 到几百 k 不等,同期数量约 20W ),想做一个服务,使得其它服务来请求的时候能快速地取走该文件,并在取走后删除。
当然,最简单的做法就是 Tornado/Flask 直接写个接口,然后 os.remove 就行,想问下大伙儿还有什么高效率的方法来实现吗?
|  |      1gwy15      2020-06-29 20:27:02 +08:00 zero-copy (sendfile)? | 
|  |      2ipwx      2020-06-29 20:31:48 +08:00 redis | 
|      3optional      2020-06-29 20:49:25 +08:00 这样性能并不高啊,包括生成大量文件与删除。 删除是强需求吗,是一定只能取一次,还是过一段时间取不到就好? | 
|      4chenqh      2020-06-29 20:55:04 +08:00 流程没懂 | 
|  |      5Te11UA OP | 
|  |      9jugelizi      2020-06-29 22:01:07 +08:00 via iPhone 效率?嫌删除动作慢?改成异步任务呗 | 
|  |      10vevlins      2020-06-29 22:07:35 +08:00 不删除直接覆盖写?瞎说一下 | 
|  |      11netnr      2020-06-29 22:15:11 +08:00 重命名文件夹,mv folder folder.del 再删除 *.del 文件夹 | 
|      12makdon      2020-06-29 22:56:02 +08:00 要不换成 SSD ?如果是自己的物理服务器,可以搞 nvme 的,或者组个 raid,应该会更快 等等首先现在你的瓶颈在哪里...是定位到了线程池里面大部分线程都在等 os.remove 吗(个人感觉应该是读文件的成本远远高于删文件吧) 如果不是的话...不要提前优化 我想到的这些: 1. 如果业务上面可以实现的话,在请求到的时候再生成文件,不落硬盘直接发送 2. 按照文件名之类的唯一键,hash 到多台服务器上面处理 3. 只能单机的话,可以调研一下有没有适合这个场景的文件系统... | 
|      13billlee      2020-06-30 00:52:59 +08:00 别想太多,才 20 万文件而已,只要你不去遍历目录,现代文件系统处理起来不会有问题 | 
|  |      14realpg PRO 想要高性能,直接写个简单的文件系统。 计算机科班专业的大佬应该都会,如果上学时候做过相关的作业,估计两三天就能解决这个问题。 发生一次读取内容之后直接标记这个文件的区域释放。 | 
|  |      15realpg PRO 而且 20 万这个级别,一个文件不超过 1MB,这种存储的 IOPS 只要高一点,连瓶颈都不会发生啊…… 文件系统只要是个稍微现代点的文件系统即可。 不知道你那边用的啥服务器,基础架构层优化一下就完事了。 如果基础架构层没法优化,还想绕开删除慢这个坑,那就用完的改名,加前缀,然后当系统 io 不密集时进行限定写负载的删除 | 
|  |      16Vegetable      2020-06-30 01:34:39 +08:00 文件需要鉴权?一定要 python 来处理文件?有点蛇。其实直接 remove 并没有什么性能问题,同步 web 框架控制好流程就行,性能瓶颈不在删除这里。异步的话可以用 redis 之类的把取走的文件标记一下,定时删除就好了。 | 
|      170ZXYDDu796nVCFxq      2020-06-30 01:38:07 +08:00 via Android nginx 提供静态访问,瓶颈就是网络带宽 访问记录输出日志,Python 定时读取日志批量删除 | 
|  |      18SlipStupig      2020-06-30 02:05:34 +08:00 Redis 直接使用队列就好了啊。。 | 
|      19hurrytospring      2020-06-30 02:24:52 +08:00 不要求立即删的话搞个表标记一下删除就行了。。真正删除的时候再搞个定时任务拉表批量删掉完事 | 
|  |      21jedihy      2020-06-30 04:07:22 +08:00 via iPhone 19 楼的方案应该是最简单高效的了。 | 
|      22em70      2020-06-30 05:24:57 +08:00 瓶颈到底在哪里? 最简单方法先实现跑起来再谈优化啊 | 
|      23yemoluo      2020-06-30 08:18:49 +08:00 一种不知道可不可行的方案是使用 nginx-lua 中的 `log_by_lua` 在这个脚本文件里删除,我没试验过,不知道可不可行 | 
|      24dbolo123      2020-06-30 08:27:07 +08:00 via Android 直接 nginx 返回,每天跑个脚本分析是 access log,删掉文件就好? | 
|      25yaleyu      2020-06-30 09:00:27 +08:00 @hurrytospring 赞同这个方案,空闲时候比如半夜再删除 | 
|      26enjoyCoding      2020-06-30 09:04:10 +08:00 两个服务 一个取 取完了通知另一个删除  删除放一个标志位或者存到一个数组里面 一个一个删除 说到底还是异步 | 
|  |      27encro      2020-06-30 09:06:37 +08:00 写都没问题,删还会成问题了?所以为什么不取的时候同时删除呢? 或者取的时候写入队列,通过 crontab 或者 supervisord 脚本任何时候想删就删。 | 
|  |      28clf      2020-06-30 09:16:03 +08:00 既然这样读写删除性能差,那么为什么要生成文件呢……看上去就是消息队列一样的功能…… | 
|  |      29xjmroot      2020-06-30 09:27:58 +08:00 如果是用 Nginx 做代理,访问文件时会有 Nginx 日志,将日志入到 kafka 写个 kafka 消费者消费 Nginx 日志删除文件 | 
|  |      30Te11UA OP @SlipStupig @lychs1998 因为内存少昂,你的意思是将文件内容缓存到消息队列是吗 ? @realpg @billlee 的确不是什么大问题,性能也可以接受,我只是想问下还有什么方式可以去做~当然,这也可能是我过早优化了 | 
|      31crclz      2020-06-30 09:43:23 +08:00 20w 个文件还是直接用数据库好了,让生产者把文件放数据库里面。传统的关系型数据库都行。 | 
|      32Huelse      2020-06-30 10:15:03 +08:00 既然时先取后删,建议还是延时删除吧,还可以避开访问高峰 | 
|  |      33SlipStupig      2020-06-30 13:22:33 +08:00 @Te11UA 是的啊,队列不是在不停消费嘛,不会占用太多,如果怕占用大,可以压缩后再存 | 
|  |      34VictorJing94      2020-06-30 15:55:37 +08:00 取走后给文件加标识?定期统一处理? | 
|  |      35est      2020-06-30 16:30:57 +08:00 高效的方法是建立个删除队列。用一个后台进程慢慢删。 | 
|  |      36009694      2020-06-30 16:53:38 +08:00 celery 异步删除 | 
|  |      37SjwNo1      2020-06-30 17:09:17 +08:00 消息队列或者 19 楼的做法都行 | 
|  |      38no1xsyzy      2020-06-30 17:47:40 +08:00 一致性的要求?是否完整地取走才能被删?取一半对方 RST 了怎么办?取一半 Python 线程 / 进程挂了怎么办? 是否要确认对方确实完全收到?是否要求对方无误地收到? |