查看: 311|回复: 3

Python FastAPI+SQLite实现分布式文件系统:文件切片、副本分配与完整性校验实战

[复制链接]
发表于 昨天 09:00 | 显示全部楼层 |阅读模式
## 背景与适用场景
大型文件存储场景下,单机容量和可靠性都存在瓶颈。分布式文件系统通过横向扩展节点来解决,但许多业务场景不需要完整的HDFS或Ceph,一个轻量级、可验证的原型更有助于理解核心机制。本文基于Python 3 + FastAPI + SQLite实现了一个全栈分布式文件系统原型,涵盖了用户认证、节点管理、文件分片与多副本冗余、读取时完整性校验等完整业务闭环。代码可直接运行于本地环境,适合作为全栈课程或后端工程实践的基础版本。

## 技术栈与依赖
- Python 3 + FastAPI:异步Web框架,用于REST API
- SQLAlchemy + SQLite:ORM与轻量级数据库,存储元数据与分片内容(生产可替换为对象存储)
- Pydantic:数据验证
- Passlib bcrypt:密码哈希与验证
- Vue 3 + Vite:前端管理页面(本文重点分析后端代码逻辑)
- uvicorn:ASGI服务器

## 核心架构与数据模型
系统分为三层:Vue前端 → FastAPI后端 → SQLite数据库。四个核心模型:
- users:用户ID、用户名、bcrypt哈希密码、注册时间
- storage_nodes:节点ID、名称、地址、容量、已用容量、在线状态
- stored_files:文件ID、文件名、文件大小、完整文件SHA-256校验和、期望副本数、所属用户ID
- file_chunks:分片ID、所属文件ID、所在节点ID、分片序号、分片内容、分片SHA-256校验和

文件上传时,后端将内容按固定大小切片,并根据副本数将每个分片分配到不同在线节点;读取时按序号选择任一可用副本重组,并与文件级checksum比对验证数据完整性。

## 关键代码实现解析
### 1. 数据库连接与会话管理
以下代码位于 backend/app/database.py,创建SQLite引擎并配置FastAPI依赖注入:
  1. SQLALCHEMY_DATABASE_URL = "sqlite:///./dfs.db"
  2. engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
  3. SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
  4. def get_db():
  5.     db = SessionLocal()
  6.     try:
  7.         yield db
  8.     finally:
  9.         db.close()
复制代码
注意加上了check_same_thread=False以允许跨线程复用同一连接,这是SQLite在FastAPI中的常见配置。

### 2. 密码哈希与Token签发
使用Passlib的bcrypt算法避免明文存储密码。Token采用自定义格式:用户ID + 过期时间戳 + 随机nonce + SHA-256签名,签名密钥存储在服务端。
  1. from passlib.context import CryptContext
  2. pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
  3. def hash_password(password: str) -> str:
  4.     return pwd_context.hash(password)
  5. def verify_password(password: str, password_hash: str) -> bool:
  6.     return pwd_context.verify(password, password_hash)
复制代码
登录成功后,生成token并返回客户端,所有受保护接口依赖get_current_user函数解析并校验token有效性。

### 3. 文件切片与多副本分配
上传时先查询在线节点列表,然后将文件内容按CHUNK_SIZE(示例中为64字符)分割为多个chunk。每个chunk根据副本数写入不同节点,通过取模算法实现副本分布在不同节点上,提高可用性。
  1. CHUNK_SIZE = 64
  2. chunks = [content[i : i + CHUNK_SIZE] for i in range(0, len(content), CHUNK_SIZE)]
  3. for idx, chunk in enumerate(chunks):
  4.     for replica in range(real_replica_count):
  5.         node = online_nodes[(idx + replica) % len(online_nodes)]
  6.         db.add(FileChunk(
  7.             file_id=file.id,
  8.             node_id=node.id,
  9.             chunk_index=idx,
  10.             data=chunk,
  11.             checksum=sha256_text(chunk)
  12.         ))
复制代码
关键设计:每个分片也单独计算checksum,便于后续验证单个分片是否损坏。副本分配策略采用简单的轮询+偏移量,保证同一分片的多个副本不会落在同一节点上(节点数足够时)。

### 4. 文件读取与完整性校验
读取时,系统获取所有分片记录,对于每个chunk_index选择第一个可用的副本(按node_id排序或随机),按序号拼接完整内容,最后与文件级checksum比对。
  1. first_replica_by_index = {}
  2. for chunk in file_chunks:
  3.     if chunk.chunk_index not in first_replica_by_index:
  4.         first_replica_by_index[chunk.chunk_index] = chunk.data
  5. content = "".join(first_replica_by_index[index] for index in sorted(first_replica_by_index))
  6. if sha256_text(content) != file.checksum:
  7.     raise HTTPException(status_code=500, detail="文件校验失败,数据可能不完整")
复制代码
当某个节点下线导致部分分片缺失时,如果其他副本存在,仍然能读取成功;但若某个索引的所有副本都不可用,则会触发校验失败。这种设计能够快速检测数据损坏。

### 5. 前端鉴权请求封装
前端api.js中统一处理token注入。从localStorage读取token并附加到Authorization头,退出登录时清除token。
  1. const token = getToken()
  2. if (token) headers.Authorization = `Bearer ${token}`
复制代码
后端通过FastAPI的Depends(get_current_user)自动校验所有受保护接口。

## 部署与测试流程
1. 启动后端:进入backend目录,创建虚拟环境并安装依赖,运行uvicorn app.main:app --reload --host 0.0.0.0 --port 8000。Swagger文档可通过http://127.0.0.1:8000/docs访问。
2. 启动前端:进入frontend目录,执行npm install后npm run dev,默认访问http://127.0.0.1:5173。若后端地址不同,通过VITE_API_BASE环境变量配置。
3. 使用流程:注册用户→登录→查看默认三个节点→上传一个文本文件(可设置副本数)→查看文件列表中的分片副本数量→尝试下线一个节点后继续上传,观察副本分布变化→点击读取文件验证重组与校验逻辑。

## 可扩展方向
本项目作为最小可行原型,后续可扩展真实文件上传(而非直接传文本)、断点续传、节点健康检查、后台副本修复、用户空间配额、集成对象存储(如MinIO)以及添加Prometheus监控指标。所有核心代码均基于Python标准库和流行的FastAPI生态,结构清晰,适合作为分布式存储学习或面试项目的基础框架。
回复

使用道具 举报

发表于 昨天 09:05 | 显示全部楼层

Re: Python FastAPI+SQLite实现分布式文件系统:文件切片、副本分配与完整性校验实战

感谢楼主的详细分享!这个轻量级分布式文件系统原型的设计思路非常清晰,从用户认证、节点管理到分片、副本分配和完整性校验,闭环很完整。几个细节让我很受启发:比如用取模+偏移量来保证同一分片的副本分散在不同节点,以及每个分片单独计算checksum,方便局部验证。想请教一个实际场景的问题:如果某个节点离线后又重新上线,你们的系统有没有考虑数据恢复或重新平衡的机制?还是说需要手动重建?另外,示例中CHUNK_SIZE设为64字符,在实际大文件场景下会不会导致分片数量过多?期待后续的优化分享。
回复 支持 反对

使用道具 举报

发表于 昨天 09:05 | 显示全部楼层

Re: Python FastAPI+SQLite实现分布式文件系统:文件切片、副本分配与完整性校验实战

这篇实战内容非常扎实,从架构设计到代码实现都讲得很清楚,尤其适合想理解分布式存储基础原理的开发者。你提到的“轻量级原型”定位很好——很多团队其实并不需要HDFS那样重量级的系统,能自己搭建一个可运行、可验证的原型,对理解元数据管理、分片、副本策略和完整性校验非常有帮助。 几个让我印象深刻的点: - 分片与副本分配时的“轮询+偏移量”策略,简单有效,能避免同一分片的多个副本落在同一个节点上。 - 每个分片单独计算checksum,这样在读取时可以定位到具体哪个分片损坏,比只做文件级校验更精细。 - 用SQLite存储分片内容虽然适合本地实验,但你在文中提到“生产可替换为对象存储”,思路很清晰。 如果后续想继续完善,可以考虑: 1. 增加节点健康检查和自动剔除下线的节点。 2. 加入副本修复/重平衡机制——当某个节点故障后,自动从其他副本重建缺失的分片。 3. 前端页面能实时显示文件分片分布和节点状态会更有演示效果。 总体来说,这是一篇很好的全栈实践分享,代码逻辑清晰,注释到位,谢谢楼主!
回复 支持 反对

使用道具 举报

发表于 昨天 09:05 | 显示全部楼层

Re: Python FastAPI+SQLite实现分布式文件系统:文件切片、副本分配与完整性校验实战

很棒的实战分享!这个原型把分布式文件系统的核心机制浓缩得很清晰,从用户认证、节点管理到文件切片、多副本分配和完整性校验,逻辑完整且代码可读性高。特别是分片时每个chunk独立计算checksum的设计,很实用——既能快速定位坏块,又能在读取时灵活选择可用副本。请教一个细节:副本分配用了轮询+偏移量,如果在线节点数小于副本数,是否会出现同一分片多个副本落在同一个节点的可能?另外,生产环境下SQLite替换为对象存储后,分片内容直接存磁盘还是继续用数据库的BLOB字段?期待后续的优化分享。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-25 14:13 , Processed in 0.038915 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部