Algorithm 同步两个有序列表
我们有两个离线系统,通常无法相互通信。两个系统都维护相同的有序项目列表。他们很少能够相互通信以同步列表 项目用修改时间戳标记以检测编辑。项目由UUID标识,以避免插入新项目时发生冲突(与使用自动递增整数相反)。同步时,检测到新UUID并将其复制到其他系统。删除也同样如此 上面的数据结构对于无序列表来说很好,但是我们如何处理排序呢?如果我们添加了一个整数“rank”,则在插入一个新项时需要重新编号(因此,由于只有1次插入,因此需要同步所有后续项)。或者,我们可以使用分数等级(使用前一项和后一项的等级平均值),但这似乎不是一个可靠的解决方案,因为当插入许多新项时,它会很快遇到精度问题 我们还考虑将其实现为一个双链接列表,其中每个项都包含其前一项和后续项的UUID。但是,这仍然需要在插入1个新项目时同步3个项目(或在删除1个项目时同步其余2个项目) 我们最好使用数据结构或算法,其中只需要同步新插入的项。是否存在这样的数据结构Algorithm 同步两个有序列表,algorithm,data-structures,synchronization,linked-list,html-lists,Algorithm,Data Structures,Synchronization,Linked List,Html Lists,我们有两个离线系统,通常无法相互通信。两个系统都维护相同的有序项目列表。他们很少能够相互通信以同步列表 项目用修改时间戳标记以检测编辑。项目由UUID标识,以避免插入新项目时发生冲突(与使用自动递增整数相反)。同步时,检测到新UUID并将其复制到其他系统。删除也同样如此 上面的数据结构对于无序列表来说很好,但是我们如何处理排序呢?如果我们添加了一个整数“rank”,则在插入一个新项时需要重新编号(因此,由于只有1次插入,因此需要同步所有后续项)。或者,我们可以使用分数等级(使用前一项和后一项的等
编辑:我们需要能够处理移动一个现有的项目到不同的位置太 您可以为每个项目添加两个字段-“创建时间戳”和“插入之后”(包含插入新项目之后的项目id)。同步列表后,发送所有新项目。这些信息足以让您在另一边构建列表 接收到新添加的项目列表后,执行以下操作(在接收端):按创建时间戳排序,然后逐个进行排序,并使用“插入后”字段将新项目添加到适当的位置 如果一个项目A被添加,然后B在A之后添加,然后A被删除,您可能会遇到麻烦。如果可能发生这种情况,您还需要同步(基本上同步自上次同步以来列表上发生的操作,而不仅仅是当前列表的内容)。它基本上是一种日志传送形式。您可以看看“镜头”,这是一种双向编程概念。
例如,我的“匹配镜头”解决了您的问题,如中所述。我认为这里合适的数据结构是。为了维护统计树,您还需要维护子树的大小以及其他数据,大小字段有助于根据需要轻松查找元素。所有操作,如排名、删除、更改位置、插入都是
O(logn)
我认为您可以在这里尝试某种事务性方法。例如,您不实际删除项目,而是将其标记为删除,并仅在同步期间提交更改。我不确定应该选择哪种数据类型,这取决于您希望哪种操作更有效率(插入、删除、搜索或迭代)
让我们在两个系统上都有以下初始状态:
|1| |2|
--- ---
|A| |A|
|B| |B|
|C| |C|
|D| |D|
|1 | |2 |
------------ --------------
|A | |A |
|B[deleted]| |B |
|C | |BC[inserted]|
|D | |C |
|D |
之后,第一个系统将元素A
标记为删除,第二个系统在B
和C
之间插入元素BC
:
|1| |2|
--- ---
|A| |A|
|B| |B|
|C| |C|
|D| |D|
|1 | |2 |
------------ --------------
|A | |A |
|B[deleted]| |B |
|C | |BC[inserted]|
|D | |C |
|D |
两个系统在考虑本地变化的情况下继续处理,系统1忽略元素B
,系统2将元素BC
视为正常元素
同步发生时:
|1| |2|
--- ---
|A| |A|
|B| |B|
|C| |C|
|D| |D|
|1 | |2 |
------------ --------------
|A | |A |
|B[deleted]| |B |
|C | |BC[inserted]|
|D | |C |
|D |
据我所知,每个系统都从其他系统接收列表快照,并且两个系统都冻结处理,直到同步完成
因此,每个系统依次迭代接收到的快照和本地列表,并在“提交事务”之后将更改写入本地列表(根据修改后的时间戳解决可能的冲突),最终应用所有本地更改并擦除有关更改的信息。
例如,对于系统1:
|1 pre-sync| |2-SNAPSHOT | |1 result|
------------ -------------- ----------
|A | <the same> |A | |A |
|B[deleted]| <delete B> |B |
<insert BC> |BC[inserted]| |BC |
|C | <same> |C | |C |
|D | <same> |D | |D |
| 1预同步| 2快照| 1结果|
------------ -------------- ----------
|A | | A | | A|
|B[删除]| | B|
|BC[插入]| | BC|
|C | | C | | C|
|D | | D | | D|
系统唤醒并继续处理
项目按插入顺序排序,移动可以实现同时删除和插入。此外,我认为可以不传输整个列表,而只传输实际修改的项目列表。我认为,大体上,可能与您在这里描述的问题有关。例如,考虑实时协同文本编辑的问题。p>
我们基本上有一个需要保持同步的项目(单词)排序列表,可以在列表中随机添加/修改/删除。我看到的唯一主要区别是列表修改的周期性。(你说这种情况不经常发生)
运营转型确实在该领域得到了很好的研究。我能找到一些指点和介绍。此外,尽管Google Wave存在诸多问题,但他们实际上在运营转型领域取得了重大进展。检查。关于这个问题,有相当多的文献可供查阅。看看这个,看看周围
另一个让我印象深刻的相似之处是文本编辑器中使用的数据结构。
因此,如果您有一个操作日志,比如说,“删除索引5”,“将索引6修改为ABC”,“插入索引8”,那么您现在可能需要做的是将更改日志从系统a传输到系统B,然后在另一个系统上按顺序重建操作