面试题答案
一键面试1. CouchDB检测冲突的方式
CouchDB 使用版本号来检测冲突。每个文档都有一个 _rev
字段,每次文档被修改时,_rev
的值都会更新。当多个客户端同时尝试修改同一文档时,它们最初获取到的 _rev
值是相同的。但当其中一个客户端成功提交修改后,文档的 _rev
会更新。此时,其他客户端再尝试提交修改时,CouchDB 会比较客户端提供的 _rev
值与服务器上当前文档的 _rev
值。如果两者不一致,就判定发生了冲突。
2. CouchDB处理冲突的方式
- 自动处理:CouchDB 会将冲突的文档保存为冲突版本,在文档的
_conflicts
数组中记录冲突的_rev
版本号。每个冲突版本都可以在_revisions
字段的conflicts
子数组中找到。 - 手动解决:开发人员可以通过读取
_conflicts
数组中的信息,手动选择保留哪个版本,或者通过合并各版本的内容来解决冲突。例如,可以根据业务逻辑决定保留最新修改的版本,或者合并不同版本中不冲突的部分。
3. 实际项目中解决冲突的示例
在一个多人协作的文档编辑项目中,多个用户可能同时编辑同一个文档。假设文档是一篇文章,用户 A 在本地修改了文章的标题,用户 B 在本地修改了文章的正文部分,然后两人同时提交修改。
解决步骤
- 检测冲突:当用户 A 先提交成功后,文档的
_rev
更新。用户 B 提交时,CouchDB 检测到_rev
不一致,判定冲突,将用户 B 的修改作为冲突版本保存。 - 手动合并:在应用层面,我们通过代码读取文档的所有冲突版本,解析出用户 A 修改的标题和用户 B 修改的正文,然后将两者合并成一个新的版本,覆盖原文档。代码示例(以Python和CouchDB-Python库为例):
from couchdb import Server
# 连接CouchDB服务器
server = Server('http://localhost:5984')
db = server['your_database']
# 获取文档
doc_id = 'your_document_id'
doc = db[doc_id]
# 处理冲突
if '_conflicts' in doc:
conflict_revs = doc['_conflicts']
new_doc = {}
for rev in conflict_revs:
conflict_doc = db.get(doc_id, rev=rev)
# 假设标题在 'title' 字段,正文在 'content' 字段
if 'title' in conflict_doc:
new_doc['title'] = conflict_doc['title']
if 'content' in conflict_doc:
new_doc['content'] = conflict_doc['content']
# 保存合并后的文档
new_doc['_id'] = doc_id
new_doc['_rev'] = doc['_rev']
db.save(new_doc)
通过这种方式,既保留了不同用户的有效修改,又解决了冲突问题。