Categories
程式開發

不可变数据库的实现:类似于区块链,但没有使用区块链


本文最初发表于 SubStack 博客,经原作者授权,InfoQ 中文站翻译并分享。

导读:不可变数据库,看起来很像区块链,但实际上,它并非区块链。

我不知道区块链技术最终是否会蓬勃发展,是否会得到广泛应用,但可以肯定的是,这项颠覆性技术所带来的许多创新都将会流传下去。从新的共识算法的实现、到更好的分布式网络协议的设计,再到新的密码原语的设计和实现,区块链技术给我们带来了许多进步,即使我们最终放弃了区块链技术的永恒承诺,这些进步也将继续盛行

潜在的进步之一,有望盛行的便是不可变数据库(immutable databases)。自 2018 年末亚马逊推出量子分类账数据库(Quantum Ledger Database,QLDB)以来,我一直在想,在企业中,是否存在使用这种数据库的利基市场。本周,我偶然看到一篇关于开源不可变数据库 ImmuDB文章,于是我决定深入研究这一问题。先是亚马逊,现在又有了开源项目,这是一个值得探讨的事情。

工作原理

不可变数据库是集中式数据库系统,其中信息的存储方式可以通过加密方式验证其完整性。每个数据更改都会被跟踪,并维护更改的完整历史记录,以便随着时间的推移可以验证“数据的完整性”。这就是我们称它们为“不可变”的原因,因为数据存储中执行的所有更改的历史都是保存的,如此一来,无论何时发生了无意或恶意的更改,都可以检测、报告,在许多情况下甚至可以恢复。我强烈建议你阅读这篇常见问题集来快速了解不可变数据库能做什么,以及不能做什么。

不可变数据库的实现:类似于区块链,但没有使用区块链 1

不可变数据库使用可验证的密码源于和数据结构来保证所存储数据的完整性。让我们以 ImmuDB 为例(稍后我们将对该开源项目展开详细的讨论)。ImmuDB 使用梅克尔树(Merkle Tree)来存储数据并保持其完整性。因此,我们在 t0 中添加值为 v0 的密钥 k0 时,数据库的梅克尔树的根值为 H0(即(k0,v0)的哈希值)。当我们不断地向数据库中添加新的信息时,树会不断地增长,树的根也会不断变化。在 t1 中,我们将 k0 的值更新为 v1 时,该树将被更新为一个新的分支,其根更改为 H01。无论是由于密钥的更新,还是由于新芈月中的存储数据,数据库中的每次新写入操作都会重复这一过程。

译注:梅克尔树(Merkle Tree)是一种二叉树,是一种高效和安全的组织数据的方法,被用来快速查询验证特定交易是否存在,由一个根节点、一组中间节点和一组叶节点组成。它使用哈希算法将大量的书面信息转换成一串独立的字母或数字。最底层的叶节点包含存储数据或其哈希值,每个中间节点是它的两个子节点内容的哈希值,根节点也是由它的两个子节点内容的哈希值组成。
不可变数据库的实现:类似于区块链,但没有使用区块链 2

使用这种数据结构,验证存储在系统中的数据的完整性是很容易的。想象一下,我们要验证客户端 A、k0 和 K1 存储的数据的完整性。为此,我们只需生成一个证明,验证第一个梅克尔树根是否与在数据库中添加新数据后生成的第二个梅克尔树根一致。为了生成这个证明,我们只需:

  1. 从梅克尔树根的第一个版本的分支中获取节点(当客户端 A 添加他的数据时);
  2. 取客户端 B 与系统交互后在树中生成的新分支中可能较高的节点;
  3. 重建梅克尔树的根,并检查其值是否与数据库中当前树的值相同

因此,我们将从第一棵树中获取 H01 和 H2,从第二棵树中获取 H3 和 H456,并将树重建到根。如果获得的根等于树的第二个版本的实际根,则意味着自客户端 A 添加数据以来,没有任何数据被更改。相反,如果在客户端 A 添加数据后信息以任何方式被修改,则第一棵树的 H01 和 H2 将与第二棵树中的不同,从而导致在重新创建树直至根时产生不同的根。

不可变数据库的实现:类似于区块链,但没有使用区块链 3

在这种情况下,梅克尔树被用来验证数据的完整性,但可以设计出更复杂的不可变数据库系统,其中可以使用其他密码原语来确保防篡改,例如零知识证明(Zero Knowledge Proofs)(尽管老实说,我并不知道在许多情况下,它是否能弥补开销)。

在何处使用

不可变数据库由单个实体管理,在由不同实体拥有和管理的网络中,不同节点之间不存在数据的分发或复制。因此,不要搞错,不可变数据库根本不会取代区块链网络,但它们非常适合特定用例,如下面一场对话所示:

某公司首席信息官 Boss 说:“为了可靠地跟踪我的所有库存变化,我想建立自己的基于区块链的系统。”

咨询公司 Hardwarker 问道:“听起来不错,老板。请问这些更新涉及哪些实体?谁需要写在这个区块链上?参与者之间有多大程度的信任感?”

Boos 回复道:“啊,不,不!就我一个人。我希望我司不同单位可以像现在一样修改数据库中的数据,但我希望跟踪所有这些变化的历史记录,这样,我们的系统就不会出现不一致的情况。更重要的是,我希望你能确保这个区块链能够容纳我司的高事务负载。但能写在这个区块链上的唯一公司将是我们。”

Hardwarker 以胜利的姿态告诉他说:“那么,让我向您介绍一下不可变数据库,这是你那个问题的解决方案。” 他促成了这笔生意。

我想这个小例子说明了我的观点。不可变数据库是理想选择,在这个用例中,我们希望从防篡改存储系统中获得好处,而不需要区块链系统的复杂性和潜在开销,因为数据库只会由单个实体(或少数收信任的实体)编写。

实际上,我期望很快就能见到不可变数据库可以立即应用到其中的一些用例中:

  • 对现有应用程序数据库的敏感数据库字段(如信用卡或银行账户数据)的每次更新,均以不可变的方式进行存储。
  • 存储 CI/CD 配方,以保护构建和部署管道
  • 存储公共证书(这是企业区块链中广泛使用的证书)。
  • 作为数字对象校验和的附加哈希存储
  • 存储日志流(即审计日志)以防篡改。

当然,我也绝对不会用不可变数据库来存储大型数据。如果我们要为大型数据提供防篡改功能,我们可以按照区块链的方式:对大型文件进行哈希,用不可变数据库来跟踪这个哈希值的变化。

实际上,我想引用亚马逊 QLDB 文档中的一句话来结束本节,这个文档完美地阐述了在何处使用不可变数据库:

问:亚马逊量子分类账数据库是分布式总账还是区块链服务?

亚马逊 QLDB 不是区块链,也不是分布式总账技术。区块链和分布式总账技术专注于解决涉及多方的去中心化应用的问题,在这种情况下,不可能有任何一个实体拥有该应用,而且各方不一定完全信任对方。另一方面,QLDB 是专门为客户打造的分类账数据库,客户需要在自己拥有的应用中维护一个完整的、可验证的数据变化历史记录。亚马逊 QLDB 提供了历史记录、不可变性和可验证性,并结合了完全托管的 AWS 数据库的熟悉性、可扩展性和易用性。如果你的应用需要去中心化,且涉及到多个不信任的第三方,那么区块链解决方案可能就是合适的。如果你的应用需要所有应用数据变更的完整且可验证的历史记录,但不涉及多个不受信任方,那么亚马逊 QLDB 是非常合适的

了解 ImmuDB

理论已经讲得够多了。让我们来看看一个不可变数据库是如何工作的。我们将重点介绍 ImmuDB,这是我在本文开头提到的开源项目。我们将从一段视频开始:

不可变数据库的实现:类似于区块链,但没有使用区块链 4

ImmuDB 包括以下几个部分:

  • immudb 是服务器二进制文件,在本地主机上监听端口 3322,并提供了 gRPC 接口。
  • immugw 是链接到 immudb 并为应用程序提供 RESRfull 接口的智能 REST 代理。建议在不同的机器上运行 immudb 和 immugw,以增强安全性。
  • immuadmin 是 immudb 和 immugw 的管理 CLI。你可以安装和管理这两个组件的服务安装,并获取统计信息和运行时信息。

运行 ImmuDB 并开始使用它的最简单方法是克隆仓库构建所有二进制文件然后启动数据库和网关,如下所示:

$ git clone https://github.com/codenotary/immudb.git
$ make all
$ ./immudb -d
$ ./immugw -d

你还可以使用 docker 来运行 ImmuDB。在我的情况下,我无法将网关与数据库连接起来,这就是我选择本地部署的原因。但我觉得这值得一提。

$ docker run -it -d --name immudb -p 3322:3322 -p 9497:9497 codenotary/immudb:latest
$ docker run -it -d -p 3323:3323 --name immugw --env IMMUGW_IMMUDB-ADDRESS=immudb codenotary/immugw:latest

随着数据库的运行,我想尝试一个 SDK,将 ImmuDB 与一个简单的应用程序集成在一起,但显然目前只有 REST API 和 gRPC 接口可以与系统交互根据他们的文档说明,驱动程序将很快可用于 Java、.NET、Golang、Python 和 Node.js,但现在我们必须满足 ImmuDB 使用的要求。

使用 ImmuDB 添加密钥和值非常简单:

./immuclient safeset mykeytest1 myvaluetest1

不可变数据库的实现:类似于区块链,但没有使用区块链 5

我们可以看到,该命令的运行结果是将密钥添加到数据库、数据的哈希值,以及是否验证了添加。如果我们不在数据库中伪造数据,我们每次添加新数据都会得到这些。

要从数据库中获取密钥,我们可以使用如下命令:

./immuclient safeget mykeytest1

或者我们可以得到历史记录

./immuclient history mykeytest1

不可变数据库的实现:类似于区块链,但没有使用区块链 6

如果你想“恶意”修改信息,可以转到 /.db(缺省情况),然后随意处理这些文件。如果你想知道你试图添加新的数据并且数据库已“损坏”时会发生什么情况,你可以这样做。

最后,从 ImmuDB 的 GitHub 仓库中提取了一些关于性能的注意事项(如果你想知道可以应用此技术的负载场景的类型):

不可变数据库的实现:类似于区块链,但没有使用区块链 7

不可变数据库的实现:类似于区块链,但没有使用区块链 8

作者介绍:

Alfonso de la Rocha,西班牙电信公司区块链技术专家,专注区块链和量子计算技术。

原文链接:

https://adlrocha.substack.com/p/adlrocha-immutable-databases