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完全没必要在硬盘中,它可以在内存中(性能又高了一截)。

总结

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

相关推荐
鱼力舟13 分钟前
【hot100】240搜索二维矩阵
算法
林的快手1 小时前
CSS列表属性
前端·javascript·css·ajax·firefox·html5·safari
匹马夕阳1 小时前
ECharts极简入门
前端·信息可视化·echarts
北_鱼2 小时前
支持向量机(SVM):算法讲解与原理推导
算法·机器学习·支持向量机
API_technology2 小时前
电商API安全防护:JWT令牌与XSS防御实战
前端·安全·xss
yqcoder2 小时前
Express + MongoDB 实现在筛选时间段中用户名的模糊查询
java·前端·javascript
十八朵郁金香2 小时前
通俗易懂的DOM1级标准介绍
开发语言·前端·javascript
DC_BLOG3 小时前
Linux-GlusterFS进阶分布式卷
linux·运维·服务器·分布式
m0_528723813 小时前
HTML中,title和h1标签的区别是什么?
前端·html
Dark_programmer3 小时前
html - - - - - modal弹窗出现时,页面怎么能限制滚动
前端·html