Python 实现大文件的高并发下载

项目背景

基于一个 scrapy-redis 搭建的分布式系统,所有item都通过重写 pipeline 存储到 redislist 中。这里我通过代码演示如何基于线程池 + 协程实现对 item 的中文件下载。

  • Item 结构

    目的是为了下载 item 中 attachments 保存的附件内容。

    {"crawl_time":"20221017 12:00:00","version":"20221017 12:00:00","data": [{"title": "","attachments": [{"ori_url": "https://www.baidu.com",	# 文件地址"path": "",	# 文件本地保存路径"filename": "xxx"	# 文件名称}]}]
    }
    

一、批量获取 item

为了能够提高数据的存储效率,选择从 redis 中弹出多个 item,但当前部署的 redis 版本为 5.0lpop 不支持同时弹出多个数据,需要通过 LRANGELTRIM 命令实现,但是两个命令执行不是原子操作,在多线程的情况下会导致数据异常,因此通过 lua 脚本执行批量弹出多个 item

1.1 lua 脚本

在这里插入图片描述

1.2 读取数据

设定好批量读取的大小,执行 lua 脚本,获取数据。
在这里插入图片描述

二、并发

2.1 线程池

使用线程池去管理这么多 item 下载任务的原因:

  • 减少频繁创建和销毁线程的开销
  • 控制并发数量,防止不断创建线程导致资源耗尽
  • 复用线程,减少线程切换开销

将获取到的 data 进行分片,分片后的数据交给多个线程去下载,提高并发效率。
在这里插入图片描述

2.2 协程任务

每个线程新建一个事件循环对象 loop,用来管理分片后的 data 协程任务。

为了复用 TCP 连接和 session,选择让分片 data 共享一个 TCPConnectorClientSession 对象。这是基于 data 分片大小大概率是同一个网站的数据设计的,可以降低连接创建会话管理的的资源消耗。
在这里插入图片描述

2.3 协程并发

通过 asyncio.gather 实现协程并发。
在这里插入图片描述

三、大文件分块

下载文件时,如果文件比较大,网络又不稳定的情况下,很容易导致下载失败,因此这里通过将文件分块下载优化流程。

3.1 分块

对文件分块之前,先要获取文件大小。向服务器发送一个预请求 head,来获取文件长度,这样可以避免获取整个文件,减少网络传输耗时。
在这里插入图片描述
然后对文件进行分块处理,在传输中,需要平衡 网络拥塞请求频次 导致的消耗,这里选择将文件分为 1024 * 1024 也就是 1 MB 的块大小。

使用 asyncio.Semaphore 控制 同时进行的下载任务数量,避免过多并发导致服务器崩溃。
在这里插入图片描述

3.2 下载

修改 headers 中的 Range 获取文件指定块大小的内容。

通过装饰器实现文件的断点续传功能,防止因网络不稳定导致文件内容缺失。
在这里插入图片描述
当文件的某个块下载失败,超出重试次数时,取消所有该文件块的下载任务,暂时放弃该文件,记录到失败下载队列中保存,避免因为问件本就损坏这种情况导致不断重试。
在这里插入图片描述
异步装饰器的实现
在这里插入图片描述

3.3 拼接

result 按顺序返回请求的结果,将请求的文件块拼接完成。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/897981.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/897981.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL与Canal、RabbitMQ集成指南

MySQL 部分 1. 查看是否开启 binlog MySQL 8 默认开启 binlog。可以通过以下命令查看是否开启: SHOW VARIABLES LIKE log_bin;如果返回结果为 ON,则表示 binlog 已开启。 Variable_nameValuelog_binON 2. 若未开启 binlog,则需手动配置 …

X86 RouterOS 7.18 设置笔记十:上海电信IPTV使用msd_lite实现组播转单拨

X86 j4125 4网口小主机折腾笔记五:PVE安装ROS RouterOS X86 RouterOS 7.18 设置笔记一:基础设置 X86 RouterOS 7.18 设置笔记二:网络基础设置(IPV4) X86 RouterOS 7.18 设置笔记三:防火墙设置(IPV4) X86 RouterOS 7.18 设置笔记四…

Select 选择器选项位置偏移的解决方案

Select 选择器选项位置偏移的解决方案 在使用 Select 组件时,可能会遇到下拉选项位置偏移的问题。这通常由 CSS 样式、组件 渲染方式 或 父级元素的影响 造成。以下是详细的排查步骤和解决方案。 一、常见原因 position: relative; 或 overflow: hidden; 影响下拉菜…

LeetCode 解题思路 17(Hot 100)

解题思路: 找到链表中点: 使用快慢指针法,快指针每次移动两步,慢指针每次移动一步。当快指针到达末尾时,慢指针指向中点。递归分割与排序: 将链表从中点处分割为左右两个子链表,分别对这两个子…

数学建模历程之初见

第一次接触数学建模是在上大学前,当时只是听过。起源于我在大学的老乡群里聊天,由于当时年轻有点傻,说的话太多了,什么都问哈哈哈哈哈。 后来有个学长从老乡群里加我,问我怎么话那么多,你们懂当时对我幼小…

Python 科学计算与机器学习入门:NumPy + Scikit-Learn 实战指南

Langchain系列文章目录 01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…

「自动驾驶背后的数学:从传感器数据到控制指令的函数嵌套」—— 揭秘人工智能中的线性函数、ReLU 与复合函数

引言 自动驾驶技术是人工智能领域的一个重要应用,其核心在于如何将传感器数据转化为车辆控制指令。这一过程涉及大量的数学知识,包括线性函数、激活函数(如 ReLU)以及复合函数的嵌套使用。本文将深入探讨自动驾驶中的数学原理&am…

详解SQL数据定义功能

数据定义 1. 数据库模式(Schema)的定义与删除定义模式删除模式 2. 基本表的定义、修改与删除定义表约束1. NOT NULL 约束2. DEFAULT 约束3. UNIQUE 约束4. PRIMARY KEY 约束多列主键示例: 5. FOREIGN KEY 约束6. CHECK 约束7. AUTO_INCREMENT…

Redis超高并发分key实现

Redis扛并发的能力是非常强的,所以高并发场景下经常会使用Redis,但是Redis单分片的写入瓶颈在2w左右,读瓶颈在10w左右,如果在超高并发下即使是集群部署Redis,单分片的Redis也是有可能扛不住的,如下图所示&a…

AI Agent 时代开幕-Manus AI与OpenAI Agent SDK掀起新风暴

【本周AI新闻: AI Agent 时代开幕-Manus AI与OpenAI Agent SDK掀起新风暴】 https://www.bilibili.com/video/BV1bkQyYCEvQ/?share_sourcecopy_web&vd_source32ed33e1165d68429b2e2eb4749f3f26 最近AI圈子里最火的话题非Manus莫属!这款由中国武汉创业公司“蝴…

多时间尺度的配电网深度强化学习无功优化策略的Python示例代码框架

以下是一个简单的多时间尺度的配电网深度强化学习无功优化策略的Python示例代码框架,用于帮助你理解如何使用深度强化学习(以深度Q网络 DQN 为例)来处理配电网的无功优化问题。在实际应用中,你可能需要根据具体的配电网模型和需求…

剑指 Offer II 081. 允许重复选择元素的组合

comments: true edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20081.%20%E5%85%81%E8%AE%B8%E9%87%8D%E5%A4%8D%E9%80%89%E6%8B%A9%E5%85%83%E7%B4%A0%E7%9A%84%E7%BB%84%E5%90%88/README.md 剑指 Offer II 081. 允许重复选择…

Webpack 前端性能优化全攻略

文章目录 1. 性能优化全景图1.1 优化维度概览1.2 优化效果指标 2. 构建速度优化2.1 缓存策略2.2 并行处理2.3 减少构建范围 3. 输出质量优化3.1 代码分割3.2 Tree Shaking3.3 压缩优化 4. 运行时性能优化4.1 懒加载4.2 预加载4.3 资源优化 5. 高级优化策略5.1 持久化缓存5.2 模…

虚拟电商-数据库分库分表(二)

本文章介绍:使用Sharding-JDBC实现数据库分库分表,数据库分片策略,实现数据库按月分表 一、Sharding-JDBC使用 1.1.准备环境 步骤一:分库分表sql脚本导入 创建了两个数据库:chongba_schedule0 和chongba_schedule1…

向量数据库对比以及Chroma操作

一、向量数据库与传统类型数据库 向量数据库(Vector Storage Engine)与传统类型的数据库如关系型数据库(MySQL)、文档型数据库(MongoDB)、键值存储(Redis)、全文搜索引擎&#xff0…

python列表基础知识

列表 创建列表 1.列表的定义:可变的,有序的数据结构,可以随时添加或者删除其中的元素 2.基本语法:字面量【元素1,元素2,元素3】使用[]创建列表 定义变量:变量名称【元素1,元素2&…

Node.js 的模块作用域和 module 对象详细介绍

目录 代码示例 1. 创建模块文件 module-demo.js 2. 导入模块并使用 module-demo.js 运行结果 总结 在 Node.js 中,每个文件都是一个独立的模块,具有自己的作用域。与浏览器 JavaScript 代码不同,Node.js 采用模块作用域,这意味…

美畅物联丨WebRTC 技术详解:构建实时通信的数字桥梁

在互联网技术飞速发展的今天,实时通信已成为数字生活的核心需求。WebRTC作为一个开源项目,凭借卓越的技术实力与创新理念,为网页和移动应用带来了颠覆性的实时通信能力。它突破了传统通信方式的限制,实现了音频、视频和数据在用户…

excel中两个表格的合并

使用函数: VLOOKUP函数 如果涉及在excel中两个工作表之间进行配对合并,则: VLOOKUP(C1,工作表名字!A:B,2,0) 参考: excel表格中vlookup函数的使用方法步骤https://haokan.baidu.com/v?pdwisenatural&vid132733503560775…

单引号与双引号在不同编程语言中的使用与支持

在编程语言中,单引号和双引号是常见的符号,它们通常用来表示字符和字符串。然而,如何使用这两种符号在不同的编程语言中有所不同,甚至有一些语言并不区分单引号和双引号的用途。本文将详细介绍不同编程语言中单引号与双引号的支持…