面试题答案
一键面试设计思路
- 版本号管理:CouchDB 每个文档都有一个
_rev
字段,每次文档更新时,该版本号会自动递增。在应用程序中,读取文档时获取_rev
。 - 乐观锁机制:在更新文档时,将获取到的
_rev
作为参数传递给更新请求。CouchDB 只会在文档当前的_rev
与请求中的_rev
匹配时才执行更新,否则返回冲突错误。 - 事务处理:对于多步骤事务,可将相关操作封装在一个函数中。在每个步骤执行前检查文档
_rev
,如果_rev
发生变化,说明其他操作已修改文档,需重新读取文档并获取新的_rev
再继续。 - 文档间关联更新:当更新涉及多个关联文档时,按顺序依次更新每个文档,并在每次更新时传递正确的
_rev
。若某个文档更新失败,需回滚之前已成功更新的文档。
关键代码示例(Node.js 与 nano 库操作 CouchDB)
- 安装依赖
npm install nano
- 代码示例
const nano = require('nano')('http://localhost:5984');
const dbName = 'your_database_name';
// 获取文档
async function getDocument(docId) {
try {
const db = nano.db.use(dbName);
const doc = await db.get(docId);
return doc;
} catch (err) {
console.error('Error getting document:', err);
}
}
// 更新文档
async function updateDocument(docId, data, rev) {
try {
const db = nano.db.use(dbName);
const updatedDoc = {...data, _id: docId, _rev: rev };
const result = await db.insert(updatedDoc);
return result;
} catch (err) {
if (err.status === 409) {
console.error('Conflict. Document has been updated by another process.');
} else {
console.error('Error updating document:', err);
}
}
}
// 示例多步骤事务
async function multiStepTransaction() {
const docId = 'your_document_id';
const doc = await getDocument(docId);
if (!doc) return;
// 步骤 1:修改文档数据
const newData = { ...doc, key: 'new_value' };
// 步骤 2:更新文档
const result = await updateDocument(docId, newData, doc._rev);
if (result) {
console.log('Document updated successfully:', result);
}
}
multiStepTransaction();
此代码通过获取文档、传递正确的 _rev
进行更新,实现基于 CouchDB 文档版本号的更新机制,确保数据一致性。在实际复杂业务中,还需处理更复杂的错误情况和事务回滚逻辑。