如何使用Gun实现无损CRDT?

问题描述 投票:3回答:1

如何使用Gun创建CRDT?

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

为了简化,让我们创建这个场景,Alice和Bob正在合作。

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

这个数组的内部表示将是一个链接列表,如下所示:

a => b => c

(当然,内部表示将类似于{value: 'a', next: { value: 'b' next: { value: 'c' }}}),但我认为你用terser符号表达我的观点。

爱丽丝现在想在cb之间插入元素d

同时,Bob希望在Cb之间插入元素d

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

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

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

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

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

要么

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

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

我们能用枪来实现吗?

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

gun crdt
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(gun.set(或其他任何命令将数据保存到图形中(put和set本身只是像RGA这样的扩展,没有什么花哨的),你可以构建/构建图形/ tree / 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);

显然你可能想要更详细并用cuids和东西来控制UUID,但是你明白了。

没有理由直接替换HAM CRDT或者在它旁边“注入”CRDT,只需@pgte就可以在GUN上模拟CRDT的数据结构(可能通过GUN扩展提供了一个很好的简易API),然后你也有了该扩展支持回调,如果通过RGA图形/树传递你的gun.get( ...并在将结果吐出回开发者之前运行各种RGA逻辑。这个树可以被许多对等体在GUN内部同时动态变异,比如Alice和Bob!

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

© www.soinside.com 2019 - 2024. All rights reserved.