面试题答案
一键面试1. 维持可用性
- 多副本机制:CouchDB采用多副本策略。在正常情况下,数据会被复制到多个节点。当网络分区发生时,各个分区内只要有包含副本数据的节点,就能对外提供读服务。例如,假设有一个3节点的CouchDB集群,网络分区将其分为两个部分,一个分区有2个节点,另一个有1个节点。有2个节点的分区可继续提供读写服务,而只有1个节点的分区能提供读服务(前提是该节点有数据副本)。
- 本地响应:每个CouchDB节点在本地维护数据。当网络分区出现,节点能直接在本地响应客户端的读请求,因为数据已经存储在本地磁盘或内存缓存中。对于写请求,节点会在本地记录这些变更,并将其标记为待同步状态,从而维持一定程度的可用性。
2. 数据同步以保证最终一致性
- 版本向量(Version Vectors):CouchDB使用版本向量来跟踪文档的版本。每个文档都有一个修订号(
_rev
),每次文档修改,修订号都会更新。当网络分区恢复后,节点间通过交换版本向量信息,能识别出哪些文档需要更新。例如,节点A上文档的_rev
为1 - a,节点B上同一文档的_rev
为1 - b,说明这两个版本是在不同分支上修改的,需要进行合并。 - 冲突解决算法:
- 最后写入者获胜(LWW, Last Write Wins):在简单场景下,CouchDB采用最后写入者获胜原则。如果两个节点在分区期间对同一文档进行了修改,当分区恢复时,具有更新修订号的文档版本将被保留。例如,节点A在
10:00
修改了文档,修订号为_rev: 2 - a
,节点B在10:05
修改了同一文档,修订号为_rev: 2 - b
,那么当分区恢复后,_rev: 2 - b
对应的文档版本将被保留。 - 手动合并:对于复杂的冲突情况,CouchDB允许开发者手动合并冲突文档。CouchDB会将冲突版本的文档以一种特殊格式存储,开发者可以编写代码来解析这些冲突版本,并决定如何合并它们。例如,对于一个包含用户信息的文档,一个版本更新了用户地址,另一个版本更新了用户电话,开发者可以编写代码将这两个修改合并到一个新的文档版本中。
- 最后写入者获胜(LWW, Last Write Wins):在简单场景下,CouchDB采用最后写入者获胜原则。如果两个节点在分区期间对同一文档进行了修改,当分区恢复时,具有更新修订号的文档版本将被保留。例如,节点A在
- 复制协议:
- 主动复制:当网络分区恢复后,CouchDB节点会主动发起复制操作。每个节点会与其他节点建立连接,并根据版本向量信息,请求那些自己没有的最新文档版本。例如,节点A发现节点B有更新版本的文档,就会向节点B请求该文档的最新修订版本。
- 双向复制:复制过程是双向的。节点之间会相互交换数据,确保所有节点最终拥有一致的数据副本。在复制过程中,会根据上述冲突解决算法来处理可能出现的冲突,从而保证数据的最终一致性。