Session 使用指南——组合域的统一协调协议
给谁看:组合多个结构(Ring × 索引 × Log)做跨结构原子提交/排序/检查点的人。 回答什么:Session 是什么、什么时候用、怎么建域、怎么写/读/检查点、故障怎么走、什么不要做。 机制细节(管线内部/seq 语义/恢复协议)见文末链接;本篇只讲怎么用。 前置:结构层用法见
structures.md(本篇示例的 Ring/索引装配同款)。
0. 快速上手(四步,可运行)
using TC.Tier.Core.IO;
using TC.Tier.Runtime.Storage;
using TC.Tier.Runtime.Transactions;
using TC.Tier.Runtime.Structures.Ring;
using TC.Tier.Runtime.Structures.ProbingIndex;
using TC.Tier.Contracts.Structures;
// ① 建结构(照常——结构对会话零感知;装配见 structures.md §1.2)
using var fs = TierFs.New("memory:");
await using var ring = await RingOfLong.CreateAsync(new BlittableRingSettings(new StorageEngineOptions("kv-ring", 64L << 20))
{ PageSize = 4096, MemorySize = 64 * 1024, MutableFraction = 0.5 }, fs);
await using var index = await HashOfLong.CreateAsync(fs, new HashIndexSettings(new StorageEngineOptions("kv-hash", 64L << 20)), ring);
// ② 建域:fs + 名字 + 参与者全集(同结构写必经同一域)
var mgr = SessionManager.Create(fs, "kv",
HangingResolution.ForwardCommit, // 悬挂裁决域声明(缺省 forward-commit,可省)
("ring", ring), ("index", index));
mgr.Initialize(); // 悬挂裁决 + 管线启动
mgr.WaitForReady();
// ③ 写(档 B 协调):Stage 物化委托 → CommitAsync 入管线
using var session = mgr.OpenSession("writer-1");
session.Stage(() => ring.Write(key, value), tag: key); // tag = 组合层自管标识(如 key),管线不解读
session.Stage(() => index.Insert(key, addr, begin), tag: key);
long seq = await session.CommitAsync(); // 入管线 → await 自己的回执(域 seq)
// ④ 读(两档):
using (var scope = session.EnterReadScope()) // 会话读:聚合域内 epoch(零拷贝 span 护栏)
ring.GetValueSpan(addr);
var direct = ring.GetValueSpan(addr); // 地址直达:无会话零税(默认推荐)
检查点(管线串行——时机归协议,内容归组合层):
long watermark = await mgr.EnqueueCheckpoint(seq =>
{
index.CheckpointFrame(); // 内容组合层自定(Hash/SortedIndex 主存储 dump)
meta.WriteAnchor(seq); // seq = 当前已提交水位(管线传入)
});
1. 概念(术语在此定义)
- Session = 零自有存储的协调层:不做任何持久化决策——持久化真源是参与者各自的 meta 水位 (2PC 六件套本就持久)。Session 只提供排序(FIFO 全序)+ 原子性(全有或全无)+ 检查点串行。
- 域(domain):一组参与者的集合(一个
SessionManager)。同结构写必经同一域—— 跨域共享结构写 = 破坏窗口契约(§3)。 - 档:写有两档——A 直写(直接调结构写 API,无协调,须过规则 W)与 B 协调(Stage 委托 → 提交管线)。读有两档——地址直达(默认,零税)与会话读(scope 聚合 epoch)。
- staged 物化委托:
Stage只登记委托(结构零触碰);管线线程按 FIFO 序执行(纯缓冲写, 尽力不抛——抛 = 域报废)。 - 悬挂裁决(HangingResolution):恢复时"已 Prepare 未 Confirm"的悬干事务怎么处理——
ForwardCommit(缺省,前推到 prepared seq,宁可前推不丢)或DropTail(截断回已确认水位)。 - seq:域内内存排序序(每域独立);批合并下同批共享一个 seq。
- 规则 W:存在开放事务会话期间(
OpenTxCount > 0),该域参与者结构的档 A 直写必须 fail-fast ——产品面写入口统一调mgr.EnsureNoOpenTransaction()。
2. 三 op 怎么用
2.1 写(两档)
| 档 | 形态 | 何时用 |
|---|---|---|
| A 直写 | 直接调结构写 API(ring.Write 等) |
无协调需求;须过规则 W 检查 |
| B 协调 | Stage(物化委托) ×N → CommitAsync() |
需要原子性/排序/跨结构一致 |
档 B 要点:
- 业务校验放
Stage之前(此时抛无副作用);物化委托内只做纯缓冲写。 - 批合并:管线排空积压为一批——同批共享 seq、一次 Prepare-all + Confirm-all(FIFO 全序不变)。
- 回执 = 域 seq;失败后会话 Faulted(重开
OpenSession),staged 已清空——重试须重新 Stage。 - 复制域(Raft WAL):
CommitReplicatedAsync(awaitDecision, …)——物化 → Prepare-all →await awaitDecision(候选 seq)(多数派共识注入位)→ true: Confirm-all(不可回退点); false/超时: Abort →RollbackException。
2.2 读(两档)
| 档 | 形态 | 何时用 |
|---|---|---|
| 地址直达 | 自缓冲句柄直接读结构(GetValueSpan 等) |
默认——地址即句柄,零会话税 |
| 会话读 | session.EnterReadScope() |
需要协调的读:RYW 覆盖层 / scope 批量 |
会话读规范:
- scope 聚合域内全部 epoch 读保护参与者(一次进出);
- 区内只做零拷贝读(
GetValueSpan族);自带 epoch 进出的 API(Ring 写、Index 逐次Find/Insert) 区内调用 = 同实例重入,Debug 绊线立即抛——用IndexScope.Find等 scope 内单查形态; - RYW 覆盖层:组合层在
session.State上自管(staged 命令表/批号映射)——读序 = 先查覆盖层再下结构。
2.3 检查点
EnqueueCheckpoint(Action<long> plan):plan 收当前已提交水位(不消耗新 seq),与事务回合天然串行;
plan 抛 = 回执原异常,管线续跑(检查点无结构悬干)。
3. 故障模型(速查)
| 故障 | 行为 |
|---|---|
| 回合物化抛 | 域 Faulted(续跑会被后续批"洗白"悬干)——恢复 = 进程重启/新域 |
| 回合 Prepare 抛 | 自动 Abort 已 Prepare 者 → 批回执异常、会话 Faulted → 管线续跑 |
| 复制决策 false/超时 | Abort 已 Prepare 者 → RollbackException 回执 |
| 崩溃(任意时点) | 无中央 record——恢复 = 参与者自身语义 + 域声明裁决(悬挂裁决) |
| 排队中 Abort/Dispose/ct | 出队丢弃——结构零触碰、seq 零消耗 |
mgr.IsFaulted / mgr.FaultReason 观测;Faulted 后 OpenSession/入队抛。
4. 反模式(必守)
- 产品面自带排序/可见性/提交语义——协调语义只在 Session 一处定义。
- 给 Session 加任何自有存储/持久化决策(record/oracle/独立文件)——纯协调层。
- 保护区(EnterReadScope/EnterEpoch)内调自带 epoch 的 API——同实例重入,Debug 立即抛。
- 物化委托里做业务校验/可抛逻辑——校验放 Stage 前;物化抛 = 域报废。
- 给地址直达读加会话——地址即句柄,直达读永远零会话税。
- 多域共享结构写——同结构写必经同一域(窗口契约)。
- 单线程会话契约(FASTER 同款):一个会话同一时刻单线程使用(staged 缓冲与覆盖层无锁)—— 违规立即抛。
5. 想深入?指路
| 想懂什么 | 去哪 |
|---|---|
| 2PC 六件套与 Abort 窗口契约 | 各子族 API 详表 §4(ring.md §4.8 / log.md §4.5 / index.md §5) |
| 恢复协议(悬挂裁决/注入档/Confirm 不落盘语义) | 源码 Transactions/SessionManager.cs 注释 |
| 吞吐基线(回合/s 口径) | benchmarks/.../Kv/SessionPipelineProbe.cs |
| 结构层装配(Ring/索引/Log) | structures.md |