V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MilletChili
V2EX  ›  程序员

异步分片上传文件,我这样做合适吗?

  •  
  •   MilletChili · 2020-04-23 14:18:25 +08:00 · 2144 次点击
    这是一个创建于 1662 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在判断分片是否全部完成上传前,加锁是必须的吧。

    怎么加 用啥加好呢?我现在用的数据库锁,为此专门建了一个表,就一个 id 字段,为每个用户的 id,在判断分片是否全部完成上传的前,去查当前用户 id 对应新建表的那条数据然后加 for update,可用倒是可用,但是感觉有点僵硬啊,大佬们能不能点拨点拨

    13 条回复    2020-04-26 18:37:44 +08:00
    h4de5
        1
    h4de5  
       2020-04-23 14:38:02 +08:00
    可以参考一下阿里云 oss 的 sdk 的代码。
    mlxj
        2
    mlxj  
       2020-04-23 14:49:28 +08:00
    1.每个分片=>暂存
    2.分片=>总数,根据总数来判断是否上传完成。
    MilletChili
        3
    MilletChili  
    OP
       2020-04-23 15:45:58 +08:00
    @h4de5 好的,我去看一下
    MilletChili
        4
    MilletChili  
    OP
       2020-04-23 16:00:13 +08:00
    @mlxj 但请求是异步的啊,在判断<当前分片数==总数> 前,得加锁,不加的话,可能出现多个分片上传的请求中判断<当前分片数==总数>都成立或不成立的情况
    MilletChili
        5
    MilletChili  
    OP
       2020-04-23 16:01:34 +08:00
    @MilletChili 我说的是最后几个分片哈
    MilletChili
        6
    MilletChili  
    OP
       2020-04-23 16:10:55 +08:00
    @h4de5 阿里云 oss 的 sdk 都是安顺序一个一个分片传的,我开几个线程异步着传分片的情况呢
    netnr
        7
    netnr  
       2020-04-23 16:54:55 +08:00
    保存分片时,完成分片计量+1 (全局缓存) ,再判断等于总片数就合并
    百度的 webuploader 分片包含 chunk chunks 两个变量
    mlxj
        8
    mlxj  
       2020-04-24 09:58:05 +08:00
    还是不用加锁。
    每次上传的时候带两个参数:
    1.文件 id
    2.chunk 第 N 个
    MilletChili
        9
    MilletChili  
    OP
       2020-04-24 10:06:46 +08:00
    @mlxj 文件 id 指的是啥? MD5 值吗
    h4de5
        10
    h4de5  
       2020-04-24 14:03:37 +08:00
    @MilletChili https://i.loli.net/2020/04/24/fj69irBU4ZJvekg.png 这个是我的 oss 上传日志。部分分片上传失败的话,后面不一定是顺序上传的。
    MilletChili
        11
    MilletChili  
    OP
       2020-04-26 18:26:36 +08:00
    @h4de5 嗯,我之前说的不太清楚,应该是阿里云 oss 都是同步着传的,不会有并发的问题。我这边找到一个比较好的方案了,用 redis 的 incr,每保存一个分片就 incr 一下分片数,redis 单进程的不受并发影响,而且基于内存还快,比关系数据库开事务加锁快多了
    MilletChili
        12
    MilletChili  
    OP
       2020-04-26 18:31:17 +08:00
    python 代码
    # 加锁判断当前分片是否是最后一个
    is_last_slice = False
    if redis_helper.incr(sign) == slice_num:
    is_last_slice = True

    # with transaction.atomic():
    # if SliceLock.objects.select_for_update().filter(sign=sign).first():
    # if slice_num == len(os.listdir(temp_dir_path)):
    # is_last_slice = True
    # else:
    # code, msg, data = (GlobalsCode.Err, 'sign 不存在', {'slice_name': slice_f.name})
    # return retCORS(code, msg, data)
    MilletChili
        13
    MilletChili  
    OP
       2020-04-26 18:37:44 +08:00
    @MilletChili 说错了,redis 单线程
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2734 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 07:39 · PVG 15:39 · LAX 23:39 · JFK 02:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.