TierBlob 使用指南
TierBlob = SnapshotBase 的产品封面:无索引语义的 GB/TB 级大对象流式存取。对象句柄 = 起始
LogicalAddress(地址一等公民——写完即得、可持久化/传输、凭地址直达数据);流式会话边写边算
CRC64 不驻内存整块。设计全案见 docs/design/tierblob-spec.md(Tier 仓内部文档)。
与 TierKV 的分工(按访问模式,不按大小)
| 场景 | 用谁 |
|---|---|
| 要索引 / 点查 / 覆盖写 | TierKV(溢出分离兜底) |
| 整对象顺序写读 / 无索引 / 流式 | TierBlob |
| 随机 seek 覆写 | 都不——KV 覆盖写或 Delete+Put(新句柄) |
快速开始
var fs = TierFs.New("local:///data/tc"); // 组合根文件系统
await using var blob = await new TierBlobBuilder(fs, new TierBlobOptions
{
BlobName = "tc", // 引擎空间:{name}.blob.data / {name}.blob.meta
MaxBytes = 1L << 40, // 容量上限(null = 不限)
}).StartAsync();
// ── 整对象单发 ──
var put = await blob.PutAsync(data); // put.ObjectId = 句柄(持久化它即可)
var dst = new byte[put.Length];
await blob.GetAsync(put.ObjectId, dst); // 凭地址直达,零元数据查询
// ── 流式写(GB/TB 不驻内存)──
await using (var session = blob.OpenWrite()) // expectedLength ≥ 0 = 定长契约
{
await foreach (var chunk in ReadSourceChunkAsync())
await session.WriteAsync(chunk);
var result = await session.CompleteAsync(); // Dispose 未 Complete = Abort(尾截断回滚)
}
// ── 流式读(CRC64 逐帧校验)──
await using (var reader = blob.OpenRead(handle))
{
int n;
while ((n = await reader.ReadAsync(buf)) > 0) Consume(buf[..n]);
// 读至对象末尾自动验帧;CRC64 不符抛 IOException
}
语义要点
- 句柄 = 起始 LogicalAddress:同址即同对象(raft 形态下确定性 apply 全组同址——泛化复制继承)。
GetAsync/OpenRead免元数据查询;GetInfoAsync/ListAsync才查对象表。 - Complete / Abort 显形:
BlobWriteSessionDispose 未 Complete = Abort(尾截断回滚),与 KV 会话 Dispose 收口惯例一致。定长会话(expectedLength ≥ 0)须恰好写满,不足/超过 Complete 拒绝并回滚。 - 分配-持久分离:Complete 返回句柄 = 对象表登记已持久(表引擎 Prepare/Confirm 收口——崩溃窗口
句柄不丢);数据面 fsync 走显式
FlushAsync。 - 写入单通道:会话存活期独占写通道(结构层写尾单会话契约);不同对象并行写为 Runtime 迭代候选, 当前版本多生产者经产品写闸串行(读路径并发无锁)。
- Delete = 墓碑 + 空间保留:List/Get 即刻不可见;物理回收走
ReclaimDeletedAsync手动档 (引擎打洞 + 死亡前缀头截断)。后台自动 Compact = 候选项,不做。
恢复语义(崩溃对账)
启动时:对象表重放(meta O(1) 水位)→ 数据尾由表推导(登记帧几何权威)→ Active 对象逐个验帧:
- 损坏帧 → 标墓碑(
TierBlobOptions.DeepVerifyOnRecovery控制深度:默认帧尾级 O(1)/对象—— footer magic + TotalLength 对账;true = 整帧 CRC64 全量)。 - 孤儿帧(Complete 后登记前崩溃)→ 不可见,区间被后续写入覆盖(at-least-once:崩溃 Put 由 调用方重试产生新对象)。
Session 2PC("业务写 + 对象登记"原子)
GetParticipant() 返回对象表参与者:Prepare 后的对象登记/删除延迟提交挂 undo 链——Confirm 统一
fsync + 提交水位;Abort = 表帧尾截断 + 内存镜像逆序回退(延迟删除回退 = 对象复活)。会话期间
PutAsync/DeleteAsync 自动挂入事务。
治理
| 机制 | 说明 |
|---|---|
TierBlobOptions.MaxBytes |
超限 Put/OpenWrite fail-fast(不定长流在完成时点终判,超限回滚) |
GetStatsAsync() |
ObjectCount / TombstoneCount / Bytes(物理折算)/ ReclaimableBytes |
ReclaimDeletedAsync() |
墓碑 extent 打洞 + 死亡前缀头截断;Active 区间零触碰 |
FlushAsync() |
数据引擎 fsync 屏障 |