Set是记录“已完成分片”的高效选择,因其天然去重、O(1)插入与查询、内存可控;相比数组(O(n)查找)和Map(Value冗余),Set语义更精准,仅关注存在性。

用 Set 记录“已完成分片”是简单且高效的选择,尤其适合单机、高并发、低延迟场景。它天然去重、插入和查询平均时间复杂度为 O(1),内存开销可控(每个分片 ID 约占几十字节),比数据库或 Redis 做轻量状态跟踪更直接。
为什么选 Set 而不是数组或 Map?
数组查找需遍历,O(n) 不可接受;Map 虽支持 O(1) 查询,但对纯存在性判断(“这个分片传没传完?”)属于功能冗余——Key-Value 结构中 Value 没实际用途,徒增内存与维护成本。Set 语义精准:只关心“有没有”,不存额外数据。
分片 ID 的设计要保证唯一且可预测
避免用随机 UUID 作为 Set 元素,推荐组合式 ID,例如:
`fileId_partIndex`(如 "abc123_5")或 `md5(fileContent)_partIndex`。
这样设计便于校验、调试,也方便后续扩展(比如按 fileId 批量清理某文件的所有分片状态)。
使用场景下的关键操作建议
- 上传时记录:收到分片并校验成功后,直接 set.add("fileA_7");
- 合并前检查:用 set.has("fileA_0") && set.has("fileA_1") && ... 或循环比对预期分片数;
- 超时清理:为防内存泄漏,给每个上传任务绑定定时器,15–30 分钟无新分片写入则 set.delete() 对应所有 ID(可配合 WeakMap 或外部映射表管理生命周期);
- 重启恢复:纯内存 Set 无法跨进程存活,若需容错,启动时从持久化存储(如本地 JSON 文件、SQLite 表)批量加载已确认分片 ID 到 Set 中。
注意边界:何时不该只用 Set?
- 需要多节点共享状态(如集群部署)→ 改用 Redis 的 SET 或 HyperLogLog;
- 分片数量极大(千万级+)且内存敏感 → 考虑布隆过滤器(Bloom Filter)做初筛,再辅以小 Set 做精确判定;
- 需审计或追溯(谁、何时、哪个 IP 传了哪片)→ Set 不存元数据,必须搭配日志或数据库记录。










