简介 - 图1

SpacetimeDB 是一种关系型数据库系统,可让你通过称为"modules"的存储过程将应用程序逻辑直接上载到数据库中。

你的客户端无需在客户端和数据库之间部署网络或游戏服务器,而是直接连接到数据库,在数据库内部执行您的应用逻辑。你可以像在普通服务器中一样,在模块中编写所有权限和授权逻辑。

这意味着你可以用一种语言 Rust 编写整个应用程序,并将其部署为一个二进制文件。不再有微服务、不再有容器、不再有 Kubernetes、不再有 Docker、不再有虚拟机、不再有 DevOps、不再有基础设施、不再有运营、不再有服务器。

它实际上类似于智能合约的想法,只不过SpacetimeDB是一个数据库,与区块链无关,并且比任何智能合约系统快几个数量级。

事实上它的速度非常之快,以至于大型多人在线角色扮演游戏 BitCraft Online的整个后端就只是一个 SpacetimeDB 模块。没有运行任何其他服务器或服务,这意味着游戏中的所有内容,所有聊天消息、物品、资源、地形,甚至玩家的位置都由数据库存储和处理,然后再同步出去实时发送给所有客户。

SpacetimeDB 针对最大速度和最小延迟进行了优化,而不是针对批处理或 OLAP 工作负载。它旨在用于游戏、聊天和协作工具等实时应用程序。

这种速度和延迟是通过将所有应用程序状态保存在内存中,同时将数据保留在用于恢复应用程序状态的预写日志 (WAL) 中来实现的。

安装

SpacetimeDB 是一个嵌入式数据库库,你可以用它来扩展自己的应用程序。你还可以通过 spacetime CLI 工具将 SpacetimeDB 作为独立的数据库服务器运行。

你可以通过 Cargo、Docker 或在我们网站上运行安装指令来安装和运行 spacetime CLI 工具:https://spacetimedb.com/install

在 macOS 上安装

在 macOS 上安装 SpacetimeDB 非常简单,只需下载二进制文件并运行即可。你还可以使用下面的 Docker 指令进行安装。

  1. curl --proto '=https' --tlsv1.2 -sSf https://install.spacetimedb.com | sh

在 Linux 上安装

在 Linux(或其他 Unix 操作系统)上安装 SpacetimeDB 也很简单,只需下载二进制文件并运行即可。你还可以使用下面的 Docker 指令进行安装。

  1. curl --proto '=https' --tlsv1.2 -sSf https://install.spacetimedb.com | sh

在 Windows 上安装

在终端中运行以下命令,并按照屏幕上的指示安装 spacetime CLI 工具和 SpacetimeDB 独立服务器。

  1. iwr https://windows.spacetimedb.com -useb | iex

使用 Cargo 安装

如果你想从源码构建 spacetime CLI 工具,可以使用 Cargo 进行安装。

  1. cargo install spacetimedb-cli

从源码安装

在 macOS 和 Linux 上,安装过程非常简单。只需在终端中运行以下命令:

  1. # 安装 rustup(如果你已经安装了 Cargo 和 wasm32-unknown-unknown 目标,可以跳过此步骤)
  2. curl https://sh.rustup.rs -sSf | sh
  3. # 克隆 SpacetimeDB 仓库
  4. git clone https://github.com/clockworklabs/SpacetimeDB
  5. # 构建并安装 CLI
  6. cd SpacetimeDB
  7. cargo install --path ./crates/cli --locked

在 Windows 上,可能需要额外安装一些依赖项,包括 OpenSSL 和特定版本的 Perl。相关指南即将发布。

使用 Docker 运行

你可以使用 Docker 运行 spacetime CLI 工具,以运行 SpacetimeDB 独立服务器,而无需安装任何命令行工具或其他依赖项。

  1. docker run --rm --pull always --name spacetimedb -p 3000:80 clockworklabs/spacetimedb:latest start

文档

关于 SpacetimeDB 的更多信息,包括入门指南、游戏开发指南和参考资料,请访问我们的文档页面

快速开始

我们为每种支持的语言准备了多个入门指南,帮助你快速上手 SpacetimeDB。你可以在我们的文档页面找到它们。

简而言之,使用 SpacetimeDB 只需 4 个步骤:

  1. 安装 spacetime CLI 工具。
  2. 使用 spacetime start 启动一个 SpacetimeDB 独立节点。
  3. 使用支持的模块语言编写并上传模块。
  4. 通过客户端库连接到数据库。

你可以在下方查看支持的语言列表,并找到相应的入门指南链接。

语言支持

你可以使用多种流行的编程语言编写 SpacetimeDB 模块,并且未来还会支持更多语言!

状态镜像

SpacetimeDB 可以生成多种语言的客户端代码 variety of languages。这创建了一个专门设计与数据库通信的客户端库。它提供了简易的接口,用于连接数据库并提交请求。它还可以 自动镜像 数据库的状态到客户端应用。

您编写 SQL 查询,指定客户端感兴趣的信息——例如,玩家头像附近的地形和物品。SpacetimeDB 会在您的客户端语言中为相关的表生成类型,并在数据库状态变化时向客户端推送实时更新流。请注意,这只是一个 只读 镜像——更改数据库的唯一方式是提交经过服务器验证的请求。

语言支持

模块库

每个 SpacetimeDB 数据库都包含一系列 存储过程 和模式定义。这些集合被称为 模块,可以用 C# 或 Rust 编写。它们指定了数据库的模式和响应客户端请求的业务逻辑。模块使用 spacetime CLI 工具进行管理。

客户端 SDK

客户端 是连接到 SpacetimeDB 数据库的应用程序。spacetime CLI 工具支持自动生成接口代码,使得与特定数据库的交互变得更加容易。

Unity

SpacetimeDB 首先作为多人 Unity 游戏的后端设计。要了解更多关于如何在 Unity 中使用 SpacetimeDB,请访问 SpacetimeDB Unity 教程

关键架构概念

主机

SpacetimeDB 主机 是一个托管 数据库 的服务器。您可以运行自己的主机,或者使用 SpacetimeDB 的主云。多个数据库可以在同一主机上运行。

数据库

SpacetimeDB 数据库 是在 主机 上运行的应用程序。

数据库导出 ,用来存储数据,并导出 reducer,允许 客户端 发起请求。

数据库的模式和业务逻辑由一个名为 模块 的软件指定。模块可以用 C# 或 Rust 编写。

(从技术上讲,SpacetimeDB 模块是一个 WebAssembly 模块,它导入了一个特定的低级 WebAssembly ABI,并导出少量的特殊函数。然而,SpacetimeDB 服务器端库 隐藏了这些底层细节。作为开发者,编写模块大致就像编写任何其他 C# 或 Rust 应用程序,唯一不同的是使用一个 特别的 CLI 工具 来部署该应用程序。)

SpacetimeDB 是 SQL 数据库表。表在模块的本地语言中声明。例如,在 C# 中,表声明如下:

  1. [SpacetimeDB.Table(Name = "players", Public = true)]
  2. public partial struct Player
  3. {
  4. [SpacetimeDB.PrimaryKey]
  5. uint playerId;
  6. string name;
  7. uint age;
  8. Identity user;
  9. }

表的内容可以通过 reducer 进行读取和更新。标记为 public 的表也可以被 客户端 读取。

Reducer

Reducer 是数据库导出的一个函数。连接的 客户端 可以调用 reducer 来与数据库进行交互。这是一种 远程过程调用

:::server-rust 一个 reducer 可以这样用 Rust 编写:

  1. #[spacetimedb::reducer]
  2. pub fn set_player_name(ctx: &spacetimedb::ReducerContext, id: u64, name: String) -> Result<(), String> {
  3. // ...
  4. }

一个 Rust 客户端 可以调用该 reducer:

  1. fn main() {
  2. // ...设置代码,然后...
  3. ctx.reducers.set_player_name(57, "Marceline".into());
  4. }

::: :::server-csharp 一个 reducer 可以这样用 C# 编写:

  1. [SpacetimeDB.Reducer]
  2. public static void SetPlayerName(ReducerContext ctx, uint playerId, string name)
  3. {
  4. // ...
  5. }

一个 C# 客户端 可以调用该 reducer:

  1. void Main() {
  2. // ...设置代码,然后...
  3. Connection.Reducer.SetPlayerName(57, "Marceline");
  4. }

:::

这些看起来大致像常规的函数调用,但在幕后,客户端通过互联网发送请求,数据库处理并响应该请求。

ReducerContext 是一个 reducer 的唯一必需参数,包含有关调用者的 身份 信息。这可以用于验证调用者。

Reducers 在独立的、原子性的 数据库事务 中运行。当 reducer 成功完成时,它所做的更改(例如插入表行)将被 提交 到数据库。但是,如果 reducer 返回错误或抛出异常,数据库将拒绝请求并 回滚 所有更改。也就是说,reducer 和事务都是原子请求,不能只保留其中一部分更改。

事务只会由外部请求启动。当一个 reducer 直接调用另一个 reducer 时,如下面的示例所示,调用的 reducer 所做的更改并不会发生在自己的子事务中。相反,当嵌套的 reducer 出现错误并且总体 reducer 成功完成时,嵌套的更改仍然会被持久化。

:::server-rust

  1. #[spacetimedb::reducer]
  2. pub fn hello(ctx: &spacetimedb::ReducerContext) -> Result<(), String> {
  3. if world(ctx).is_err() {
  4. other_changes(ctx);
  5. }
  6. }
  7. #[spacetimedb::reducer]
  8. pub fn world(ctx: &spacetimedb::ReducerContext) -> Result<(), String> {
  9. clear_all_tables(ctx);
  10. }

::: :::server-csharp

  1. [SpacetimeDB.Reducer]
  2. public static void Hello(ReducerContext ctx)
  3. {
  4. if(!World(ctx))
  5. {
  6. OtherChanges(ctx);
  7. }
  8. }
  9. [SpacetimeDB.Reducer]
  10. public static void World(ReducerContext ctx)
  11. {
  12. ClearAllTables(ctx);
  13. // ...
  14. }

:::

:::server-rust 虽然 SpacetimeDB 不支持嵌套事务,但一个 reducer 可以 安排另一个 reducer 在特定时间间隔或特定时间运行。 ::: :::server-csharp 虽然 SpacetimeDB 不支持嵌套事务,但一个 reducer 可以 安排另一个 reducer 在特定时间间隔或特定时间运行。 :::

客户端

客户端 是连接到 数据库 的应用程序。客户端使用 身份 登录并接收一个 连接 ID 以标识该连接。之后,它可以调用 reducer 并查询公共

客户端是使用 客户端 SDK 编写的。spacetime CLI 工具允许自动生成与客户端 SDK 配合使用的代码,以便与特定数据库进行通信。

客户端是常规软件应用程序,开发者可以选择如何部署(通过 Steam、应用商店、包管理器或其他任何软件部署方式,具体取决于应用程序的需求)。

身份

SpacetimeDB Identity 用于标识与模块交互的用户。它是一个长期有效的公共、全球有效的标识符,总是指代同一个终端用户,即使在不同的连接中也是如此。

用户的 Identity 附加到他们每次调用的 reducer,您可以使用它来决定他们被允许执行的操作。

模块本身也有 Identity。当您执行 spacetime publish 发布一个模块时,它会自动获得一个 Identity 来区分它与其他模块。您的客户端应用程序需要在连接到 主机 时提供此 Identity

身份是通过 OpenID Connect 规范颁发的。数据库开发人员负责为他们的最终用户颁发身份。OpenID Connect 允许用户通过 Google 和 Facebook 等标准服务登录到这些帐户。

具体来说,身份是通过将 JSON Web Token (JWT) 的颁发者和主题字段进行哈希计算得出的。伪代码如下:

  1. def identity_from_claims(issuer: str, subject: str) -> [u8; 32]:
  2. hash1: [u8; 32] = blake3_hash(issuer + "|" + subject)
  3. id_hash: [u8; 26] = hash1[:26]
  4. checksum_hash: [u8; 32] = blake3_hash([
  5. 0xC2,
  6. 0x00,
  7. *id_hash
  8. ])
  9. identity_big_endian_bytes: [u8; 32] = [
  10. 0xC2,
  11. 0x00,
  12. *checksum_hash[:4],
  13. *id_hash
  14. ]
  15. return identity_big_endian_bytes

连接 ID

ConnectionId 标识客户端与 SpacetimeDB 模块的连接。

一个用户有一个单一的 Identity,但可以打开与模块的多个连接。每个连接将接收到一个唯一的 ConnectionId

能量

能量 是在 SpacetimeDB 主机中用于支付数据存储和计算操作的货币。

常见问题解答

  1. 什么是 SpacetimeDB? 它是一个足够快速以运行实时游戏的数据库云平台。

  2. 如何使用 SpacetimeDB? 安装 spacetime 命令行工具,选择您喜欢的语言,导入 SpacetimeDB 库,编写模块,编译成 WebAssembly,然后将其上传到 SpacetimeDB 云平台。上传后,您可以直接在应用程序上调用函数并订阅状态更改。

  3. 如何获取/安装 SpacetimeDB? 只需安装我们的命令行工具,然后将应用程序上传到云端。

  4. 如何使用 SpacetimeDB 创建新数据库? 请参考我们的 快速入门 指南!

  5. 如何用 SpacetimeDB 创建 Unity 游戏? 请参考我们的 Unity 教程 指南!