GoshawkDB:一个分布式、支持事务与容错的对象存储

  • 张龙

2016 年 1 月 10 日

话题:数据库语言 & 开发

在经过了 10 个月的全力开发后,GoshawkDB 0.1 发布了。这是 GoshawkDB 的首个公开发布版本,但该版本还是 Beta 版,因此不建议在生产环境下使用。同时,GoshawkDB 服务端二进制文件现在已经可以下载,Go 客户端(Go gettable)也可以使用了。

GoshawkDB 是一个对象存储,提供了完全的事务支持、直观的语义、分布式、高性能的 CP 系统、冗余、无模式以及安全等特性。

GoshawkDB 的主要特性列举如下:

对象存储

在编程语言中,你会通过对象而不是行或列来对数据进行建模。GoshawkDB 是个对象存储,因此无需将对象转换为表项目,然后再转换回来:你所使用的只是持久化对象而已。这种直观且简单的做法与编程语言之间形成了非常自然的吻合关系。任何对象图都是可以接受的:它并没有施加什么限制,因此在使用 GoshawkDB 时,你无需改变自己对数据进行建模的方式。对象图的导航以及资源探测都是通过从根对象进行遍历的,根对象是在 GoshawkDB 首次启动时由其所创建的。连接到 GoshawkDB 集群的所有客户端都会知道这个根对象,并且会从这个对象开始进行导航。对象值就是普通的字节数组:GoshawkDB 不要求使用模式,因此无需解释对象值。这意味着你可以自由使用任何对象序列化格式:从 JSON 到 ProtoBuf,再到 CapnProto 等等。这样,对象就是多语言的了,你只需选择一种序列化格式即可。此外,这还表示你可以自由加密对象值,因为 GoshawkDB 根本就不会检测他们:他们对于 GoshawkDB 来说是完全透明的。

完全的事务支持

GoshawkDB 支持完全的多对象事务,事务是原子和隔离的,无论事务中包含了多少对象,无论这些对象存储在哪里都是如此。GoshawkDB 客户端支持嵌套事务,诸如 Retry 等高级特性使得 GoshawkDB 的事务变得异常强大和灵活。

直观的语义

如果语义不明确或是非常复杂,那么使用任何数据存储都是毫无意义的。GoshawkDB 对于事务只支持最强的序列化隔离级别。这是最简单,也是最直观的隔离级别。GoshawkDB 对于在失败的情况下应该如何做进行了明确的保证,这可以确保你的理解与系统的行为之间不会出现任何偏差。

分布式

GoshawkDB 是个分布式数据存储,无论在云端还是自己的数据中心都如此。结点集群会呈现出一种逻辑存储,独特且改进过的一致性哈希形式确保了对象与负载会均匀地散落在各个结点上,同时还提供了可配置的冗余级别。客户端可以连接到任何结点来访问数据存储;所有结点都是等同的。

在传统数据库中,数据是存储在服务器上的,你需要向服务器发送请求。这样,在传统的 SQL 事务中,你对数据库所执行的每个操作都会在客户端与服务器之间形成一个来回的通信。服务器还会追踪你所执行的所有操作,一旦操作完成,它就会以某种方式来验证这些动作不会违背隔离级别的要求。这会导致非常长且复杂的 SQL 查询,从而减小客户端与服务器之间的来回通信以及事务长度,甚至还会要求我们使用存储过程。

GoshawkDB 的设计则是完全不同的。在 GoshawkDB 中,事务只运行在客户端。你可以将客户端看作是服务器所存储的对象的不完整缓存。事务是完全运行在客户端的。所有对象的读、创建与写入都是在客户端累积到一起的,然后一次性发送给服务器进行验证。这样,如果客户端的对象缓存合法,那么无论事务有多么长,客户端与服务器之间只有一次来回通信。如果由于其他客户端的修改导致当前客户端的缓存过期了,那么服务器就会拒绝事务,并要求该客户端重新运行并更新缓存。客户端只需应用更新,然后自动重新运行事务即可。

由于这一点,事务就变成了普通的功能,它会使用客户端 API 来检测并修改对象。我们无需再去使用类似于 SQL 这样的语言。客户端会负责在必要的情况下自动重新运行事务。这也意味着在某些情况下,GoshawkDB 是无锁的:一个事务的动作可能永远不会导致另一个事务被锁定,从而无法继续进行,死锁也就不会发生了。不过,在客户端提交事务修改前,事务可能需要运行多次,这些修改会成功通过验证并应用到数据存储上。

高性能的 CP 系统

GoshawkDB 是个 CP 系统(Consistency,Partition Tolerance)。这意味着当出现失败或是分区状况时不会导致一致性问题;相比于 AP 系统(Availability,Partition Tolerance)来说,它不会欺骗你。有证据表明 CP 系统要做的事情比 AP 系统要多,因此速度上不会很快,不过 GoshawkDB 独特的设计考虑到了性能与网络问题。GoshawkDB 只会在必要时开启事务。与其他很多分布式 CP 数据存储不同,对于不变负载来说,GoshawkDB 的性能并不会随着结点的增加而有所降低,相反性能还会得到提升。

冗余

GoshawkDB 在多个结点上维护了每个对象的副本。它并未使用 leader/follower 设计方式:所有结点都是等同的,每个对象的所有副本也都是等同的。事务只需要与每个对象的大多数副本进行通信即可进行,因此 GoshawkDB 可以在失败的情况下继续处理,只要每个对象的大多数副本依然可以使用即可。每个对象的副本数量可能会比集群中的结点数少:GoshawkDB 是分片的。GoshawkDB 使用了 Paxos Synod 协议来实现一致性。对象的修改会在客户端知道事务结果之前被写到磁盘上。

无模式

GoshawkDB 并不要求对数据使用模式;GoshawkDB 将对象值看作是普通的字节数组,你可以根据自身情况选择适合的序列化格式。唯一的要求就是要显式声明指向其他对象的指针:如果对象 x 包含了对对象 y 的指针,那么你需要让 GoshawkDB 知道这一点。

安全

服务器结点之间的所有通信都是通过 NaCl crypto 库加密的。客户端与服务器结点之间的所有通信也都是通过 NaCl crypto 库加密的,同时客户端连接是需要认证的(使用用户名与密码)。

GoshawkDB 服务器是免费提供的,基于 GNU Affero General Public License 3.0。同时也可以使用商业许可。GoshawkDB Server 0.1 - Linux 64-bit x86(10587576 字节)的 sha1sum 是 5084891dcac0d606a0c30df257310fba18e1052a。可以通过 Mercurial 浏览并克隆其源代码。目前,其预构建的二进制文件只针对 64-bit x86 Linux。GoshawkDB 可以在支持 Go 与 LMDB 的平台上进行构建。其源代码在 GitHub 上也有镜像

数据库语言 & 开发