• php 大文件上传 redis+php resque 较低io消耗


    在做视频站的时候存在这么一个情景,用户需要上传较大的视频文件,一般在两个G以上,且可能存在多人同时上传的情况。

    经过查阅资料解决方案有如下几种:

    1、调整php和nginx文件上传的最大限制

    2、在前端将文件切片上传后再进行合并

    经过我们的评估发现,方案1的做法并不合适,单纯的调大文件大小限制,会导致上传一个文件需要一个连续很长的时间, 占用一个php进程,且可能出现超时等各种情况。

    所以我们选择方案二进行探索:

    使用百度webuploader前端插件对大文件进行切片处理,等待所有文件全部上传完毕后再进行合并。

    但是用着用着凸显出一些问题:

    1、大文件在完全上传完毕后,把一个一个小的切片文件合并成一个大文件,这个时间可能是很长的,很有可能超过php或者nginx的超时限制,这样给用户的就是超时提醒,是极为不友好的。

    2、文件在合并的时候需要连续长时间的写入到磁盘中,对服务器io压力很大,如果mysql在同一台服务器上也将对整个网站产生压力。

    3、多人同时上传,且差不多同一时间上传完毕,再合并对服务器的压力将更大。。。超时问题也将更加的严重。

    4、php接收上传的文件临时区默认是在磁盘上,整个流程就是接收->写入磁盘->上传完毕->读取切片文件->写入磁盘,整个流程对服务器压力较大。

    经过查找资料(但是没找到太多,难道是关键词不对)我们想出了如下大致的解决方案

    1、修改php文件上传存放的临时目录,放到ubuntu分配的内存文件目录,减少io。

    2、将上传完毕再合成修改为边上传边合并,这样用户发完最后一个文件就能很快的得到上传成功或失败的提醒,同时减少了上面提到的连续长时间磁盘io。

    第1点没什么说的,修改php配置即可,但是需要注意的是内存的大小限制。

    难点主要在第2点中:

    具体如下:

    1、切片上传的文件是无序的,可能上传切片的顺序是1、5、3、4、2这样的,如何保证合并的顺序?

    2、同一用户同时上传多个文件?

    3、不同用户上传同名文件,如何命名?

    这里主要针对难点1的解决方案进行阐述:

    需要的两个工具:redis和任务调度框架php resque

    利用redis维护

    一个有序集合(存储已经上传的切片文件编号,有序是因为合并切片需要切片的顺序)

    and

    一个普通列表(存储已经合并的切片编号,用于判读切片是否连续)

    php resque去发起合并任务(每个上传的文件对应唯一的任务标志id)

    根据php resque的任务状态确保同一个文件同时只有一个合并任务在进行

    每次切片上传成功后,向该上传文件的有序集合中,添加一个数据,键为切片序号,值也为切片序号

    php resque中的job内容:参数主要为(临时文件名、切片文件总长度,最终保存的文件名)

    job:

    循环执行:

    从有序集合从取第一小的切片号,判断该切片号-1是否已经在已经合并的切片的普通列表中(切片为1直接开始合并),不在的话循环结束

    读取切片号对应的文件,写入到最终的文件中,最刚开始不存在则创建。

    写入完毕后,向切片列表中加入该切片编号

    删除该切片文件

    继续循环

    如果切片号==文件切片长度,任务over

  • 相关阅读:
    [推荐系统]常见术语
    大表建索引
    mysql数据表设计
    导入导出的系统设计
    java系统设计 面试题
    工厂模式的实际运用
    系统对接的沟通与协作
    elastaticSearch(es) 面试题
    Redis面试题
    Kafka面试题
  • 原文地址:https://www.cnblogs.com/Lynwood/p/9650603.html
Copyright © 2020-2023  润新知