此模型会维护两个集合,一个是新增集合,保存新增的元素,另一个是删除集合,保存被删除的元素 。
模型的最终状态为新增集合和删除集合的差集 。
另外,集合比较特殊,它是只增集合(grow-only set),只能往集合里加元素,不能从集合里移除元素 。
这意味着一个元素如果被删除了,就再也不能添加回来 。所以删除集合也被叫做 tombstone set(墓碑集合),人噶不能复生 。
2P-Set 也算是一种 RW-Set(删除优先),特别的点在于元素被删除后不能新增回来 。
G-CounterG-Counter,Grow-only Counter,只增计数器,一个只能增加计数的计数器 。
此模型使用 n 个节点的容器(一个整数数组),每个副本会分配一个 id,某个副本给计数器 +1,其实就会给对应的数组元素 +1 。
计数器的值为数组的求和 。
PN-CounterPN-Counter,Positive-Negative Counter,一个支持增减的计数器 。
多个 CRDT 可以组合成一个更复杂的 CRDT 。
类似 G-Counter , 但 PN-Counter 使用两个 G-Counter,一个保存新增数(新增操作),另一个保存减少数(减少操作) 。
计数器的值为新增数组求和减去减少数组的和 。
YATA最后我们看看复杂点的,简单介绍一下 Y.js 的 YATA(Yet Another Transformation Approach)模型 。
假设我们有值为 "ABCD" 的字符串 。
YATA 模型会将其拆分成一个个字符,加上元数据,然后按顺序首尾相连组成一个双链表 。
// 大概这样子{id: '2:0', // 客户端 ID + clock IDval: 'B',left: a, // 当前节点的左节点right: c, // 右节点origin: a, // 节点创建时的左节点rightOrigin: c // 节点创建时的右节点}操作有 “插入” 和 “删除” 。
假设本地在 AB 之间插入 E , 此时没有发送同步,然后收到其他副本传过来的 F,也是要插入到 AB 之间 。
此时 E 和 F 是冲突的,我们会对唯一的 id(某种意义上的时间戳)使用特定的规则来决定先后顺序 。
至于删除操作 , 因为插入操作需要找到在左右节点的位置,所以节点即使被删除了也是不能从双链表中移出的 。
对此,YATA 选择使用墓碑机制 。YATA 将对应节点标记为删除(item.deleted 设置为 true),并将节点记录到删除集合 DeleteSet 里 。
这里其实可以看到,CRDT 通常是需要加很多元数据的,尤其是复杂数据结构且数据量较大的场景,所以这也是 CRDT 起初被诟病占用内存高的原因 。
但 Y.js 通过一系列手段(比如将多个节点合并为一个大节点),将性能优化到足够面对大多数场景 , 证明了用 CRDT 是做协同编辑的是不用担心性能问题的,如果有,一定是你没优化好 。
结尾本文只是简单介绍一些 CRDT 是什么 , 并感受了一些简单的 CRDT 模型 , 希望对你有所帮助 。
【这一次,彻底搞懵 CRDT】
推荐阅读
- 37岁刘亦菲拍大片彻底放飞!穿红色上衣半穿半露又纯又欲,火辣的像换了个人
- 李小璐又出事了?这一次娱乐圈竟然集体闭嘴
- 古巨基的“清醒”,彻底扯下了《声生不息》的遮羞布
- 这一次,殴打赵露思扇嘴巴的“公司老板”,如今底裤快被扒光了
- 何捷转业成保安,年薪曝光差距立显,这下,张馨予彻底输了
- 被爆当小三的吉克隽逸,人设算是彻底崩塌了,三观尽毁!
- 一天一个猛料,资本圈杀人不见血,这一次,张颂文还能撑得住吗?
- 这一次,40岁的叶一茜,终是为她的“重男轻女”买了单
- 31岁孙怡彻底放飞了,穿衬衫忘记扣扣子,急忙用手遮挡掩饰尴尬!
- 第一集就上尺度,国民第一初恋,彻底黑化
