如何压缩冷数据?
解读
在国内金融、政企、IoT 等 CouchDB 落地场景中,冷数据通常指 90 天~1 年未被读写、但仍需保留合规的 JSON 文档。面试官问“压缩”不仅是磁盘瘦身,更关注合规、可逆、零停机、可回滚四个硬性指标。回答必须给出“CouchDB 原生能力 + 国内机房限制 + 审计要求”三位一体的落地方案,而不是简单一句“gzip 一下”。
知识点
- CouchDB 存储模型:B+ 树追加写,删除/更新产生旧版本(tombstone & revision tree),冷数据实际=大量历史 revision + 未被压缩的附件。
- 国内等保 2.0 要求:冷数据压缩后仍须可秒级还原、哈希校验、操作审计日志 180 天以上。
- 压缩层级:
- 文件系统层:ZFS/zstd、ext4 + e4defrag,需运维权限,不适合云托管版 CouchDB。
- CouchDB 内置:
_compact仅清理 tombstone,不会跨 revision 去重;_replicate过滤同步可把冷库缩到最小。 - 业务层:按“库-分区-日期”切分,历史分区离线压缩成 带签名的 tar.zst,原库删除并保留
digest + 审计链。
- 附件二次压缩:JSON 附件若原为
base64,先转二进制再 zstd,平均再降 40%;压缩后把content_type改为application/zstd,并写入x-couch-attachment-meta:{compressor:'zstd',level:3,sha256:'...'}。 - 还原链路:国内机房常禁外网,压缩包必须存入内网 MinIO 或华为云 OBS 私有桶;还原时通过
_bulk_docs带new_edits:false写回,确保 revision 不变。
答案
分五步落地,全部可在零停机下完成:
- 识别冷范围:用
_find+ 索引{"lastAccess":{"$lt":"2023-06-01T00:00:00"}}拉出 docid 列表,写入本地冷名单文件,MD5 留痕。 - 冷分区复制:新建
db-cold-2023q1库,通过_replicate+doc_ids把名单内文档拉过去,开启create_target":true与"batch_size":2000,复制完做一次_compact清理 tombstone。 - 附件二次压缩:写 Node 脚本遍历
db-cold-2023q1,对._attachments里>10 kB且content_type≠application/zstd的附件:- 下载二进制 → zstd level=3 → 计算新 sha256 → 更新附件 stub → 把原
content_type记录到x-couch-attachment-meta。
脚本每更新 500 条调用_bulk_docs并写审计日志(docid、旧长度、新长度、sha256、操作人、时间)。
- 下载二进制 → zstd level=3 → 计算新 sha256 → 更新附件 stub → 把原
- 离线打包:对压缩后的
db-cold-2023q1做couch-backup导出.couch文件,再用zstd -19 --long压成db-cold-2023q1.tar.zst,附加 gpg 签名(国密 SM2 亦可),上传至内网对象存储,桶策略设为“写后锁定 1 年”。 - 原库瘦身:确认 tar.zst 哈希入库后,在原库通过
_purge接口批量清除已冷 docid(需先关集群同步,避免 purge 扩散),再执行_compact释放空间;最后把冷名单、哈希、签名、操作人、审批单号写入 MySQL 审计表,保留 3 年供等保抽查。
还原时反向操作:下载 tar.zst → 验签 → 解压 → couch-restore 到临时库 → 用 _replicate 拉回生产库("create_target":false),revision 与原号段一致,业务无感。
拓展思考
- 如果集群是 CouchDB 3.x 分片 + 腾讯云 CBS 盘,第 4 步可直接用 云盘快照 替代 tar.zst,快照链自带加密与定时策略,节省 30% 运维量,但需解决快照跨账号审计问题。
- 对 附件大于 100 MB 的冷视频,可拆出到 自研 MinIO+EC 冷存,CouchDB 仅保留
external类型附件存根,实现 “DB-对象存储” 混合压缩”,此模式在广电与医疗影像场景已落地。 - 未来升级到 CouchDB 4.x,官方实验性支持 Pluggable Storage Engine,可引入 RocksDB + zstd 字典训练,对冷分区自动切换引擎,实现在线透明压缩,届时上述脚本可退化为一条
PUT /{db}/_settings {"storage":"cold_rocks"}即可,值得持续关注。