CRDT宝典 - Delta-state AWOSet

背景

看完AWORSet,它有一个致命的缺点:元信息很大,大到远超数据本身,比如

ts 复制代码
A.AWORSet = [
    {
        'element1': {
            [A.id]: 1,
            [B.id]: 2,
            [C.id]: 5,
            [D.id]: 1,
            [E.id]: 8,
            [F.id]: 3,
            [G.id]: 7,
            [H.id]: 4,
            [I.id]: 9,
            [J.id]: 2,
            [K.id]: 6,
            [L.id]: 5,
        },
    },
    {
    }
]

我们为了表示出不同节点添加element1的操作,其元数据本身远远超过了element1本身,这是我们不能容忍的,这会导致以下的问题

  1. 不同节点的CRDT需要将自身的整个CRDT推送到远端用于合并,这数据量太大了
  2. 合并CRDT时,耗时太长了

我们需要一个减少元数据的方式

思维链

flowchart A["1. 每个节点都会间隔性地拉取远端节点的AWORSet,然后和自身的AWORSet进行合并,\n合并后的结果会覆盖掉原来的AWORSet。\n同样也会间隔性的将自身的AWORSet推送到远端节点,用于同步。"] A --> B["2. 同时,节点自身会产生许多对AWORSet的操作。\n`记住,这些操作只代表该节点对AWORSet的操作`"] B --> C["3. 我们聚焦节点A,其实它只需要将自身对AWORSet产生的增删操作同步出去就可以了,\n我们完全可以用delta来表达这些操作"] C --> D["4. 很明显,delta = `添加集` + `删除集` = 一个AWORSet,\n所以将delta合并到AWORSet中 = 两个AWORSet的合并"] D --> E["5. 通过delta的方式,我们能很显著的解决`背景`里提出的两个问题"]

实现

这个CRDT如下,我们称之为Delta-state-AWORSet,我们简称一下:Delta-AWORSet

ts 复制代码
A.Delta-AWORSet = {
    values: [
        {
            'element1': {
                [A.id]: 3,
                [B.id]: 2
            },
            'element3': {
                [A.id]: 1,
                [B.id]: 2
            },
        },
        {
            'element1': {
                [A.id]: 3,
                [B.id]: 2
            },
        }
    ],
    delta:[
        {
            'element1': {
                [A.id]: 3,
                [B.id]: 2
            },
        },
        {
            'element2': {
                [A.id]: 1,
            },
        }
    ]
}

代表节点从上一次同步delta后,进行了新增element1和删除element2的操作

某个节点添加元素,比如A节点添加了element1,即A.Delta-AWORSet.delta.add(element1),并且A.Delta-AWORSet.values.add(element1)

某个节点删除元素,比如A节点删除了element2,即A.Delta-AWORSet.delta.remove(element2),并且A.Delta-AWORSet.values.remove(element2)

某个节点的Delta-AWORSet的值,是A.Delta-AWORSet.values.value()

同步其他节点的Delta-AWORSet,比如将B节点的Delta合并到A节点中,只需要将A.Delta-AWORSet.values.merge(B.Delta-AWORSet.delta)

合并两个Delta-AWORSet,比如合并A.Delta-AWORSet和B.Delta-AWORSet,只需要将A.Delta-AWORSet.values.merge(B.Delta-AWORSet.values),且A.Delta-AWORSet.delta.merge(B.Delta-AWORSet.delta)

代码如下(伪代码):

ts 复制代码
A.Delta-AWORSet:<{values: AWORSet, delta: AWORSet}> = {
    values: [
        {
            'element1': {
                [A.id]: 3,
                [B.id]: 2
            },
            'element3': {
                [A.id]: 1,
                [B.id]: 2
            },
        },
        {
            'element1': {
                [A.id]: 3,
                [B.id]: 2
            },
        }
    ],
    delta:[
        {
            'element1': {
                [A.id]: 3,
                [B.id]: 2
            },
        },
        {
            'element2': {
                [A.id]: 1,
            },
        }
    ]
}

// 添加元素的代码示例
function addElement(node: Delta-AWORSet, element) {
    node.values.add(element);
    node.delta.add(element);
}

// 删除元素的代码示例
function removeElement(node: Delta-AWORSet, element) {
    node.values.remove(element);
    node.delta.remove(element);
}

// 值的获取
function getValue(node: Delta-AWORSet) {
    return node.values.value();
}

// 同步其他节点的Delta
function mergeDelta(node: Delta-AWORSet, delta: Delta-AWORSet) {
    node.values.merge(delta.values);
}

// 合并两个Delta-AWORSet的代码示例
function mergeDelta(node: Delta-AWORSet, delta: Delta-AWORSet) {
    node.values.merge(delta.values);
    node.delta.merge(delta.delta);
}

QA

问:都有delta了,为什么还需要合并两个Delta-AWORSet?

答:因为你业务决定的,可能会存在需要全量同步的需求。

问:为什么合并别的节点的delta的操作里,只需要合并values,不需要合并delta?

答:你问到delta的精髓了,A.Delta-AWORSet.delta代表着A节点对Set的操作,而这个操作绝对是最新的(无论是离线还是在线,且别的节点里不可能有比这个delta还新的操作,因为A节点是A.Delta-AWORSet.delta的唯一产生者),也就算说即便A.Delta-AWORSet.values合并了别的节点的delta,A.Delta-AWORSet.delta里的操作也能保证是最新的。

问:什么时候delta可以重制

答:看业务,比如A节点将自身的delta同步出去后就可以重制delta了,因为这代表着A对Set的操作都同步出去了,没必要保留delta了。对,所以delta完全没必要在硬盘中,它可以在内存中(性能又高了一截)。

总结

很复杂,需要看好几遍,有问题的评论区见

相关推荐
liangshanbo121524 分钟前
高级前端面试题:package.json 常见字段
前端·json
Doubbbbbbble云33 分钟前
基于流处理框架的实时算法实现策略4
算法
2601_9628857239 分钟前
如何用 Python 计算 ROC 变动率指标做动量分析?
开发语言·python·算法
CappuccinoRose44 分钟前
输入事件进阶
前端·javascript·输入事件
胡家伟++1 小时前
我用 48 轮 AI 思维链做了一次研究战略推演:从“验证信号危机“到“验证栈“统一框架
人工智能·算法
朝朝辞暮i1 小时前
C++ 第 39 章: 阶段性总复习——类、对象、构造、继承、this、指针与智能指针
开发语言·c++·算法·ros2
垆边人似月.2 小时前
华为题:污染水域
算法
All for pursuit.2 小时前
【回溯-6】79.单词搜索
数据结构·c++·算法·leetcode
ZhangJun952 小时前
Mobike 共享单车分析项目
人工智能·python·算法·kmeans·聚类·knn
Navigator_Z2 小时前
LeetCode //C - 1281. Subtract the Product and Sum of Digits of an Integer
c语言·算法·leetcode