当前版本:v0.25.2 — 所有发布。
一句话概括: Slater 服务于无法放入内存的图——数亿个节点和数十亿条边仅占用几百 MB 内存——通过标准 Bolt 协议提供服务,因此任何 neo4j 驱动都能直接使用;磁盘原生的向量搜索紧邻图而生,并且它在不放弃这一切的同时接受实时、持久的写入。常驻内存由你选择的缓存预算决定,而不是由图的大小决定。
快捷入口
| 为什么存在 Slater | 读取与写入 | 你会得到什么 | 功能特性 |
| 使用 Docker 运行 | 工作原理 | 可写层 | 存储后端(文件系统 / S3 / GCS) |
| 挂载 | 环境与配置 | ACL | 健康检查 |
| 实操示例 | 开发 | 性能 | 许可证 |
| Graphiti 记忆存储 | 📖 完整手册 |
图数据库将数据存储为事物(节点)以及它们之间的关系(边),关系是一等公民。当你关注的是连接而非行时,这正是你想要的——“谁在这个账户三跳之内?”、“这次构建背后的完整依赖链是什么?”、“哪些账户共享设备、地址和银行卡?”——这些查询在 SQL 中会成为递归连接的泥潭,但在图中却自然呈现。
关于图数据库最常见的抱怨是:它们无法扩展到超出内存能容纳的规模。 其中许多(如 neo4j、Memgraph、FalkorDB 等)将整个图常驻内存:一个 40 GB 的图就需要 40 GB 内存——每个实例。想按区域、按租户或按 Pod 各放一个副本?账单成倍增加。而且一旦超过一定规模,它们根本无法加载:例如 9000 万节点 / 15 亿边的 Wikidata 图需要约 64–128 GiB 常驻内存,因此内存引擎根本无法打开它。
Slater 是对此的反驳。它不把图加载到内存,而是离线一次性编译:slater-build 将你的数据转换为内容寻址、不可变的磁盘映像,任意数量的 Slater 服务器随后通过 Bolt 提供该映像(因此你现有的 neo4j 驱动可以直接使用),按需分页加载块,并仅保留固定的缓存预算常驻内存。正是这样,同一个 9000 万节点的图只需几百 MB 内存即可服务——图的大小与内存账单解耦。一个 4 GB 的图和一个 400 GB 的图服务所需内存相同,因此你可以廉价地横向扩展无状态只读副本,让存储而不是堆来持有图。
这使它天然适合 RAG 背后的知识图谱、推荐与身份图、依赖图——任何庞大且相互关联、你想廉价而频繁查询的数据。磁盘原生的向量搜索紧邻图而生,因此同一引擎也可作为嵌入向量的检索层。
不过,一次性编译并不意味着冻结。该映像是一个基础,而不是最终状态:一个可选的写入层位于其上,因此在线图可以被修正和扩展,而无需重建任何东西。
核心是不可变的,但图不是。启用可写层(delta.enabled)后,你可以通过 Bolt 进行写入——修正一个属性、添加一个节点、撤回一条边——变更持久生效,无需重建映像。让读取端保持廉价的关键是写入的存放位置。
写入会累积在不可变核心之上的日志结构合并(LSM)层中:一个预写日志和一张内存表,溢出为不可变的增量段,并通过定期合并(consolidation) 折回成全新的核心。这带来以下好处:
count(*)、标签与关系类型的边际统计——即使存在未完成的写入,也仍然是元数据读取:增量维护自己的计数器,因此对 9160 万节点核心且带有 50 万待处理写入执行 count(*),仍可在几十毫秒内返回结果,而无需触碰任何数据块。fsync 完成之后才返回 SUCCESS。将写入分组可以降低成本——一次写入 UNWIND 每个批次只提交一次 fsync,而不是每行一次。MERGE / MATCH … SET / DELETE(以及 CREATE / REMOVE、分离删除、关系写入)——或等价的 ISO GQL 数据修改语句(INSERT / SET / REMOVE / DELETE),它们降级到同一条路径。对节点和边进行修正、插入、upsert(插入或更新)和撤回,以你数据已有的方式来寻址。在关闭该层(默认情况)时,Slater 只提供纯粹的不可变核心,并拒绝写入。完整模型请参阅 可写层。
关于名字。 Slater 得名于 Archer(一部很棒的美剧)中的 CIA 特工, 他坚持只用一个名字——“就叫我……Slater”——也是我在这部剧中最喜欢的 角色之一。参见 角色维基页面。
MERGE / SET / DELETE,组提交并由 fsync 确保持久化,通过合并折回成全新核心。读取无需为此付出代价。current 指针,服务器即会拾取。每个块都有校验和,因此半拷贝的映像会被拒绝而不是被服务。| 功能特性 | 对你意味着什么 |
|---|---|
| 有界、可预知的内存 | 常驻内存跟踪你设定的三个缓存预算,误差在有界的每条目与分配器开销之内——它不会随图的大小增长;你调整性能/内存权衡,而不是为整个图做资源预配。带有后台清理的 jemalloc 分配器会在大量查询突发后把释放的内存归还给操作系统,因此常驻内存回落到空闲基线,而不是停留在突发后的高水位。 |
| 开箱即用的多租户 | 一台服务器托管多个图,并支持按用户的读取授权——这是大多数图数据库只在付费/企业版中提供的多数据库隔离能力。 |
| 静态与传输中加密 | 逐块 XChaCha20-Poly1305 密封(密钥从不写入磁盘),外加可选的 TLS(bolt+s://)。按构造即符合 GDPR。加密同时也是获得可认证完整性的手段:构建器用带密钥的 MAC 密封清单,持有密钥的服务器会验证它,并拒绝服务清单被伪造、篡改或被剥离 MAC 的代次。未加密钥(明文)的映像仅由无密钥的内容哈希保护——能检测完整性与损坏,但无法检测篡改。参见 每种配置中的完整性含义。 |
| 极小的安装包 | 基于 distroless glibc 的小型 stripped 二进制(无 shell/apt)——多架构(amd64/arm64)镜像拉取约 22 MB,仅服务器的 slater:latest-lite 标签约 12 MB;纯 Rust TLS,无 OpenSSL。拉取即可运行。 |
| 为定期发布而设计 | 离线构建图,以不可变方式提供服务,然后零停机原子地切换新版本——非常适合数据仓库 / 定时刷新工作负载。 |
| 负载下依然坚固 | 服务器和离线构建器都以 #![forbid(unsafe_code)] 编译——引擎中唯一的 unsafe 位于经过审计的 jemalloc 分配器 crate 中。核心不可变,因此读取无需加锁,也永远不必等待写入者;单个写入者只在写入路径上串行化变更。没有 GC 暂停,没有数据竞争。一个坏查询无法让服务器宕机。 |
| 与你现有的 neo4j 工具兼容 | 讲 Bolt 5.4 / 4.4 / 4.1——可直接使用标准 neo4j 驱动(JS、Python、Go、Java……)、cypher-shell 或图浏览器,无需修改。 |
| 丰富的 Cypher 查询面 | 广泛的读取面:MATCH/WHERE/WITH/UNION、CALL {…} 子查询、70+ 函数与聚合、时间与地理空间值,以及正则表达式。 |
| 实时、持久的写入 | 不可变核心之上可选启用的单写入者 LSM 层(delta.enabled):对节点和关系进行业务键 MERGE / SET / DELETE / CREATE / REMOVE、批处理写入 UNWIND(每批一次 fsync),以及 CALL slater.consolidate()——组提交、fsync 持久化,并通过合并折回成全新核心。当增量为空时,读取路径逐字节一致。 |
| ISO GQL,读写皆可 | 在同一个 Bolt 连接上讲 ISO GQL(ISO/IEC 39075)子集——量化路径、路径限制器、最短路径选择器、标签/类型布尔表达式、FOR、CAST、可选的 GQL/CYPHER 方言前缀——并且当可写层开启时,GQL 的数据修改语句(INSERT / SET / REMOVE / [DETACH] DELETE)降级到同一条持久写入路径。Cypher 与 GQL,读取与写入,同一引擎内实现。 |
| 向量 + 图,同一引擎 | 磁盘原生的 ANN 向量搜索(Vamana + PQ;cosine / L2 / dot),用于嵌入/RAG,另有图算法(PageRank、BFS、介数、WCC……)——即使有数百万向量,内存也保持有界。嵌入向量可写(FreshDiskANN 风格的写入阶梯):插入 / 更新 / 删除向量,KNN 立即可见,无需重建即可折回基础。 |
| 网络存储上安全 | 每个文件都经过 BLAKE3 内容哈希并在打开时验证;撕裂或半拷贝的映像会被拒绝而不是被服务。专为 NFS/远程卷设计(没有 mmap 的意外)。 |
| 可插拔的存储后端 | 从本地文件系统、S3(S3 兼容)存储桶或 Google Cloud Storage 存储桶提供相同的代次格式——发布一次,横向扩展到无状态副本——并可在对象存储前放置可选的本地 SSD 缓存层。参见 存储后端(文件系统 / S3 / GCS)。 |
工作区由两个二进制文件组成:
| 二进制 | 角色 |
|---|---|
slater | 在线 Bolt 服务器(容器 ENTRYPOINT):提供读取,并在启用 delta.enabled 时提供单写入者持久写入路径。 |
slater-build | 离线编译器:将基础 Cypher 转储转换为不可变、内容哈希的代次目录。 |
Slater 将批量构建与服务分离:slater-build 在离线状态下完成繁重工作——摄取你的数据并将其编译为不可变代次——因此冷图永远不会在服务热路径上组装。在服务器内部,读取面回答广泛的 Cypher 子集——模式匹配、WITH/UNION/CALL {…} 子查询、70+ 标量与聚合函数、时间与地理空间值、图算法(algo.*)以及磁盘原生向量 KNN(db.idx.vector.queryNodes)——而可写层的增量覆盖层位于该读取面之下,为空时零成本,因此读取永远不会携带写入侧的机制。你可以通过两种方式更新图:通过 Bolt 实时写入(参见 可写层),或离线构建新代次并原子地切换 current 指针,运行中的服务器通过其代次守卫(generation guard)拾取该指针(参见 代次守卫)。
完整的用户手册位于 docs/manual/——这是一份逐功能指南,针对每项能力解释它是什么、为什么存在以及如何使用,并带有可在随附示例图上运行的实操示例。凡超出本概述的内容,请从那里开始。