存储模型
该存储采用两级结构:操作
这些操作由协议中描述的 Host 契约定义。读取一个值
读取请求包含:
响应包含一个
found 布尔值和一个 value 字节序列。键不存在并不是一种错误:found 为 false,且不返回值。
读取一个值不会创建其命名空间或键。
写入一个值
写入请求包含相同的namespace 和 key 字段,此外还有:
写入一个已存在的键会替换其值。当写入被拒绝时(例如该命名空间是只读的),该操作会返回一个错误字符串。
删除一个值
删除请求包含namespace 和 key。删除一个已存在的键会移除其值;删除一个不存在的键会成功执行,且不会改变该存储。
当删除被拒绝时(包括尝试从只读命名空间中删除),该操作会返回一个错误字符串。
列出键
列表请求包含一个namespace 字段:
- 当
namespace非空时,响应包含该命名空间中当前存在的键。 - 当
namespace为空时,响应包含存储中当前存在的所有命名空间的名称。
生命周期与持久性
内核在创建服务管理器时创建该 KV 存储。该存储位于内存中:- 停止或重启一个服务不会清除其 KV 值;
- 加载同一服务的新版本不会清除其 KV 值;以及
- 重启内核会创建一个新的空存储,并清除所有值。
并发与值的所有权
内核会对每一次 KV 操作进行同步。当多个服务并发调用时,读取、写入、删除和列出操作都是安全的。 不存在事务或比较并交换(compare-and-swap)操作。类似”读取、修改、写入”这样的一系列操作,相对于另一个服务而言并不是原子的。如果多个服务更新同一个键,请协调好所有权,或者设计好值的结构,使丢失更新不会破坏应用状态。 内核在存储和读取字节值时都会进行拷贝。在写入之后修改一个字节缓冲区不会改变已存储的值,修改一个返回的缓冲区也不会改变存储中的值。sys 命名空间
sys 是一个由内核管理的只读命名空间。服务可以读取和列出它,但通过服务的 host 边界进行的写入和删除都会返回错误。
内核使用该命名空间保存主机管理的状态,包括服务注册表信息——例如,sys/service/catalog/<name> 用于保存扫描到的包元数据,sys/service/<instance-id> 用于保存某个运行实例已注册的路由和传输。请不要写入 sys,也不要依赖未在文档中说明的系统键,除非内核文档明确定义了它们。
后端行为
WASM 和 gRPC 服务使用相同的 KV 契约:- WASM 服务通过生成的 host 绑定访问该存储;以及
- gRPC 服务通过内核的 host 回调通道访问该存储。
static 服务没有代码,永远不会自己调用这些操作。
推荐用法
请使用可预测的命名空间和键方案:found 结果,处理好写入和删除的错误,并且不要把一次成功的写入当作持久化保证。