如意乾坤袋 · 冷数据无损压缩归档
> 袋口一张,天地山海皆入其中
> 针对股票历史数据、数字精度高、偏差小的无损压缩归档——可还原、带完整性校验、字节级校准
> v1.7.0 · 2026-08-21
在不丢失任何数据(100% 无损还原)的前提下,对历史数据做压缩瘦身 + 台账管理。
触发场景
- 数据目录占用空间越来越大,历史数据「用不上又不敢删」
- 海量小文件(上万个 JSON/日志/快照)拖慢备份与检索
- 需要知道「压缩后省多少、解压要占多少空间、数据在哪、何时压的」
核心原则(铁律)
> 第 0 条 · 血泪教训(最高优先):曾把「每天更新的数据源」当冷数据压删,导致 30+ 消费脚本断链。删原文前必须过三道闸:① 全量校验通过 ② 热/冷判定留痕(--confirm-cold)③ 显式确认。缺一不删。
- 热/冷分界是最高铁律:热数据源(每天更新 + 多脚本消费 + 门禁依赖)不压删;冷数据(历史快照、消费方少)才可压删。误压热数据 = 断链灾难
- 无损优先:纯数字/结构化数据一律无损压缩(100% 还原),不做有损摘要
- 识别三档:按内容特征分档,不按扩展名一刀切
- 台账三件套:目录索引 + 详细台账 + 时间戳
- 解压占用必标:每个压缩文件/类别标注「解压所需空间」
- 链路验证:压删后必须验证下游,不过即回滚
工作流(五步)
第 1 步 · 盘点分类
扫描全项目,按「扩展名 × 内容特征」识别目标:
json/html/txt/md/csv → 文本类·可压缩(重点看占空间大头)
png/pdf/xlsx/gz/db → 已压缩或二进制·不压
✅ 支持压缩的文件格式(文本类·无损):
| 格式 | 内容特征 | 预期压缩比 |
|---|---|---|
| .json(结构化快照) | 字段重复/稀疏 | 9-22:1 |
| .json(时序 bars) | varint delta 预处理 | 4-6:1 |
| .html | 文本冗余 | 2.5-5:1 |
| .md | 文本冗余 | 2-4:1 |
| .txt / .log | 文本 | 2-5:1 |
| .csv | 结构化文本 | 5-15:1 |
| .xml / .yaml / .ini | 标记文本 | 3-10:1 |
❌ 不支持压缩的文件格式(二进制/已压缩/运行时):
| 格式 | 原因 |
|---|---|
| .png/.jpg/.jpeg/.gif/.webp | 图片已压缩·压 1:1 无收益 |
| 已压缩 | |
| .xlsx/.xls/.docx/.pptx | zip 结构·内部已压缩 |
| .zip/.rar/.7z/.gz/.bz2/.zst | 已是压缩归档 |
| .mp4/.mp3/.avi/.wav | 音视频已压缩 |
| .exe/.dll/.bin/.so/.pyc | 二进制程序/字节码 |
| .db/.sqlite | 运行时数据库·需在线用 |
> 判据 = 内容特征,扩展名只是第一道筛:扩展名「支持」但内容是浮点随机(如指标历史序列),压缩比也低(~2:1);扩展名「不支持」但内容是纯文本(如 .txt 改名),照样可压。拿不准就抽样压一个测压缩比。
第 2 步 · 热/冷判定(最高铁律)
对每个候选目录问三个问题:
- 它每天/定期更新吗?(有写者脚本)→ 热
- 它被多个脚本/门禁直接读取吗?→ 热
- 它是历史快照、消费方极少吗?→ 冷
热数据不压删,冷数据才压删。
第 3 步 · 无损压缩
压缩前必须确认数据静止(无写入):停掉写者脚本/等定时任务结束,避免压到半写文件损坏数据。
内存管理:批量压缩/聚合/校验一律走流式(分块读,不把整个文件读进内存)+ 循环及时 del 大对象 + 定期 gc.collect(),防止批量压缩内存累积、CPU 持续高负载。
- 普通文本/JSON:
zlib或zstd(zstd 压缩比更高,业界标准) - 时序数字:先做
varint delta差分(日期差 + 相对前值差),压缩比可 +50% - 稀疏字符串:
bz2效果好(重复字段多时比 zlib 高一倍) - 海量小文件:
tar + zstd 大窗口聚合(window≥4MB),压缩比 +30% 且文件数大减 - 大单文件:流式 zlib,勿用 lzma(慢 10 倍不值)
压实度:默认 --level 9(极限压缩)——测试/调试阶段用最极限的压缩暴露最多问题,稳定后再放松到 --level 6(更快 + 容错更好)。level 1~9 压缩比几乎持平(4.5 vs 4.6:1),但极限才能更充分反映问题。
聚合压缩 + 保护值(过极则反):MIN_GZ_BYTES = 3072(3KB·寓意三生万物生生不息)——单个小文件(次新股)单独压没意思,聚合成一个 tar.gz 包再压(--aggregate),保护值 3KB 管整个压缩包(包超过3KB),不管单个文件。防止「过度压缩把文件压没」+「小文件散装无意义」。
压缩比是动态的:随数据波动变化(如行情正常 12:1、高波动期可能掉到 4:1),压前实测、按「正常/高波动」双档评估,别把参考值当恒量。
完整性校验:压缩时写 SHA-256 进文件索引(防篡改·比 CRC32 更强),台账定期校验 .gz 完整性,防静默损坏。
聚合容灾:tar 聚合包单点损坏=整包丢失,重要数据保留独立 .gz 副本 + 聚合包另存校验和。
动作顺序:压缩 → 校验(全量/大样本逐字节对比 100%)→ 通过才删原文 → 落台账。
第 4 步 · 台账三件套
生成机器台账 + 人类索引,每类记录:
类别 / 源目录 / 文件数 / 压缩大小 / 解压所需空间 / 压缩比 / 格式 / 压缩时间 / 档位 / 状态
- 目录索引:归档目录树(文件数 + 压缩大小 + 解压需空间)
- 详细台账:上述字段表
- 时间戳:updated_at(台账时间)+ compressed_at(压缩时点)+ mtime_range(归档范围)
- 解压占用标注(必填):
解压所需空间 = 还原为原始可用数据后的占用;文件级用索引记录每个文件的压缩/解压大小 - 解压前空间检查:解压前对比「当前磁盘可用空间 vs 解压所需空间」,不够先腾挪,避免解压到一半磁盘满
第 5 步 · 链路验证(三件套)
压删后必须验证:
- 门禁/健康检查:数据检查器能识别(文件数恢复)
- 代表消费者抽跑:跑下游消费脚本不报错
- 还原质量抽验:抽样解压逐字节对比 100%
任一不过 → 立即从备份还原回滚。
工具(参数化通用脚本)
# 混合目录(不细分也能压):文本类自动压·二进制自动跳过·未知扩展名内容检测(含中文)
python scripts/compress_archive.py --src <大杂烩目录> --out <归档目录> --auto
# 纯 JSON 目录:--kind kline(含 bars 字段自动 varint)/ json(直压)
python scripts/compress_archive.py --src <数据目录> --out <归档目录> [--kind kline|json] [--format zlib|bz2|zstd] [--price-div 100]
# 生成台账(索引 + 明细 + 时间戳 + 解压占用)
python scripts/build_ledger.py --archive <归档目录> --src-map <源目录映射.json>
# 应急回滚:从归档还原原文
python scripts/restore_archive.py --src <归档目录> --out <还原目录> [--kind kline|json]
# 定期校验(bit-rot 检测·挂定时每周跑):SHA-256 对比 + 解压抽验
python scripts/verify_archive.py --archive <归档目录> [--spot 10]
> 完整性:压缩即写 SHA-256(files_index + checksums.sha256 标准清单·可 sha256sum -c 一键校验)。verify_archive.py 定期校验 = bit-rot 检测(SHA-256 对比 + --spot 解压抽验防「包好数据坏」);无 sha256 的旧归档提示迁移重算。校验发现损坏 → 从备份还原(检测≠修复,修复需 PAR2 可选增强)。
> 脚本位于本 skill 的 scripts/ 目录,用绝对路径调用,如 python ~/.workbuddy/skills/qiankun-pouch/scripts/compress_archive.py ...
混合目录模式(--auto · 核心能力)
目录没细分、什么格式都有?直接 --auto 一把梭,自动三路分流:
- 文本白名单(json/html/md/txt/log/csv/xml/yaml…)→ 自动压缩
- 二进制黑名单(png/pdf/xlsx/zip/mp4/exe/db…)→ 自动跳过(报告原因)
- 未知扩展名 → 内容检测(UTF-8 解码 + 替换字符比例,中文文本也能识别)→ 文本压缩 / 二进制跳过
✅ 压缩 6 个(文本类) ⏭️ 跳过 5 个(非文本/已压缩)
· 二进制格式: 4 个 · 二进制内容: 1 个
> 已验证:中文 .data 正确识别为文本压缩;随机 .bin 正确跳过。关键时候不会说不行。
不可压文件处理(三选一):
| 方式 | 命令 | 效果 |
|---|---|---|
| 默认:原位保留 | --auto |
不压不删,跳过清单留痕(skipped.json) |
| 移入归档不动区 | --auto --move-binary |
不可压文件移入 <out>/binary_keep/(只归档不压缩·省源目录空间) |
混合有无影响:无影响——文本进 .gz、二进制留原地/不动区,分开处理互不干扰;台账/报告记录「压缩清单 + 跳过清单」双清单,找回路径清晰。
🔒 隐私边界(内容检测铁律)
--auto 的内容检测只做:
- ✅ 读前 2048 字节算字节分布,判断文本/二进制(不读全文件)
- ✅ 只判类型,不解析语义、不输出内容、不落盘原文
- ✅ 检测结论(可压/跳过)记录在索引,原文内容不保留
禁做:
- ❌ 禁止展示/输出文件内容片段
- ❌ 禁止把原文写进日志/索引/台账
敏感目录(含密钥/Token/个人信息文件):压前人工确认,或用白名单排除,不让脚本读未知敏感文件。
加密:默认不做(本地归档场景无外部传输/云存储暴露面,加密是无谓开销)。仅当未来归档要传外部/上云时,再加 AES-256 客户端加密(先压缩后加密)。
检查单(交付必验)
- [ ] 热数据源未被压删(热/冷判定留痕)
- [ ] 压缩前确认数据静止(无写入)
- [ ] 压缩后 100% 无损还原(校验记录)
- [ ] 台账含:目录索引 + 详细台账 + 时间戳 + 解压占用
- [ ] 每个压缩文件有「解压所需空间」标注(字节级精确记录 gz_bytes/raw_bytes)
- [ ] .gz 带 SHA-256 校验(files 索引 + checksums.sha256 可验完整性·防篡改)
- [ ] 解压前确认磁盘可用空间 ≥ 解压所需空间
- [ ] 链路验证三件套全过(门禁 + 消费者 + 还原抽验)
- [ ] 留痕可追溯:压缩时间、格式、校验结果、回滚路径
踩坑备忘录
- 热数据当冷数据压删 → 30+ 消费脚本断链(最高教训)
- 上万文件
rm *.json超命令行参数上限 → 用find -delete分批 - 行情价格常 ×100 整数存储 → 展示需 /100
- 同列 int/float 混存 → 无损转换前验证小数部分为 0
- zlib 聚合只减文件数不提升压缩比 → 要提升压缩比用 zstd 大窗口
- lzma 大文件耗时 10 倍 → 压缩比收益仅 +0.5:1,不值
- Reed-Solomon 块 >255 字节(GF(2^8) 域上限)→ 冗余膨胀 + 修复失败,块 ≤255
- Windows 删海量小文件耗时巨大(实测数万小文件删了约 25 分钟)→ 主因 Windows Defender 实时防护对每个删除动作扫描 + 系统盘 I/O 竞争;PowerShell Remove-Item / find -delete / Python 逐个 os.remove / .NET Delete 四种方式都慢或遇中断。对策:避免逐个 os.remove;按子目录分批删 + 接受耗时;或(需授权)临时暂停实时防护再删。预留删除时间,别当小文件删得快。
故障场景预案(前人经验 → 假设我们遇到 → 怎么处理)
> 无法预判会出什么错,但可以用业界踩过的坑做跳板,预演「我们也遇到」时的处理路径。
| 前人经验场景 | 假设我们也遇到 | 我们的处理(已落地) |
|---|---|---|
| 下载中断/磁盘坏道 → 压缩包损坏 | .gz 解不开 | SHA-256 检出 → --repair 用 .rec 修复 → 还原 |
| 误删热数据 → 断链灾难(我们踩过) | 删错数据 | 删原文三道闸(全量校验 + --confirm-cold 热冷声明 + 确认) |
| 高波动期压缩比暴跌(12:1→4:1) | 压了没省多少 | 按「正常/高波动」双档评估 + 压实度权衡,不追极限 |
| 去重仓库单块损坏毒害多快照 | 若未来做去重 | 定期 check + 分块校验 + 每快照独立哈希 |
| 恢复块(.rec)本身也损坏 | 损坏超出冗余上限 | 冗余率设够(5% 可修 2.5%)+ .rec 独立存 + 校验 |
| 解压时磁盘空间不足 | 解压到一半磁盘满 | 台账标「解压所需空间」+ 解压前查可用空间 |
| 压缩时数据还在被写 | 压到半写文件 | 压缩前确认数据静止(停写者/等任务结束) |
| 编码变更后旧文件解不了 | 旧 .gz 格式不兼容 | format_version 记录 + 解析器兼容旧版 |
| 哈希清单被篡改/损坏 | 假警报/漏检 | files_index 单一事实源 + checksums 兜底 |
| 中文内容被误判二进制 | 漏压中文文本 | UTF-8 解码 + 替换字符比例 <5% 判文本 |
| 海量小文件删除耗时巨大 | 删几万小文件卡很久 | 按子目录分批删 + 预留时间;别逐个删;必要时暂停实时防护 |
原则:每个场景「先检测 → 再修复 → 兜底还原」,检测靠 SHA-256/verify,修复靠 .rec/PAR2,兜底靠第二副本。缺一环就补一环,而不是出事了才想。
v1.7.0 · 方法论通用可复制 · 工具参数化可移植
版本历史
| 版本 | 日期 | 变更 |
|---|---|---|
| 1.0.0 | 2026-08-21 | 初版:识别热冷 + 无损压缩 + 台账三件套 + 脱敏 |
| 1.1.0 | 2026-08-21 | 炼器精炼 8 盲点:压缩比动态/数据静止/CRC32/聚合容灾/解压空间/--price-div/台账增量/脚本路径 |
| 1.2.0 | 2026-08-21 | 混合目录 --auto + 隐私边界 + 支持/不支持格式白黑名单 + 不可压三选一 |
| 1.3.0 | 2026-08-21 | 完整性升级:SHA-256 + checksums.sha256 + verify 定期校验(bit-rot)+ 解压抽验 |
| 1.4.0 | 2026-08-21 | PAR2 恢复块(--recovery·Reed-Solomon 块内纠错·损坏可修复)+ 删原文三道闸(--delete/--confirm-cold)+ 压实度权衡默认 level6 + 热/冷教训上首屏 |
| 1.5.0 | 2026-08-21 | 台账 v2:自动扫描 cold_archive/ 子目录(新增归档目录自动入账·不再硬编码)+ 文件级索引 KB→字节级精确记录(gz_bytes/raw_bytes·消除整除取整丢精度)+ 冷数据认知链(压缩≠提炼·过度提炼无效·三层完整性) |
| 1.6.0 | 2026-08-21 | 压实度重定 level9(极限压缩暴露问题·稳定再放松)+ 保护值 3KB(整个压缩包超过3KB·管包不管单个文件)+ 聚合压缩 --aggregate(多个小文件聚合 tar.gz·单个小文件不单独压)+ 内存流式优化(分块读+及时 del+gc.collect 防累积) |
| 1.6.1 | 2026-08-21 | 踩坑+预案补充:Windows 删海量小文件耗时巨大(Defender 实时防护+系统盘 I/O·数万小文件删约 25 分钟)→ 按子目录分批删+预留时间·避免逐个 os.remove |
| 1.7.0 | 2026-08-21 | 定名「如意乾坤袋」·里外统一改名 qiankun-pouch(目录/SKILL.md/脚本/zip 五处零残留)+ tagline「袋口一张,天地山海皆入其中」+ 定位句「股票历史数据·数字精度高·偏差小·字节级校准」 |