
1) 【一句话结论】
采用分块并行下载架构,结合文件元数据校验、分布式锁控制资源竞争,以及指数退避重试策略,确保高并发下断点续传的可靠性与效率。
2) 【原理/概念讲解】
老师口吻解释核心机制:
3) 【对比与适用场景】
| 机制 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 分布式锁(如Redis) | 基于分布式存储的原子锁(SETNX) | 原子性、可扩展、避免死锁(通过超时释放) | 分布式系统、高并发场景(如多客户端下载同一文件) | 需考虑网络延迟、锁超时,避免死锁 |
| 文件锁(本地锁) | 本地文件系统中的锁(如flock) | 实现简单、适用于单机或小规模分布式 | 单机应用、本地文件共享 | 分布式环境下可能存在锁竞争,无法跨机器 |
| 分块策略(固定) | 固定大小分块(如10MB) | 线程数计算简单,资源占用可控 | 网络带宽稳定或中等 | 网络波动时效率可能下降 |
| 分块策略(动态) | 按带宽调整块大小 | 适应不同网络环境,提升效率 | 高动态网络环境 | 算法复杂,需实时监测带宽 |
4) 【示例】
伪代码展示核心流程(含文件元数据检查、分块、锁、重试):
def download_video(file_id, url):
# 1. 文件元数据检查(大小、MD5)
remote_size, remote_md5 = get_file_metadata(url) # HTTP HEAD获取大小,GET请求获取MD5
local_size, local_md5 = get_local_metadata(file_id)
if remote_size != local_size or remote_md5 != local_md5:
return "文件已更新,请重新下载"
# 2. 计算分块信息
block_size = 10 * 1024 * 1024 # 10MB
total_blocks = (remote_size) // block_size + 1
downloaded_blocks = get_downloaded_blocks(file_id)
# 3. 并行下载剩余块
thread_pool = ThreadPoolExecutor(max_workers=4)
futures = []
for i in range(total_blocks):
if i in downloaded_blocks:
continue
start = i * block_size
end = min(start + block_size - 1, remote_size - 1)
futures.append(thread_pool.submit(download_block, file_id, i, start, end))
for future in futures:
future.result()
# 4. 更新断点
save_downloaded_blocks(file_id, list(range(total_blocks)))
def download_block(file_id, block_index, start, end):
lock_key = f"lock:file:{file_id}:{block_index}"
if not acquire_lock(lock_key, timeout=5): # 分布式锁,超时避免死锁
return
try:
response = requests.get(f"{url}?offset={start}&size={end-start+1}", stream=True)
response.raise_for_status()
with open(f"{file_id}.part{block_index}", "wb") as f:
for chunk in response.iter_content(8192):
f.write(chunk)
save_downloaded_block(file_id, block_index, end) # 更新断点
except Exception as e:
log_error(e)
retry_count = 0
while retry_count < 3:
retry_count += 1
time.sleep(2 ** retry_count) # 指数退避
download_block(file_id, block_index, start, end)
finally:
release_lock(lock_key)
def acquire_lock(key, timeout=5):
return redis.setnx(key, "locked", ex=timeout) # Redis原子锁
def release_lock(key):
redis.delete(key)
5) 【面试口播版答案】
“面试官您好,针对高并发视频素材下载的断点续传系统,我的设计核心是分块并行下载,结合文件元数据校验、分布式锁控制资源竞争,以及指数退避重试策略。首先,系统将文件拆分为固定大小的数据块(如10MB),每个线程负责下载一个块,通过本地偏移量记录下载进度。资源竞争用Redis分布式锁,限制同一文件的最大并发下载线程数(比如每个文件最多4个线程),避免服务器资源耗尽。网络不稳定时,采用指数退避重试,第一次失败后等待1秒,第二次2秒,最多重试3次。核心模块包括:分块管理器(计算块大小、偏移量)、下载线程池(管理线程)、断点存储(本地文件或数据库)、锁服务(分布式锁)。数据结构上,用Map<文件ID, List<块信息>>存储块信息,每个块包含偏移量、大小、状态。高并发下,通过锁服务确保同一时间只有一个线程下载某个块,防止数据冲突。重试机制中,失败后等待时间指数增长,避免频繁重试影响性能。这样既能保证断点续传,又能应对高并发和网络波动。”
6) 【追问清单】
7) 【常见坑/雷区】