【转载】OrbitDB:在浏览器中部署分布式IPFS数据库

前奏:分布式网络正在全力以赴

分布式协议开发正在快速发展,并且只会加速进入2019年,这一年看起来对于一般的分散化非常令人兴奋。

内部协议开发的日子已经一去不复返了。开源生态系统和新兴的分散经济学正在为塑造软件未来的更多协作努力铺平道路。因此,我们可以通过部署今天最新的开源工作来了解即将发生的事情。OrbitDB就是这样一种在分布式数据库中引领潮流的努力; 在IPFS之上运行的对等数据库。

OrbitDB令人印象深刻的是它在浏览器中的IPFS Javascript实现之上运行。这样做允许我们基于每个用户复制和管理数据库。我们将详细探讨这实际意味着什么,以及它提供的用例。

什么是OrbitDB

该OrbitDB Github的页面票据包一个对等网络数据库的分布式网络。为实现这种分散性,数据库在IPFS之上运行,如上所述。但与传统的集中式数据库不同,数据存储在一个中心位置(并且可能复制或分片到其他集中位置),OrbitDB数据库是无服务器的,并且会复制到使用它的所有对等方。而且由于IPFS的哈希协议不允许复制一段内容,因此这种数据库没有中心点。

哈希是真正的源,可以存在于网络上的数百或数千个节点上。考虑到这一点,数据库的高级功能如下:

1.OrbitDB兼容服务器端和浏览器。

2.OrbitDB是无服务器的。它不需要中央保留服务器,但是,它确实需要至少一个IPFS节点愿意保留数据库,以便在浏览器断开连接时不丢失,或者使用go-ipfs收集垃圾。

3.数据库会自动在同行之间同步。IPFS pubsub协议自动使数据库在同行之间保持最新。Pubsub是publish-subscribe的缩写,是一种可靠地处理对等事件和更新的模型。

4.OrbitDB数据库是最终一致性, 实现 与无冲突的数据库合并(CRDTs)。简而言之,跨对等体的数据库副本可以同时更新,而无需它们之间的协调机制。因此,保证数据库的每个对等体最终将拥有与其他所有人相同的数据库; 相同的记录,相同的顺序等。这是前端开发人员不必考虑的极好的底层管理。

5.由于OrbitDB数据库由对等方复制并存储在本地,因此应用程序将变为脱机兼容。这提供了更多的可访问性,但会牺牲可靠性; 应用离线的时间越长,数据就会越来越过时。

6.OrbitDB支持写权限。我们可以基于特殊的哈希键来限制对数据库的写访问,这个哈希键对于每个对等体都是唯一的,我们将在本文后面进一步访问。

注意:在编写本文时,我们仅限于在首次启动数据库时定义写入权限。但是,OrbitDB核心开发人员正在开发更灵活的权限管理功能,包括读取权限,这些功能将在未来的更新中推出。

1.OrbitDB数据是公开的。私有IPFS协议正在进行中,虽然处于早期阶段,因此这里不再进行探讨。目前,确保OrbitDB上没有存储敏感数据

  1. 坚持您希望全世界了解的数据。

3.OrbitDB提供5种数据类型,可以开箱即用。让我们访问下一个。

OrbitDB数据结构

OrbitDB提供了一系列可直接使用的数据类型,以及添加自定义数据类型的功能。我们定义了在初始化数据库时要遵循的数据类型。我们将访问这个需要进一步深入的代码。

我们开箱即用的数据类型是:

1.一个log(仅追加的,一成不变的)与穿越历史的结构。对于您不想删除条目的排队和日志记录应用程序很有用。

2.一个feed(可变)结构,穿越历史。可以添加和删除条目。适用于购物车,评论,文章回复。

3.一家keyvalue商店。顾名思义,这是一个简单的键值结构。适用于持久应用配置或应用状态。

4.一家document商店。与基于文档的数据库(如MongoDB)类似,文档数据类型允许我们将JSON文档存储为条目。该_id字段可用于查找文档的条目。这种更灵活的数据类型可用于描述产品和文章等项目。

5.一counter。最简单的数据类型,一个计数器带有一个inc()函数,我们可以通过正整数和负整数来操纵我们的计数器。计数器对于与事件log或feed数据库一起计数事件非常有用。

安装所需的包

要启动并运行OrbitDB,请安装IPFS JS和OrbitDB,它们可以使用npm或yarn安装:

npm i orbit-db ipfs

#or

yarn add orbit-db ipfs

注:如果您遇到错误安装特定的软件包,因为我做了tiny-secp256k1,在这个问题上记载,该解决方案entailed重新安装使用自制的新鲜NPM:

sudo rm -rf /usr/local/lib/node_modules/npm brew reinstall node

IPFS JS是alpha版。谨慎使用

重要的是要强调IPFS JS处于alpha状态,并且随着项目接近公开发布,API可能确实会发生变化。但是,我们要求它与OrbitDB一起运行以在浏览器中运行,因此将在此处采用它。

通常不建议在您的关键任务应用程序中包含预发布软件,但我完全建议使用预发布软件创建应用程序的原型版本以测试稳定性并从实施中学习 - 您可能会惊喜地看到您的应用程序执行完美。

通过Github项目页面了解IPFS JS的最新信息:

ipfs/js-ipfs
IPFS implementation in JavaScript. Contribute to ipfs/js-ipfs development by creating an account on GitHub.github.com

无论您是希望将资产慢慢推广到IPFS,向用户的子集发布beta版本,还是等到最终版本发布到生产基础架构之前,这都是您的号召。

考虑到这一点,现在让我们来实例化一个数据库。

实例化OrbitDB数据库

现在安装了ipfsand orbit-dbpackages,我们可以在浏览器中自发地实例化IPFS节点,然后启动OrbitDB数据库。

这样做所需的代码如下:

const IPFS = require(‘ipfs’) const OrbitDB = require(‘orbit-db’)

const ipfsOptions = { EXPERIMENTAL: { pubsub: true } }

const ipfs = new IPFS(ipfsOptions)

ipfs.on(‘ready’, () => { //Create OrbitDB instance const orbitdb = new OrbitDB(ipfs);

//orbitdb is now the OrbitDB instance we can use to interact with databases

})

在React中实例化

此时您可能想知道如何将此代码应用到React状态管理的应用程序中。以下要点解决了这个问题。

将以下内容复制并粘贴到React项目中(使用ipfs并orbit-db安装),以观察IPFS实例化的速度,然后是OrbitDB:

在我的本地计算机上,IPFS实例化在OrbitDB实例化之前花了不到一秒的时间,然后是一瞬间 - 从而触发重新渲染以反映更新的状态。

数据库创建者+数据库持久性

此时,值得简要地访问哪个节点创建数据库的问题。如果我们允许最终用户这样做,运行基于浏览器的IPFS节点,我们将看到当所述用户离开网页时节点被断开,或者只是失去连接。刚创建的数据库然后变得无法访问和销毁。

所需要的是一个高度可用的节点来实例化数据库,并使其对等体复制并固定数据库以使其变得可广泛访问。

这里的解决方案是将服务器端IPFS节点作为IPFS群集的一部分来创建数据库。IPFS群集是另一个谈话的主题,但是,作为群集对等方的IPFS节点将自动复制并由所述群集中的每个对等方固定。这可以通过其Distributions页面上的IPFS ipfs-cluster-service和ipfs-cluster-ctl包来实现。

通过以下介绍性文章了解有关安装和配置IPFS群集的更多信息:

Using IPFS Cluster Service for Global IPFS Data Persistence
How to install and configure IPFS’s cluster service across your IPFS networkmedium.com

创建数据库

现在,通过orbitdb实例化我们的对象,我们现在能够在IPFS网络上创建数据库并与之交互。

创建数据库很简单 - 可以使用以下命令创建keyvalue数据库:

#keyvalue database const db = await orbitdb.keyvalue(‘my-database’)

OrbitDB方法是异步的,支持async awaitJavascript中的实现。

为了完整性,让我们基于其他开箱即用的数据类型运行其他数据库创建方法:

#log const db = await orbitdb.eventlog(‘site.visitors’)

#feed const db = await orbitdb.feed(‘orbit-db.issues’)

#docs const db = await orbitdb.docs(‘orbit.users.shamb0t.profile’)

#counter const counter = await orbitdb.counter(‘song_123.play_count’)

创建数据库后,将生成结果地址字符串,从而允许对等方复制和写入数据库(如果它们具有写访问权限)。我们接下来看看地址字符串。

注意:如果我们想要复制现有数据库而不是创建数据库,则数据库的地址字符串将传递给上述方法而不是名称字符串。

OrbitDB数据库地址字符串

OrbitDB数据库字符串由以下内容组成:

/<protocol>/<database_manifest_hash>/<database_name>

有问题的协议总是如此orbitdb。数据库清单文件由关于数据库的重要元数据组成。最后,数据库名称是我们在创建数据库时定义的名称。

orbitdb地址的一个实际示例如下:

/orbitdb/Qmd8TmZrWASypEp4Er9tgWP4kCNQnW4ncSnvjvyHQ3EVSU/first-database

为了节省重复的现有资源,可以在Github上找到更多的地址字符串文档。

获取数据库地址

了解OrbitDB中的数据库字符串非常重要,因为其他对等方需要它来与数据库进行交互或复制。地址可以用db.address。db作为您的数据库实例:

const address = db.address.toString();

接下来让我们访问辅助功能,以及如何配置对等体以获得对数据库的写访问权限。

提供写访问权限

OrbitDB目前仅支持配置写访问 - 默认情况下,写访问仅授予数据库创建者,读访问权限是全局访问。为了给更多对等体提供写访问权,我们在创建数据库时传入一个access对象。那就对了; 目前定义写访问的唯一方法是创建数据库。这无疑将在未来发生变化,但这是我们目前必须遵守的限制。

access在实际使用中传递对象的方法如下:

const access = { // Give write access to ourselves write: [orbitdb.key.getPublic(‘hex’)], }

const db = await orbitdb.keyvalue(‘first-database’, access);

数据库的创建方式与之前相同,但这次将access对象作为第二个参数传递。access是一个由一个write字段组成的对象,由一个需要写访问权限的对等公钥组成。

现在,这些公钥不是您的IPFS标识哈希。相反, 这些是对等的OrbitDB 实例密钥。为了获得所需的write-priviledged对象的实例密钥,他们每个都需要 orbitdb.key.getPublic('hex') 在实例化OrbitDB后运行:

console.log(orbitdb.key.getPublic(‘hex’));

一旦获得,它们就可以插入到access物体中。

const access = { write: [‘key1’, ‘key2’, ‘keyN’], } …

有关访问控制的官方文档可以在Github上找到。

数据库事件

此时我们已准备好与数据库进行交互,但您可能想知道我们如何监听复制数据库的更新以保持UI同步。

我们从文章前面的内容中了解到,数据库在对等体之间自动保持最新,因此现在需要的只是对来自其他可写对等体的传入更改做出反应。

事件机制内置于数据库实例中。我们可以通过replicated事件对传入的更新作出反应(例子来自文档):

// When the second database replicated new heads, query the database db2.events.on(‘replicated’, () => { const result = db2 .iterator({ limit: -1 }) .collect() .map(e => e.payload.value) { console.log(result.join(’\n’)) } });

有关复制和事件的进一步阅读,有关于Github的良好文档。

查询数据库

您现在可以深入了解文档并研究每种数据库类型的CRUD方法。使用起来并不多,而且使用简单:

  • keyvalue put,set,get 在这里。
  • log add,get,iterator 在这里。
  • feed add,get,remove,iterator 在这里。
  • docs put,get,query,del 在这里。
  • counter inc 在这里。

所有OrbitDB方法都是异步的,记得将它们视为promises await。

结束评论

这是使用OrbitDB的细分。现在正是开始尝试使用OrbitDB和IPFS的好时机,以了解与您的应用程序基础架构相关的用例并从其分布式架构中受益。

声明:本文由入驻IPFS中国社区的作者撰写,观点仅代表作者本人,不代表IPFS中国社区的立场。