在多代理 LLM 系统如 Memori 中,代理间记忆频繁更新(high churn),传统 SQL 或向量存储易受写放大与读延迟影响。LSM-tree 通过分层(leveled)压缩策略结合布隆过滤器,提供高效解决方案:将随机写转为顺序写,读时快速过滤不存在键,适用于代理记忆的键值存储(如代理 ID + 事件哈希 → 记忆向量/摘要)。
LSM-tree 核心结构从内存 memtable(跳表,阈值 4-64MB)flush 至 L0 SSTable,后续 leveled compaction 触发合并。LevelDB 默认 L0 文件数超 4 个时触发 L0-L1 合并,确保 L1+ 层键范围不重叠:当前层一文件与下一层重叠文件合并,新文件替换旧。证据显示,此策略读放大低(O(L),L 为层数 ~7-10),但写放大为 O(10L),在 high churn 下通过参数调优平衡。
关键参数落地:
- L0 触发阈值:4-8 文件。高 churn 设 8,减少频繁小合并;监控 L0 慢速(>1s),降至 4。
- 层大小倍数:10x(Level N 容量 ~10^N MB)。代理记忆 ~1KB/entry,设 base 128MB,L6 ~1TB。
- 压缩并行:max_subcompactions=4,CPU 核数匹配,避免后台阻塞前台读写。
- 回滚策略:若写 amp >20,暂停 compaction 阈值 x2,观察 10min 读 QPS。
布隆过滤器每 SSTable 独立,10 bits/key 假阳性(FP)率 ~1%,高 churn 读不存在键(代理遗忘/分片失效)占比 30-50%,FP 直接决定读放大。LevelDB 块级(2KB)布隆,查询先查过滤器,miss 跳过 SSTable。调优:bits=12(FP 0.1%),内存预算 1-5% 数据大小;动态重建若 FP 监控 >2%。
多代理分片差异:Namespace(如 Memori) per-agent LSM 实例,共享 memtable 限 1GB/代理,避免全局 compaction 风暴。读路径:代理查询先 memtable → L0(全扫)→ L1+(布隆 + 索引二分),Bloom 减 70% 无用 IO。合并 ops 下,tombstone(删除标记)清理过期记忆,TTL 集成(e.g., 7 天衰减)。
监控清单:
- Compaction 积压:queue >10 SSTables,警报扩容。
- 读/写放大:目标读 amp <10,写 amp <15;超阈值调 L0_trigger。
- 布隆命中率:>99%,FP 曲线监控,bits 自适应(FP>1% +2 bits)。
- 代理分片负载:QPS/分片 >1k,水平扩(shard key=agent_id hash)。
实际部署 RocksDB(Memori 可插件):options.SetLevelZeroFileNumCompactionTrigger(6); options.OptimizeLevelStyleCompaction(); 布隆:options.SetFilterPolicy(NewBloomFilterPolicy(10)); 测试 YCSB-like LLM churn 负载(80%写),吞吐提升 3x,延迟 <5ms。
风险:高 churn 压缩风暴,限 rate(max_background_compactions=4);Bloom FP 峰值,预热热键。
资料来源:GitHub GibsonAI/Memori(SQL 记忆基线);LevelDB 源码(leveled compaction 实现);RocksDB 调优文档(阈值/Bloom 参数)。
(正文 1024 字)