是否有描述两个 Couch 之间复制如何工作的技术文档?
CouchDB 复制的基本概述是什么?它有哪些值得注意的特点?
不幸的是,没有描述复制协议(protocol)的详细文档。只有 CouchDB 内置的引用实现,以及 Filipe Manana 对其的重写,这可能会成为 future 的新实现。
然而,这是一般的想法:
关键点
如果您了解 Git,那么您就会知道 Couch 复制的工作原理。 复制与使用 Git 等分布式源代码管理器进行推送或 pull 非常相似。
CouchDB 复制没有自己的协议(protocol)。 复制器只是作为客户端连接到两个数据库,然后从一个数据库读取并写入另一个数据库。推送复制是读取本地数据和更新远程数据库; pull 复制反之亦然。
有趣的事实 1 : 复制器实际上是一个独立的 Erlang 应用程序,在它自己的进程中。它连接到两个沙发,然后从其中一个读取记录并将它们写入另一个。 趣闻2 : CouchDB 无法知道谁是普通客户端,谁是复制者(更不用说复制是推还是 pull )。这一切看起来都像客户端连接。他们中的一些人阅读记录。他们中的一些人写了记录。 一切都源于数据模型
复制算法是微不足道的,无趣的。训练有素的猴子可以设计它。这很简单,因为聪明的是数据模型,它具有以下有用的特征:
CouchDB 中的每条记录都完全独立于所有其他记录。如果你想做一个 JOIN
那就太糟糕了或事务,但如果您想编写一个复制器,那就太棒了。只需弄清楚如何复制一条记录,然后对每条记录重复该操作。 像 Git 一样,记录有一个链表修订历史。记录的修订 ID 是其自身数据的校验和。后续修订 ID 是以下各项的校验和:新数据,加上前一数据的修订 ID。 除了应用程序数据 ( {"name": "Jason", "awesome": true}
) 之外,每条记录都存储了所有以前的修订 ID 的演化时间线。
练习:花点时间安静地反射(reflection)。考虑任意两条不同的记录,A 和 B。如果 A 的修订 ID 出现在 B 的时间线中,那么 B 肯定是从 A 演变而来的。现在考虑 Git 的快进 merge 。你听到了吗?那是你的思想被吹走的声音。 Git 并不是一个真正的线性列表。当一个 parent 有多个 child 时,它有 fork 。 CouchDB 也有。
练习:比较两个不同的记录,A 和 B。A 的修订 ID 没有出现在 B 的时间线中;但是,A 和 B 的时间线中都有一个修订 ID C。因此,A 不是从 B 进化而来的。B 也不是从 A 进化而来的。相反,A 和 B 有一个共同的祖先 C。在 Git 中,这是一个“ fork ”。在 CouchDB 中,这是一个“冲突”。 在 Git 中,如果两个 child 都继续独立开发他们的时间线,那就太酷了。 Forks 完全支持这一点。 在 CouchDB 中,如果两个 child 都继续独立开发他们的时间线,那也很酷。冲突完全支持这一点。 趣闻3: CouchDB“冲突”不对应于 Git“冲突”。 Couch 冲突是不同的修订历史,Git 称之为“ fork ”。出于这个原因,CouchDB 社区用无声的 n 发音“冲突”:“co-flicked”。 当一个 child 有多个 parent 时,Git 也有 merge 。 CouchDB 也有这种情况。
在数据模型中,没有 merge 。 客户端只需将一个时间线标记为已删除,然后继续使用唯一存在的时间线。 在应用中,感觉就像是 merge 。 通常,客户端以特定于应用程序的方式 merge 来自每个时间线的数据。然后它将新数据写入时间线。在Git中,这就像将分支A的更改复制粘贴到分支B,然后提交到分支B并删除分支A。数据 merge 了,但没有git merge
. 这些行为是不同的,因为在 Git 中,时间线本身很重要;但在 CouchDB 中,数据很重要,时间线是附带的——它只是为了支持复制。这就是 CouchDB 的内置修订不适合像 wiki 页面一样存储修订数据的原因之一。 最后的笔记
这篇文章中至少有一个句子(可能是这个)是完整的 BS。