3

如何使用 Gun 创建 CRDT?

例如,如果我想实现一个只增长的数组,其中每个元素都指向下一个元素,我该如何解决冲突?

为简化起见,让我们创建一个 Alice 和 Bob 合作的场景。

该数组包含 3 个元素,[a, b, d].

这个数组的内部表示将是一个像这样的链表:

a => b => c

(当然,内部表示形式类似于{value: 'a', next: { value: 'b' next: { value: 'c' }}}),但我认为您使用更简洁的表示法理解了我的观点。

Alice 现在想在和c之间插入元素。bd

同时,Bob 想要在和C之间插入元素。bd

同时,它们具有数组的这种内部表示:

爱丽丝:a => b => c => d

鲍勃:a => b => C => d

当他们加入 CRDT 时,他们将收敛到以下值之一:

a => b => c => C => d

或者

a => b => C => c => d

无论如何,a)它们都将收敛于相同的值,并且 b)它们不会丢失彼此的数据。

我们可以使用 Gun 来实现这一点吗?

(这个问题是对https://github.com/amark/gun/issues/602的简化和后续问题)

4

1 回答 1

0

是的。

这是几年前的代码演示:

https://youtu.be/rci89p0o2wQ

您可以在 GUN 的基础 CRDT 之上创建任何其他 CRDT 作为数据结构。

我们甚至对这类东西的通用算法做了一个完整的卡通解释:

https://gun.eco/explainers/school/class.html

(或者从https://youtu.be/yCcWpzY8dIA?t=29m36s开始,由精彩的 Martin Kleppmann 查看针对特定案例实施的更详细说明)

我还没有看到任何人专门在 GUN 之上实现 RGA,但考虑到您发送的代码有多短,它应该很容易。(虽然“删除”需要是一个空墓碑,但这很好)

从查看计数器 CRDT 开始可能是最简单的,“如何开始使用自定义扩展将数据保存到 GUN”,这是一个仅包含 12 行代码的增长型 CRDT:

https://gun.eco/docs/Counter

您注意到它非常基本,RGA 会很相似,您可能会有一些 GUN 扩展(只是一个 JS 方法/函数,这使得开发人员更容易使用),比如

Gun.chain.rga = function(...

然后在内部,就像使用计数器一样,您可以调用gun.put(orgun.set(或任何其他命令将数据保存到图中(put 和 set 本身只是 RGA 之类的扩展,这里没什么特别的),您将在其中构建/构造图/树/table,或者你可能很懒,只是做一些类似的事情:

// fictional code
var myData = {
  rgaTree: {left: {}, right: {}}
}
myData.rgaTree.left.next = myData.rgaTree.right;
myData.rgaTree.right.prev = myData.rgaTree.left;
// yes! circular references are supported!
gun.put(myData);

显然,您可能希望更详细并使用 cuid 和其他东西来控制 UUID,但您明白了。

没有理由直接直接替换 HAM CRDT 或“注入”一个 CRDT,只是 @pgte 会在 GUN 上对 CRDT 的数据结构进行建模(可能通过 GUN 扩展使用一个很好的简单 API),然后你也会有该扩展支持回调,如果将其传递给您gun.get(...通过 RGA 图/树并运行各种 RGA 逻辑,然后将结果吐回给开发人员。这棵树可以在 GUN 内部由许多对等方同时动态变异,比如 Alice 和 Bob!

然后,GUN 将通过(许多)存储引擎之一(例如 IPFS!)将动态更改和更新的数据保存到磁盘,因此 IPFS 可以随着时间的推移托管数据的持久性,并且 GUN 可以管理 O(1) 树查找是可变/变化/动态树/图/索引结构。

于 2018-09-01T00:29:40.650 回答